CORE JSC

International Technology Partnership

VS Code / Tools

Fixing Slow Git Operations and an Unresponsive Source Control Panel in VS Code on Large Repos

Checking out a branch or pulling changes makes the editor visibly stutter for a few seconds, and the little M/U/A badges in the file explorer lag behind what's actually changed. The repository itself isn't unusually huge — what's actually expensive is a status scan that has to walk far more files than the real change touched.

Core JSC Team·September 1, 2026
VS CodeGitPerformanceSource ControlDeveloper Tools

The Problem

On a repository with a large working tree — many tracked files, a long history, or a large number of currently untracked files — VS Code's Source Control panel becomes noticeably sluggish. The editor visibly stutters for a few seconds right after a checkout, pull, or branch switch, and the small file-decoration badges in the Explorer (the M/U/A indicators showing modified, untracked, or added files) lag behind the actual git status, sometimes taking many seconds to catch up. None of this correlates with how large the actual change was — a tiny commit can trigger the same multi-second pause as a large one.

Why It Happens

Git status scans scale with the size of the working tree, not the size of the change

VS Code's Source Control panel works by running the actual git CLI in the background and re-scanning repository status to keep its UI in sync. That scan is fundamentally a walk of the working tree, and its cost scales with how many files are being tracked or watched — not with how much actually changed. A repository with an enormous number of files, or a large number of currently untracked files (commonly build output that isn't gitignored), makes every single status refresh expensive regardless of how small the real diff is.

Explorer file-decoration badges add their own correlation cost

The M/U/A badges shown next to files in the Explorer require VS Code to correlate every currently visible file against the latest git status on relevant UI updates. On a repository with a very large working tree, that correlation work is itself a real, repeated cost — compounding with file-watcher load if the same large tree is also being watched for changes, a related but distinct cause covered separately for VS Code's file watcher exhaustion issue.

Multiple git-aware extensions can each trigger their own independent status scan

If more than one extension hooks into git events — a history/blame extension alongside the built-in Source Control panel, for instance — each one can independently query git status in response to the same underlying repository change, multiplying the actual number of status scans happening per operation rather than sharing a single one.

Ungitignored build output is the single most common, most fixable cause

Untracked files still get walked by git status on every scan, even though they'll never be committed. A build or dependency directory that isn't excluded via .gitignore inflates what every single status scan has to examine — this is frequently the actual reason a repository "feels" large to Git tooling even when its genuinely tracked source size is entirely reasonable.

The Fix

1. Confirm generated content is actually covered by .gitignore

git status --porcelain | grep "^??" | wc -l

A large number of untracked files reported here is the clearest signal that something generated (a build directory, dependency output) isn't excluded. Adding it to .gitignore removes that content from every future status walk entirely — this single fix resolves the majority of cases where the slowdown is disproportionate to the repository's genuinely tracked size.

2. Exclude large generated directories from VS Code's own watchers

// .vscode/settings.json
{
  "files.watcherExclude": {
    "**/node_modules/**": true,
    "**/dist/**": true,
    "**/build/**": true
  },
  "search.exclude": {
    "**/node_modules": true,
    "**/dist": true
  },
  "git.autofetch": false
}

Even directories correctly listed in .gitignore can still be scanned by VS Code's own file watcher and search indexing unless explicitly excluded there too — these settings stop VS Code itself from repeatedly walking the same large, irrelevant trees independent of git's own behavior.

3. Reduce redundant git-aware extensions on the same large repository

If multiple extensions independently hook into git status changes, disable or limit the ones that duplicate what the built-in Source Control panel already provides, particularly on a repository large enough for this to matter — each additional extension polling git status on the same event multiplies the actual scan cost rather than sharing a single result.

4. For genuinely large tracked repositories, use Git's own scaling tools

git sparse-checkout init --cone
git sparse-checkout set path/to/active/area
git config core.fsmonitor true

When the working tree is large because of genuinely large tracked source (not just ungitignored noise), VS Code-side settings alone can't fix the underlying cost — sparse-checkout materializes only the subset of the tree actually being worked on, and enabling Git's fsmonitor integration lets status queries use a persistent file-watcher daemon instead of a full walk on every single call.

Why This Works

Each fix reduces the actual amount of filesystem the status scan has to walk, rather than trying to make an inherently large scan complete faster. Fixing .gitignore removes untracked noise from every future scan; excluding directories from VS Code's own watchers stops redundant scanning independent of git; reducing duplicate extensions removes multiplied scan cost for the same underlying event; and sparse-checkout or fsmonitor address the case where the tree is genuinely large by changing what actually needs walking at all.

Conclusion

A sluggish Source Control panel and stuttering git operations in VS Code are almost always a symptom of the status scan walking far more of the working tree than the actual change touched — most commonly because generated content isn't excluded via .gitignore. Confirm untracked file count and fix .gitignore first, exclude large generated directories from VS Code's own watcher and search indexing, reduce redundant git-aware extensions triggering their own scans, and for genuinely large tracked repositories, reach for Git's own sparse-checkout and fsmonitor tools rather than relying on editor settings alone.