fix(desktop): worktree from origin/main should not set up upstream tracking

When "new worktree" branches off a remote-tracking ref like origin/main,
`git worktree add -b <branch> <dir> origin/main` auto-sets upstream
tracking (branch → origin/main), producing `branch:origin/main` in branch
listings. The user wants a standalone local branch — like `git checkout
origin/main && git checkout -b branch` — not one silently wired to the
remote. Add `--no-track` when the base is an `origin/` ref. Local branch
bases are unaffected (they never triggered tracking).
fix/verification-admin-route-recovery
ethernet 2026-07-14 18:05:00 -04:00
parent 07be37d996
commit 678b86df1c
2 changed files with 44 additions and 1 deletions

View File

@ -262,3 +262,39 @@ test('addWorktree: base param branches off a specified local branch', async () =
fs.rmSync(dir, { recursive: true, force: true })
}
})
test('addWorktree: base origin/main does not set up upstream tracking', async () => {
// Two repos: a bare "remote" and a clone, so origin/main resolves as a
// remote-tracking ref — the condition that triggers auto-tracking.
const remoteDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hermes-remote-'))
const cloneDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hermes-clone-'))
const git = (...args) => execFileSync('git', args, { cwd: cloneDir }).toString().trim()
try {
// Seed the remote with a commit on main.
execFileSync('git', ['init', '-b', 'main', remoteDir])
execFileSync('git', ['-C', remoteDir, 'commit', '--allow-empty', '-m', 'root'])
// Clone so origin/main exists as a remote-tracking ref.
execFileSync('git', ['clone', remoteDir, cloneDir])
const result = await addWorktree(cloneDir, { base: 'origin/main', branch: 'feature-branch', name: 'feature-branch' }, 'git')
assert.equal(result.branch, 'feature-branch')
// The new branch must NOT have an upstream — like `git checkout origin/main
// && git checkout -b feature-branch`, not `git worktree add -b … origin/main`.
let hasUpstream = true
try {
execFileSync('git', ['-C', result.path, 'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'])
} catch {
hasUpstream = false
}
assert.equal(hasUpstream, false)
} finally {
fs.rmSync(remoteDir, { recursive: true, force: true })
fs.rmSync(cloneDir, { recursive: true, force: true })
}
})

View File

@ -265,8 +265,15 @@ async function addWorktree(repoPath, options, gitBin) {
} catch {
// The fetch isn't mandatory, but it would be nice to do if possible.
// If it's not possible, just use the local ref of the remote branch.
// If it doesn't exist locally, we'll get an error anyways
// If it doesn't exist locally, we'll get an error
}
// When branching off a remote-tracking ref, git auto-sets up tracking
// (e.g. `new-branch` → tracks `origin/main`). The user almost certainly
// wants a standalone local branch — like `git checkout origin/main &&
// git checkout -b new-branch` — not a branch silently wired to the
// remote's upstream. `--no-track` prevents that.
args.push('--no-track')
}
args.push(base)