Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
Summary
In the Agents Window, the Source Control panel shows “Initialize Repository” for 7 of 10 byte-identical sister clones of the same git repo. The same folders work in an Editor Window. Per the Cursor logs, the standard git extension successfully opens the repository in all clones, but for the broken ones, Cursor’s GitProvider spawns the git binary without a CWD inside the repo and without --git-dir/--work-tree when invoking the diff/ls-files/merge-base methods that feed the SCM panel. Git falls back to --no-index mode and emits explicit error output:
> git --no-optional-locks diff --cached --numstat -z [1221ms] (GitProvider.getDiffFileEntries.numstat)
error: unknown option `cached'
usage: git diff --no-index [<options>] <path> <path> [<pathspec>...]
> git --no-optional-locks diff --name-status -z [1453ms] (GitProvider.getDiffFileEntries.nameStatus)
warning: Not a git repository. Use --no-index to compare two paths outside a working tree
(captured from the per-workspace Git output channel for one of the broken clones)
In working clones the identical commands succeed and run hundreds of times over the same Cursor session — same args, just spawned with a usable CWD.
Evidence: per-workspace Git log, broken clone
In a broken clone (Clone-5), [Model][openRepository] succeeds, the branch and remote URL are read correctly, and git status -z -uall runs successfully. Then Cursor’s GitProvider invokes the diff pipeline:
[13:07:30.899] > git --no-optional-locks diff --cached --numstat -z [1221ms] (GitProvider.getDiffFileEntries.numstat)
error: unknown option `cached'
usage: git diff --no-index [<options>] <path> <path> [<pathspec>...]
[13:07:31.048] > git --no-optional-locks diff --name-status -z [1453ms] (GitProvider.getDiffFileEntries.nameStatus)
warning: Not a git repository. Use --no-index to compare two paths outside a working tree
[13:07:31.201] > git --no-optional-locks diff --numstat -z [1556ms] (GitProvider.getDiffFileEntries.numstat)
warning: Not a git repository. Use --no-index to compare two paths outside a working tree
The command is correct. The failure mode is git not finding a repo, which only happens when CWD isn’t set inside the repo and --git-dir/--work-tree aren’t passed.
The very next call in the same log succeeds, because it does pass the paths explicitly:
[13:07:31.240] > git --git-dir c:\repos\multi-clone\Clone-5\.git --work-tree c:\repos\multi-clone\Clone-5 rev-parse --git-common-dir [1057ms]
[no error]
Same workspace, same Cursor process, same instant — different spawn helper.
Quantitative comparison (one Cursor session)
Counts of GitProvider calls in two currently-alive extension hosts in the same Cursor process:
| Call | Clone-10 (working) | Clone-5 (broken) |
|---|---|---|
getDiffFileEntries |
78 | 4 |
hasUnpushedCommits |
13 | 0 |
ls-files --others |
15 | 0 |
merge-base origin/... |
13 | 0 |
GitProvider.resolveGitRevision |
4 | 1 |
fatal: not a git repository |
1 | 7 |
Clone-10 runs the full data pipeline hundreds of times and refreshes every few minutes. Clone-5’s pipeline starts, fails on the very first diff calls, retries git rev-parse --show-toplevel periodically (also fatal), and never populates the panel.
Diagnosis
Cursor’s GitProvider has multiple spawn paths:
- A “with CWD” path:
git --no-optional-locks diff --cached --numstat -zwith the spawn CWD set inside the repo. Works. - A “with explicit args” path:
git --git-dir <path>\.git --work-tree <path> rev-parse --git-common-dir. Works regardless of CWD. - A “neither CWD nor args” path:
git --no-optional-locks diff --cached --numstat -zwithout CWD and without--git-dir/--work-tree. Git falls back to--no-indexmode and emits the error/warning above.
For the broken workspaces, the diff/ls-files/merge-base data-fetch methods (GitProvider.getDiffFileEntries.*, GitProvider.hasUnpushedCommits, GitProvider.resolveGitRevision, plus the unlabeled git rev-parse --show-toplevel retries) are taking the third path.
The differentiator (which workspaces get CWD and which don’t) is keyed by workspace identity, persists across workspaceStorage rebuilds and Cursor restarts, and lives outside workspaceStorage.
What I ruled out
- Workspace root vs git root mismatch
- Symlinks / junctions / worktrees
safe.directory,core.fsmonitor,core.untrackedcache,extensions.*.gitignore/.gitattributesdifferences (SHA-256 identical).cursor/workspace settings (empty in all 10).code-workspacefiles- Long indexed paths
- Repo health (
git fsckclean) - Permissions / git binary
- Per-workspace state corruption / insufficiency / size (rename, donor-copy, and inverse-rename tests on
workspaceStorageall leave the broken/working assignment unchanged) - Branch / commit / pending-change state (5 clones on the same branch split 3 broken / 2 working)
- Unusual git state (no clones mid-rebase/merge/cherry-pick)
- Standard VS Code git extension (
[Model][openRepository]succeeds andgit statusruns in broken clones — Cursor’sGitProviderlayer is the broken one)
Steps to Reproduce
Setup: ten parallel sister clones of the same git repo, all under one parent directory, each opened as its own workspace by Local agents in the Agents Window:
C:\repos\multi-clone\Clone-1
…
C:\repos\multi-clone\Clone-10
All ten clones share:
- the same
remote.origin.url - byte-identical
.gitignoreand.gitattributes(SHA-256 verified) - the same
core.*config (filemode=false,ignorecase=true,symlinks=false) - empty
.cursor/folders - clean
git fsck - workspace root == git root (
git rev-parse --show-toplevel) - regular clones (not worktrees:
--git-dirand--git-common-dirboth return.git) - no
.code-workspacefiles - no
safe.directory,core.fsmonitor,core.untrackedcache, orextensions.*config
Steps:
- In the Agents Window, click an agent bound to a broken clone (Clone-5 in my case).
- Open the Source Control panel.
- Observe: panel shows “Use a Git repository to track changes” / “Initialize Repository” with no changes listed, even though the repo has pending changes.
- In the same Agents Window, click an agent bound to a working clone (Clone-10 in my case).
- Observe: panel populates correctly with branch, change list, Commit & Push button.
- From Command Palette →
Open Editor Window, thenFile > Open Folder…→ pick the same path that was broken in step 3. - Observe: Editor Window’s Source Control panel populates correctly for that same folder.
Result, across all ten clones in the same Agents Window:
| Clone | SCM panel |
|---|---|
| Clone-1 | works |
| Clone-2 | broken |
| Clone-3 | broken |
| Clone-4 | broken |
| Clone-5 | broken |
| Clone-6 | broken |
| Clone-7 | broken |
| Clone-8 | broken |
| Clone-9 | works |
| Clone-10 | works |
The 3 working / 7 broken split is stable across Cursor restarts, Developer: Reload Window, renaming the broken workspace’s workspaceStorage folder, donor-copying a working workspace’s state.vscdb into a broken workspace’s storage, and inverse-renaming a working workspace’s workspaceStorage (which stays working with a fresh ~4 KB state DB). The assignment is keyed by workspace identity and persists outside workspaceStorage.
Expected Behavior
Source Control panel in the Agents Window populates with the correct change list, branch, untracked files, ahead/behind state, and a working Commit button — for every workspace that is a valid git repo. Same as the Editor Window does today, and same as Cursor’s Agents Window does for 3 of my 10 sister clones.
Operating System
Windows 10/11
Version Information
IDE:
Version: 3.4.17 (user setup)
VSCode Version: 1.105.1
Commit: 93e603f703cd553a6bb3644711a3379bbbb31180
Date: 2026-05-13T21:39:55.724Z
Layout: glass
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Windows_NT x64 10.0.26200
Git: 2.53.0.windows.1
Shell: PowerShell (pwsh.exe)
Additional Information
Workaround
Use an Editor Window for git operations against any broken clone — its SCM panel populates correctly because the standard VS Code git extension is unaffected. Both Agents Window and Editor Window can be open simultaneously.
Hypothesis for the team
The bug is in the spawn helper that Cursor’s GitProvider uses for the diff/ls-files/merge-base data-fetch methods. For the workspaces where it works, the spawn site is providing CWD; for the workspaces where it fails, it isn’t. Pointing at:
- a per-workspace registration step where the workspace-folder-to-CWD binding is established once and cached, which fails (silently) for some workspaces but is preserved across restarts in
globalStorageor process state, and/or - an LRU / “active workspaces” cap that fully wires up
GitProviderfor the top-N workspaces and leaves the rest with partial bindings.
I have full per-workspace Git output logs for one broken (Clone-5) and one working (Clone-10) clone, plus the matching exthost.log files, and can attach them on request. Happy to install sqlite3 and dump specific tables/keys from globalStorage\state.vscdb (~10.9 GB on this install) if pointed at what to look for.
Environment notes
- Workspace count: 10 sister clones of one git repo, all opened as Local agents in the Agents Window
globalStorage\state.vscdbsize: ~10.9 GB (worth flagging separately; may or may not be related)%LOCALAPPDATA%\Cursor\does not exist on this install (Roaming AppData only)
Possibly related threads
- Cloud Agents Not available and no source control provider
- Agent "Changes" panel stays empty while git status shows changes
- Cursor fails to fully initialize workspace when restoring a “Working Tree” tab from previous session
Does this stop you from using Cursor
No - Cursor works, but with this issue