Skip to content

Commit b03d658

Browse files
committed
safe delete branch
1 parent 9d52792 commit b03d658

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

src/env/node/git/git.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,11 @@ export class Git {
16091609
async rev_list(
16101610
repoPath: string,
16111611
ref: string,
1612-
options?: { all?: boolean; maxParents?: number },
1612+
options?: {
1613+
all?: boolean;
1614+
maxParents?: number;
1615+
maxResults?: number;
1616+
},
16131617
): Promise<string[] | undefined> {
16141618
const params = ['rev-list'];
16151619
if (options?.all) {
@@ -1620,6 +1624,10 @@ export class Git {
16201624
params.push(`--max-parents=${options.maxParents}`);
16211625
}
16221626

1627+
if (options?.maxResults != null) {
1628+
params.push(`-n ${options.maxResults}`);
1629+
}
1630+
16231631
const rawData = await this.git<string>(
16241632
{ cwd: repoPath, errors: GitErrorHandling.Ignore },
16251633
...params,
@@ -1885,6 +1893,10 @@ export class Git {
18851893
return data.length === 0 ? undefined : data.trim();
18861894
}
18871895

1896+
async update_ref(repoPath: string, ...args: string[]): Promise<void> {
1897+
await this.git<string>({ cwd: repoPath }, 'update-ref', ...args);
1898+
}
1899+
18881900
async show<TOut extends string | Buffer>(
18891901
repoPath: string | undefined,
18901902
fileName: string,

src/env/node/git/localGitProvider.ts

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

1287-
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1288-
12891287
if (options.remote) {
12901288
const trackingBranches = localBranches.filter(b => b.upstream != null);
12911289
if (trackingBranches.length !== 0) {
@@ -1294,17 +1292,43 @@ export class LocalGitProvider implements GitProvider, Disposable {
12941292
);
12951293

12961294
for (const [remote, branches] of branchesByOrigin.entries()) {
1297-
await this.git.push(repoPath, {
1298-
delete: {
1299-
remote: remote,
1300-
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1301-
},
1295+
const remoteCommitByBranch: Map<string, string> = {};
1296+
branches.forEach(async b => {
1297+
remoteCommit = await this.git.rev_list(repoPath, `refs/remotes/${remote}/${b.ref}`, {
1298+
maxResults: 1,
1299+
});
1300+
remoteCommitByBranch[b.ref] = remoteCommit;
13021301
});
1302+
1303+
await this.git.branch(
1304+
repoPath,
1305+
'--delete',
1306+
'--remotes',
1307+
...branches.map((b: GitBranchReference) => `${remote}/${b.ref}`),
1308+
);
1309+
1310+
try {
1311+
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1312+
await this.git.push(repoPath, {
1313+
delete: {
1314+
remote: remote,
1315+
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1316+
},
1317+
});
1318+
} catch (ex) {
1319+
// If it fails, restore the remote branches
1320+
remoteCommitByBranch.forEach(async (branch, commit) => {
1321+
await this.git.update_ref(repoPath, `refs/remotes/${remote}/${branch}`, commit);
1322+
await this.git.branch__set_upstream(repoPath, branch, remote, branch);
1323+
});
1324+
throw ex;
1325+
}
13031326
}
13041327
}
13051328
}
13061329
}
13071330

1331+
const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
13081332
if (remoteBranches.length !== 0) {
13091333
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
13101334

0 commit comments

Comments
 (0)