mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
An existing develop outranks a main-pointing origin/HEAD
Cursor Bugbot's remaining round-1 finding held for the current code too: in a git-flow repo whose platform default was never flipped off main, a feature branch without an upstream picked origin/HEAD's main over the develop branch features actually merge to, dragging the develop-vs-main divergence into scan targets. develop now sits between the upstream signal and origin/HEAD in the candidate order; repos without a develop branch are unaffected. Failing-first test covers the exact shape (develop exists, origin/HEAD -> main). Prepared with AI assistance (Claude Code), directed by @pbakaus. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Code
parent
b9d294b29c
commit
e82653965c
@@ -129,8 +129,13 @@ function gitSignals(cwd) {
|
||||
// The upstream tracks the actual merge target, so its own rev wins over
|
||||
// a possibly stale local branch of the same name.
|
||||
if (upstream) addCandidate(upstream.name, [upstream.rev]);
|
||||
// A develop branch marks a git-flow repo where features merge to develop
|
||||
// even when the platform default (origin/HEAD) was never flipped off
|
||||
// main; an existing develop therefore outranks the remote default. This
|
||||
// is #302's own repro shape, and repos without develop are unaffected.
|
||||
addCandidate('develop', ['develop', 'origin/develop']);
|
||||
if (remoteHead) addCandidate(remoteHead.name, [remoteHead.name, remoteHead.rev]);
|
||||
for (const name of conventional) addCandidate(name, [name, `origin/${name}`]);
|
||||
for (const name of ['main', 'master']) addCandidate(name, [name, `origin/${name}`]);
|
||||
for (const c of candidates) {
|
||||
const rev = c.revs.find((r) => run(['rev-parse', '--verify', '--quiet', r]) !== null);
|
||||
if (rev) {
|
||||
|
||||
@@ -309,6 +309,31 @@ describe('gatherSignals', () => {
|
||||
assert.deepEqual(s.git.changedFiles, ['src/Hero.tsx']);
|
||||
});
|
||||
|
||||
it('an existing develop outranks a main-pointing origin/HEAD (#302)', async () => {
|
||||
const { execFileSync } = await import('node:child_process');
|
||||
const git = (...args) => execFileSync('git', args, { cwd: scratch, stdio: 'ignore' });
|
||||
git('init', '-q', '-b', 'main');
|
||||
git('config', 'user.email', 't@example.com');
|
||||
git('config', 'user.name', 'Test');
|
||||
write('src/App.tsx', 'export default 1;\n');
|
||||
git('add', '.');
|
||||
git('commit', '-qm', 'init');
|
||||
git('branch', '-q', 'develop');
|
||||
// Classic git-flow with the platform default never flipped off main.
|
||||
git('update-ref', 'refs/remotes/origin/main', 'main');
|
||||
git('symbolic-ref', 'refs/remotes/origin/HEAD', 'refs/remotes/origin/main');
|
||||
git('checkout', '-q', 'develop');
|
||||
git('checkout', '-q', '-b', 'feature/g');
|
||||
write('src/Hero.tsx', 'export const Hero = () => null;\n');
|
||||
git('add', '.');
|
||||
git('commit', '-qm', 'feature work');
|
||||
const s = await gatherSignals(scratch);
|
||||
// Features merge to develop here; picking origin/HEAD's main would drag
|
||||
// the develop-vs-main divergence into scan targets.
|
||||
assert.equal(s.git.base, 'develop');
|
||||
assert.deepEqual(s.git.changedFiles, ['src/Hero.tsx']);
|
||||
});
|
||||
|
||||
it('remote signals cannot bypass the integration-branch guard (#302)', async () => {
|
||||
const { execFileSync } = await import('node:child_process');
|
||||
const git = (...args) => execFileSync('git', args, { cwd: scratch, stdio: 'ignore' });
|
||||
|
||||
Reference in New Issue
Block a user