Skip to content

Commit 2e5715c

Browse files
committed
safe delete branch
1 parent 75244c3 commit 2e5715c

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
@@ -1606,7 +1606,11 @@ export class Git {
16061606
async rev_list(
16071607
repoPath: string,
16081608
ref: string,
1609-
options?: { all?: boolean; maxParents?: number },
1609+
options?: {
1610+
all?: boolean;
1611+
maxParents?: number;
1612+
maxResults?: number;
1613+
},
16101614
): Promise<string[] | undefined> {
16111615
const params = ['rev-list'];
16121616
if (options?.all) {
@@ -1617,6 +1621,10 @@ export class Git {
16171621
params.push(`--max-parents=${options.maxParents}`);
16181622
}
16191623

1624+
if (options?.maxResults != null) {
1625+
params.push(`-n ${options.maxResults}`);
1626+
}
1627+
16201628
const rawData = await this.git<string>(
16211629
{ cwd: repoPath, errors: GitErrorHandling.Ignore },
16221630
...params,
@@ -1889,6 +1897,10 @@ export class Git {
18891897
return data.length === 0 ? undefined : data.trim();
18901898
}
18911899

1900+
async update_ref(repoPath: string, ...args: string[]): Promise<void> {
1901+
await this.git<string>({ cwd: repoPath }, 'update-ref', ...args);
1902+
}
1903+
18921904
async show<TOut extends string | Buffer>(
18931905
repoPath: string | undefined,
18941906
fileName: string,

src/env/node/git/localGitProvider.ts

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

1266-
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1267-
12681266
if (options.remote) {
12691267
const trackingBranches = localBranches.filter(b => b.upstream != null);
12701268
if (trackingBranches.length !== 0) {
@@ -1273,17 +1271,43 @@ export class LocalGitProvider implements GitProvider, Disposable {
12731271
);
12741272

12751273
for (const [remote, branches] of branchesByOrigin.entries()) {
1276-
await this.git.push(repoPath, {
1277-
delete: {
1278-
remote: remote,
1279-
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1280-
},
1274+
const remoteCommitByBranch: Map<string, string> = {};
1275+
branches.forEach(async b => {
1276+
remoteCommit = await this.git.rev_list(repoPath, `refs/remotes/${remote}/${b.ref}`, {
1277+
maxResults: 1,
1278+
});
1279+
remoteCommitByBranch[b.ref] = remoteCommit;
12811280
});
1281+
1282+
await this.git.branch(
1283+
repoPath,
1284+
'--delete',
1285+
'--remotes',
1286+
...branches.map((b: GitBranchReference) => `${remote}/${b.ref}`),
1287+
);
1288+
1289+
try {
1290+
await this.git.branch(repoPath, ...args, ...branches.map((b: GitBranchReference) => b.ref));
1291+
await this.git.push(repoPath, {
1292+
delete: {
1293+
remote: remote,
1294+
branches: branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
1295+
},
1296+
});
1297+
} catch (ex) {
1298+
// If it fails, restore the remote branches
1299+
remoteCommitByBranch.forEach(async (branch, commit) => {
1300+
await this.git.update_ref(repoPath, `refs/remotes/${remote}/${branch}`, commit);
1301+
await this.git.branch__set_upstream(repoPath, branch, remote, branch);
1302+
});
1303+
throw ex;
1304+
}
12821305
}
12831306
}
12841307
}
12851308
}
12861309

1310+
const remoteBranches = branches.filter((b: GitBranchReference) => b.remote);
12871311
if (remoteBranches.length !== 0) {
12881312
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
12891313

0 commit comments

Comments
 (0)