Skip to content

Fix .git/config lock race when creating worktrees concurrently#794

Merged
selfcontained merged 1 commit into
mainfrom
agt_75b415f48f46/job-test-enforcer-b83bd6d5
Jul 18, 2026
Merged

Fix .git/config lock race when creating worktrees concurrently#794
selfcontained merged 1 commit into
mainfrom
agt_75b415f48f46/job-test-enforcer-b83bd6d5

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

Problem

git worktree add -b <branch> <path> origin/main auto-writes branch tracking config (branch.<name>.{remote,merge}) into .git/config, which takes the repo-wide config lock. When two worktree agents are created against the same repo at the same instant, the second worktree add loses the lock race:

error: could not lock config file .git/config: File exists
error: unable to write upstream branch configuration

git treats this as fatal (exit 255) and fails the whole command, so POST /api/v1/agents returns a 500. Surfaced as an intermittent E2E failure in worktree.spec.ts (whose setup creates several worktree agents in parallel) that aborted the E2E run. Root-caused from the preserved Playwright trace (500 body contained the config-lock error).

Fix

Pass --no-track to git worktree add so it no longer writes tracking config. That removes the only .git/config write from the non-idempotent command, so it can't lose the race. Upstream is still set explicitly right after via git branch --set-upstream-to (unchanged), which already tolerates exit 1/128 — git returns exit 1 when that write hits a contended lock, and a missing upstream degrades correctly to origin/<base> in worktree-status.ts and base-ref.ts, so creation succeeds either way. The end-state upstream (origin/main) is identical to git's auto-track output.

Tests

  • worktree add carries --no-track and sets upstream explicitly.
  • Creation succeeds when the upstream write is blocked by a contended config lock (exit 1 + lock stderr) — matches real git behavior (verified against git 2.50.1: exit 1, not 255).
  • Updated the two existing worktree add command assertions for the new --no-track flag.

Validation

  • pnpm run check
  • pnpm run test ✓ (server 2281 pass / 8 skip, +2 net new tests)
  • pnpm run test:e2e ✓ (168 passed / 13 skipped; previously-failing worktree.spec.ts:480 now green)

A review agent flagged that an earlier draft's retry loop was dead code (git returns exit 1, which allowedExitCodes swallows before any throw); this PR drops the retry in favor of the deterministic --no-track fix per that feedback.

🤖 Generated with Claude Code

`git worktree add -b <branch> <path> origin/main` auto-writes branch
tracking config (branch.<name>.{remote,merge}) into .git/config, which
takes the repo-wide config lock. When two worktree agents are created
against the same repo at the same instant, the second `worktree add`
loses the lock race and dies:

    error: could not lock config file .git/config: File exists
    error: unable to write upstream branch configuration

git treats that as fatal (exit 255) and fails the whole command, so the
agent-create API returns a 500. Surfaced as an intermittent E2E failure
in worktree.spec.ts whose setup creates several worktree agents in
parallel.

Fix: pass --no-track to `git worktree add` so it no longer writes
tracking config — that removes the only .git/config write from the
non-idempotent command, so it can't lose the race. Upstream is still set
explicitly right after via `git branch --set-upstream-to` (unchanged),
which already tolerates exit 1/128; git returns exit 1 when that write
hits a contended lock, and a missing upstream degrades correctly to
origin/<base> in worktree-status and base-ref, so creation succeeds
either way.

Adds regression tests: `worktree add` carries --no-track, and creation
succeeds when the upstream write is blocked by a contended config lock
(exit 1 + lock stderr), matching real git behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@selfcontained
selfcontained merged commit 67fb3c8 into main Jul 18, 2026
1 check passed
@selfcontained
selfcontained deleted the agt_75b415f48f46/job-test-enforcer-b83bd6d5 branch July 18, 2026 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant