Skip to content

[finding] git worktree add -b can fail writing upstream config and leave the branch created but no worktree — the recipe's own half-state, and .git/config is shared like the stash #13052

Description

@os-elon

Observed once while following the worktree-first recipe in CLAUDE.md / AGENTS.md, in a container running several dev agents against the same primary checkout. Recording it because the failure leaves a half state the recipe does not mention, and because its cause is the shared-state family AGENTS.md already documents — one namespace further than the current wording reaches.

What happened

The prescribed command:

git fetch origin main && git worktree add ../objectstack-issue-NNNN -b claude/issue-NNNN-slug origin/main

printed the fetch result and then:

error: unable to write upstream branch configuration
hint:
hint: After fixing the error cause you may try to fix up
hint: the remote tracking information by invoking:
hint:   git branch --set-upstream-to=origin/refs/heads/main

and exited non-zero. Measured immediately afterwards:

  • git branch --list 'claude/issue-NNNN*'the branch exists, pointing at the fetched tip;
  • ls -d ../objectstack-issue-NNNNno such directory; git worktree list does not name it.

So the branch was created and the worktree was not. A naive retry of the same command then fails differently (branch already exists), which reads as a second, unrelated problem rather than the residue of the first.

Why it matters more than one lost minute

  1. It is a half state in the very first step of the standard recipe. Every dev agent runs exactly this line before its first edit. An agent that reads the error as "the whole command failed" and retries gets a confusing second error; one that reads it as "the worktree exists" starts editing the shared primary checkout — which is the thing worktree-first exists to prevent.

  2. The orphan branch is not cheap to clean up here. Agent seats cannot delete their own remote branches (there is an open finding about that), and a local orphan branch is invisible to anything that looks at the remote.

  3. The recipe's recovery is not obvious. What worked: git branch -D the orphan, then re-run with --no-track, which skips the config write entirely:

    git worktree add --no-track -b claude/issue-NNNN-slug ../objectstack-issue-NNNN origin/main
    

The cause is a shared namespace the docs stop one short of

CLAUDE.md says a worktree isolates the checkout and exactly four ref namespaces, and names refs/stash and refs/remotes/* as the shared ones that bite. .git/config is shared the same way — every linked worktree reads and writes the one file in the common git dir — and -b with default tracking writes to it (branch.NAME.remote / branch.NAME.merge). Git takes a lock on that file, so a sibling worktree writing config in the same instant is a plausible loser-of-the-race, and the loser here fails after creating the branch.

That makes this the same species as the stash incident, in a namespace the current wording does not enumerate: config, not refs.

Suggested remedies, cheapest first

  • Docs: add .git/config to the shared-namespace list in AGENTS.md §9 / CLAUDE.md, and change the prescribed recipe to git worktree add --no-track -b .... Nothing in the agent flow needs the upstream tracking — the first push is git push -u origin BRANCH, which sets it, in the agent's own worktree, one command later.
  • Recipe hardening: if the recipe stays as it is, add one line about the half state and its cleanup, because the error text does not mention that a branch was created.
  • I did not attempt to reproduce it deliberately (it is a race, and reproducing it means arranging concurrent config writes), so treat the cause as strongly-indicated rather than proven. The half state itself is directly measured, and does not depend on the cause being right.

Found while implementing #12962; not fixed there — out of scope for that card.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions