[Bug] Periodic git.refresh rewrites .git/index without GIT_OPTIONAL_LOCKS=0 - sync-loop hazard for repos in cloud-synced folders
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
Environment
- ZCode Desktop 3.10.2.6414, Windows 11
- Workspace = a git repo whose folder is also synced by a cloud-sync client (the whole folder incl.
.gitis mirrored across several PCs)
Summary
ZCode's Git integration spawns read-only git commands without GIT_OPTIONAL_LOCKS=0, so git status rewrites .git/index whenever the stat cache is stale. Since refreshes are triggered by window focus, a file watcher, and background polling (observed while a mobile web-remote session was paired), ZCode rewrites .git/index every ~1-3 minutes even when the user does nothing.
Evidence (captured 2026-09-06)
- Process capture - git.exe spawned by the ZCode host process:
git status --porcelain=v2 --branch --untracked-files=normal -z
git diff --cached --numstat -z --find-renames --
git diff --numstat -z --find-renames --
git config --show-scope --show-origin --get user.name / user.email
.git/index mtime changed within the same capture window as the spawn.
- Host-log correlation - ZCode's own log shows the refresh RPC completing ~10 ms after the index rewrite:
23:06:27.428 .git/index written (file mtime observed)
23:06:27.439 [zcode-host] [rpc:call] git.refresh OK (124.9ms)
- Triggers confirmed independently:
- Window focus: switching to the ZCode window -> index rewritten 19 s later
- File watcher: touching a tracked file -> index rewritten ~1-2 min later
- Idle polling: git.refresh every ~1-3 min with zero user input while a paired web-remote session was online (e.g. a refresh at 23:07:48 with nothing touched)
- Control experiment - VS Code built-in Git extension on the same repo under the same stale-stat conditions, captured
git status -z -uall:.git/indexwas not rewritten. (VS Code spawns git withGIT_OPTIONAL_LOCKS=0for read-only commands - the standard practice for exactly this reason.)
Impact
For a plain local repo this is invisible. For a repo inside a cloud-synced folder it creates a self-sustaining loop across machines:
machine A rewrites index -> sync client uploads (~437 KB per rewrite for a mid-size repo) -> machine B receives the replaced index -> B's index stat cache becomes fully stale -> B's ZCode rewrites it on next refresh -> uploads -> back to A ...
In our case (repo synced across machines) the sustained loop consumed a 1 GB/month upload quota in about two days (~55 rewrites/hour at peak).
Suggested fix
Set GIT_OPTIONAL_LOCKS=0 in the environment when spawning read-only git commands (status / diff / log / for-each-ref ...), or pass --no-optional-locks to git status. The SCM view stays correct while background refreshes never touch the index.
Reproduction
- Open a git repo as a ZCode workspace; optionally pair the mobile web-remote (speeds up the refresh cadence).
- Touch any tracked file (or simply focus the ZCode window).
- Watch
.git/indexmtime - it changes within seconds to minutes, parented by the ZCode host process.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Git integration's git.refresh entry point and the process-spawn paths for the listed read-only commands: status, diff, log, and for-each-ref. Reproduce the stale-stat case while watching .git/index mtime and host logs. Done means background refreshes leave the index unchanged while the SCM view remains correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git
- Domain
- devtools, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100