[BUG] Desktop Code tab git polling still leaves orphaned .git/index.lock on large repos

Status Open
Maintainer reply None cached
Activity 1 comment · opened Oct 9, 2026

Summary

The Claude Desktop app (Code tab) polls git in the background for every open session. On a large repository this still leaves an orphaned .git/index.lock from time to time. Any later git add, git commit or index update then fails until someone removes the lock by hand. This is the same family as #37198, #11005, #47721 and #50269. Those issues are closed or locked, so I am filing a fresh report with captured evidence, as the bot comment asks.

Environment

  • Claude Desktop 2.26454.2 (Code tab), macOS 26.6.2
  • git 2.50.1 (Apple) and 2.49.0 (Homebrew)
  • Repository: about 159k tracked files on an external exFAT volume. Several Code sessions are open on the same repository at once.
  • Repo config already tuned for size: feature.manyFiles=true, index.version=4, core.untrackedCache=true, core.preloadIndex=true

Evidence

We ran a detached watcher that records every process touching the repository's git directory. It captured 9 orphaned locks over about 24 hours.

  • We traced and fixed the sources inside our own scripts. Every one was a porcelain git command that a Python subprocess.run(timeout=...) killed with SIGKILL.
  • Afterwards, one more orphan lock appeared at 11:04:35 local time. The only git processes that had started in the 30 seconds before it belonged to the desktop app.
  • Two of them were children of Claude Helper (the app's NodeService). Both started at 11:04:31, 4 seconds before the lock appeared.
  • Their command lines began with git -c core.quotepath=false … -c diff.ignoreSubmodules=…, which is consistent with the sidebar's git diff --numstat / git status polling.
  • No other git writer was running.

Local experiments with git 2.49 on clean repositories gave these results:

  • git diff (porcelain, against the worktree or HEAD) refreshes and writes the index (refresh_index_quietly) even with GIT_OPTIONAL_LOCKS=0. git status does honour GIT_OPTIONAL_LOCKS=0.
  • git diff-index, git diff-files and git diff --cached never write the index.
  • git removes its index.lock on SIGTERM but not on SIGKILL. A poller that kills a slow git process with SIGKILL therefore leaves the lock behind.
  • On a large repository a single refresh can hold the lock for 10–60 s, so a poll that times out is likely to hit this.

Expected

Background polling should never be able to leave .git/index.lock behind, and it should not compete with the user's own index writes.

Suggestions

  1. Run every read-only poll with --no-optional-locks (or GIT_OPTIONAL_LOCKS=0).
  2. Use plumbing instead of porcelain git diff for change counts, because porcelain diff refreshes the index anyway. For example, git diff-index --numstat HEAD also skips stat-only changes.
  3. On timeout, send SIGTERM to the git process group, allow a short grace period, and only then SIGKILL. Never SIGKILL git first.
  4. Add a per-project setting to turn off or slow down git polling for large repositories, as #50269 requested.

Thanks!

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗