Skip to content

fix(server): background status fetch no longer breaks a concurrent git pull - #26568

Open
juliusmarminge wants to merge 5 commits into
mainfrom
fix/issue-26560
Open

juliusmarminge wants to merge 5 commits into
mainfrom
fix/issue-26560

Conversation

@juliusmarminge

Copy link
Copy Markdown
Member

Problem

The background status poll runs git fetch about every 30s, and that fetch rewrites .git/FETCH_HEAD. Git writes that file without a lock. When the poll overlaps a user's own git pull in the same checkout, both fetches append for-merge lines, and the pull fails with fatal: Cannot fast-forward to multiple branches. Reproduced on main 125b619 with Git 2.43: the status fetch's exact arguments ran in a loop while git pull --ff-only ran against a moving remote, and 12 of 300 pulls failed that way.

Change

fetchRemoteForStatus now passes --no-write-fetch-head. The poll only needs refs/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 fetches in apps/server/src/vcs/GitVcsDriverCore.test.ts:

    • Fails on main's implementation: AssertionError: background status fetch wrote .git/FETCH_HEAD, which an overlapping \git pull` merges from: expected true to equal false`
    • Passes with the fix, and behindCount is still 1, so the fetch still runs.
  • GitVcsDriverCore.test.ts: 172/172 pass. vp run check:changed passes.

  • Runtime transcript (Git 2.43, Linux): a background loop runs the status fetch's exact command while git pull --ff-only runs 300 times against a remote that gains a commit before each pull.

    Before (125b619) After (97adfec)
    Cannot fast-forward to multiple branches failures 12/300 0/300

    Driver: 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

juliusmarminge and others added 3 commits October 28, 2026 16:40
…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>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Oct 28, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 28, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 444ac38

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.

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The background status fetch adds --no-write-fetch-head and retains its existing options. A regression test checks that remote status detects one commit of divergence without creating .git/FETCH_HEAD.

Changes: Background status fetch

Layer / File(s) Summary
Fetch behavior and regression test
apps/server/src/vcs/GitVcsDriverCore.ts, apps/server/src/vcs/GitVcsDriverCore.test.ts
The background fetch adds --no-write-fetch-head. The test verifies that remote status reports one commit behind while .git/FETCH_HEAD remains absent.

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: t3dotgg

Merge Risk: Minimal · up to 444ac

The background status fetch is intended to leave user-initiated pulls’ FETCH_HEAD untouched. No merge-blocking issue is identified from the supplied evidence; normal checks remain appropriate.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title is concise, uses the conventional commit format, and clearly describes the main fix: preventing background status fetches from breaking concurrent Git pulls.
Description check Passed The description includes all required sections. It clearly explains the problem, change, scope, linked issue, focused tests, runtime verification, limitations, and agent details. It does not include a…
Linked Issues check Passed Issue #26560 requires the server background status fetch to avoid writing .git/FETCH_HEAD while still updating remote-tracking refs for ahead/behind status. The reviewed change adds `--no-write-fetc…
Out of Scope Changes check Passed The whole pull-request summary contains one server change to the background fetch and a focused regression test. The source comment update supports the same fetch behavior. The reviewed scope contains…
Full details: Description check

Explanation

The description includes all required sections. It clearly explains the problem, change, scope, linked issue, focused tests, runtime verification, limitations, and agent details. It does not include an explicit maintainer approval comment, but the description is otherwise complete and directly related to the change.

Full details: Linked Issues check

Explanation

Issue #26560 requires the server background status fetch to avoid writing .git/FETCH_HEAD while still updating remote-tracking refs for ahead/behind status. The reviewed change adds --no-write-fetch-head to fetchRemoteForStatus only. The regression test verifies that the fetch detects one commit of remote divergence and does not create .git/FETCH_HEAD. The reported tests also pass. User-initiated fetch and pull commands remain unchanged.

Full details: Out of Scope Changes check

Explanation

The whole pull-request summary contains one server change to the background fetch and a focused regression test. The source comment update supports the same fetch behavior. The reviewed scope contains no unrelated product behavior or user-facing changes.

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Usage-based review receipt

Note

This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.

Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 97adfec and 444ac38.

Files selected for processing: 2

  • apps/server/src/vcs/GitVcsDriverCore.test.ts
  • apps/server/src/vcs/GitVcsDriverCore.ts

Limit details: You’ve used all 10 included reviews currently available.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 21.5 KiB 21.5 KiB 0 B (0.0%) 24.4 KiB ✅
Codex Live turn messages 1 1 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.9 KiB 21.9 KiB 0 B (0.0%) 24.4 KiB ✅
Claude Live turn messages 1 1 0 (0.0%) 8 ✅

Baseline: 1d80047 · PR result: 444ac38 · Source CI: success

Scenario and decoded snapshot size

10 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.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Copy link
Copy Markdown
Member Author

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.

@macroscopeapp
macroscopeapp Bot dismissed their stale review November 11, 2026 03:50

Dismissing prior approval to re-evaluate 444ac38

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed size:XS 0-9 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Background status fetch writes FETCH_HEAD, racing user git pull ("Cannot fast-forward to multiple branches")

1 participant