From 9f2564735b972a2d7d717346a42081dd255b74f9 Mon Sep 17 00:00:00 2001 From: KPal Date: Thu, 22 Oct 2026 18:46:28 +0100 Subject: [PATCH] fix: skip backports the release branch already has A fix backported by hand under a different patch cherry-picks as an empty commit, which failed the release as a conflict. Empty picks are now dropped and logged as already on the branch. --- scripts/release.ts | 9 ++++++--- test/release/release.test.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/release.ts b/scripts/release.ts index bc6c876a4..b6f45419a 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -126,14 +126,17 @@ export const release = (cwd: string, { type, bumpEngine }: Options, deps: Deps) continue; } git('checkout', '-q', '--detach', head); - if (!ok('cherry-pick', '-x', sha)) { + + // a fix backported by hand under a different patch applies as nothing, so it's dropped + if (!ok('cherry-pick', '-x', '--empty=drop', sha)) { git('cherry-pick', '--abort'); throw new Error( `Backport of #${number} conflicts on ${branch}; backport it by hand or remove its "${BACKPORT_LABEL}" label` ); } - head = git('rev-parse', 'HEAD'); - console.log(`Backported #${number}`); + const picked = git('rev-parse', 'HEAD'); + console.log(picked === head ? `Skipping #${number}: already on ${branch}` : `Backported #${number}`); + head = picked; } head = withEngine(head); if (!git('rev-list', '-1', `${latest}..${head}`)) { diff --git a/test/release/release.test.ts b/test/release/release.test.ts index b0c99b248..e284824b6 100644 --- a/test/release/release.test.ts +++ b/test/release/release.test.ts @@ -91,6 +91,15 @@ describe('release', function () { expect(refs()).to.equal(before); }); + it('skips a backport the branch already has under a different patch', () => { + run('minor'); + picks = [{ number: 9, title: 'fix: b', sha: land('main', 'b.txt', 'b') }]; + land('release-2.34', 'b.txt', 'old'); + land('release-2.34', 'b.txt', 'b'); + expect(run('patch')).to.deep.equal({ tag: 'v2.34.1', released: true }); + expect(sh(remote, 'show', 'release-2.34:b.txt')).to.equal('b'); + }); + it('does nothing when there is nothing to release', () => { run('minor'); const before = refs();