Repository navigation
fix(server): background status fetch no longer breaks a concurrent git pull - #26568
juliusmarminge wants to merge 5 commits into
Conversation
…HEAD The background upstream status fetch rewrites .git/FETCH_HEAD, so a poll that overlaps the user's own `git pull` makes it fail with "Cannot fast-forward to multiple branches". This test fails on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pull The background upstream status poll rewrote .git/FETCH_HEAD. Git writes that file without a lock, so a poll that overlapped the user's own `git pull` left it with several for-merge lines and the pull failed with "Cannot fast-forward to multiple branches". The poll only needs refs/remotes/* updated, so pass --no-write-fetch-head (Git 2.29+). Fixes #26560 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…EAD on its flag Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Background status fetches stop writing FETCH_HEAD, reducing interference with concurrent Git pulls. Status calculations still use upstream references, and explicit fetch operations are unchanged. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
The automated pipeline stopped on this pull request and will not merge it: someone else pushed to fix/issue-26560 (head is now 97adfec); the pipeline does not build on commits it did not review It stays open for a person to finish or close. |
Dismissing prior approval to re-evaluate 444ac38
Problem
The background status poll runs
git fetchabout every 30s, and that fetch rewrites.git/FETCH_HEAD. Git writes that file without a lock. When the poll overlaps a user's owngit pullin the same checkout, both fetches append for-merge lines, and the pull fails withfatal: Cannot fast-forward to multiple branches.Reproduced on main 125b619 with Git 2.43: the status fetch's exact arguments ran in a loop whilegit pull --ff-onlyran against a moving remote, and 12 of 300 pulls failed that way.Change
fetchRemoteForStatusnow passes--no-write-fetch-head. The poll only needsrefs/remotes/*to compute ahead/behind, and nothing reads the FETCH_HEAD it wrote. User-initiated fetches and pulls keep writing FETCH_HEAD as before. The flag needs Git 2.29 or newer. On older Git this background fetch fails and goes through the existing failure backoff.Scope and approval
Fixes #26560
Verification
New test
leaves FETCH_HEAD to the user's own pulls in background upstream fetchesinapps/server/src/vcs/GitVcsDriverCore.test.ts:AssertionError: background status fetch wrote .git/FETCH_HEAD, which an overlapping \git pull` merges from: expected true to equal false`behindCountis still 1, so the fetch still runs.GitVcsDriverCore.test.ts: 172/172 pass.vp run check:changedpasses.Runtime transcript (Git 2.43, Linux): a background loop runs the status fetch's exact command while
git pull --ff-onlyruns 300 times against a remote that gains a commit before each pull.Cannot fast-forward to multiple branchesfailuresDriver: repro2.sh. Output: transcript.txt
Server-only, no visible surface, so there are no captures.
Not checked: the reporter's Apple Git 2.54 on macOS, and Git older than 2.29. The changed code is platform-independent server code.
Model and harness: Claude Opus 5.5 (lead, test, implementation, review B) and GPT-6.1 Sol (review A), in Claude Code and Codex via T3 Code.
🤖 Generated with Claude Code