Skip to content

Commit 3f2d168

Browse files
committed
safe delete branch
# Conflicts: # src/env/node/git/git.ts
1 parent e8ff53b commit 3f2d168

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

src/env/node/git/git.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1622,7 +1622,12 @@ export class Git {
16221622
async rev_list(
16231623
repoPath: string,
16241624
ref: string,
1625-
options?: { all?: boolean; maxParents?: number; since?: string },
1625+
options?: {
1626+
all?: boolean;
1627+
maxParents?: number;
1628+
maxResults?: number;
1629+
since?: string;
1630+
},
16261631
): Promise<string[] | undefined> {
16271632
const params = ['rev-list'];
16281633
if (options?.all) {
@@ -1633,6 +1638,10 @@ export class Git {
16331638
params.push(`--max-parents=${options.maxParents}`);
16341639
}
16351640

1641+
if (options?.maxResults != null) {
1642+
params.push(`-n ${options.maxResults}`);
1643+
}
1644+
16361645
if (options?.since) {
16371646
params.push(`--since="${options.since}"`, '--date-order');
16381647
}
@@ -1902,6 +1911,10 @@ export class Git {
19021911
return data.length === 0 ? undefined : data.trim();
19031912
}
19041913

1914+
async update_ref(repoPath: string, ...args: string[]): Promise<void> {
1915+
await this.git<string>({ cwd: repoPath }, 'update-ref', ...args);
1916+
}
1917+
19051918
show(
19061919
repoPath: string,
19071920
options?: { cancellation?: CancellationToken; configs?: readonly string[] },

src/env/node/git/localGitProvider.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,8 +1298,6 @@ export class LocalGitProvider implements GitProvider, Disposable {
12981298
args.push('--force');
12991299
}
13001300

1301-
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1302-
13031301
if (options.remote) {
13041302
const trackingBranches = localBranches.filter(b => b.upstream != null);
13051303
if (trackingBranches.length !== 0) {
@@ -1308,17 +1306,43 @@ export class LocalGitProvider implements GitProvider, Disposable {
13081306
);
13091307

13101308
for (const [remote, branches] of branchesByOrigin.entries()) {
1311-
await this.git.push(repoPath, {
1312-
delete: {
1313-
remote: remote,
1314-
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1315-
},
1309+
const remoteCommitByBranch: Map<string, string> = {};
1310+
branches.forEach(async b => {
1311+
remoteCommit = await this.git.rev_list(repoPath, `refs/remotes/${remote}/${b.ref}`, {
1312+
maxResults: 1,
1313+
});
1314+
remoteCommitByBranch[b.ref] = remoteCommit;
13161315
});
1316+
1317+
await this.git.branch(
1318+
repoPath,
1319+
'--delete',
1320+
'--remotes',
1321+
...branches.map((b: GitBranchReference) => `${remote}/${b.ref}`),
1322+
);
1323+
1324+
try {
1325+
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1326+
await this.git.push(repoPath, {
1327+
delete: {
1328+
remote: remote,
1329+
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1330+
},
1331+
});
1332+
} catch (ex) {
1333+
// If it fails, restore the remote branches
1334+
remoteCommitByBranch.forEach(async (branch, commit) => {
1335+
await this.git.update_ref(repoPath, `refs/remotes/${remote}/${branch}`, commit);
1336+
await this.git.branch__set_upstream(repoPath, branch, remote, branch);
1337+
});
1338+
throw ex;
1339+
}
13171340
}
13181341
}
13191342
}
13201343
}
13211344

1345+
const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
13221346
if (remoteBranches.length !== 0) {
13231347
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
13241348

0 commit comments

Comments
 (0)