Git Status Slow in a Large Repo? Two Config Lines Cut It From 17.6s to 0.83s
On a 393K-file Chromium checkout, a clean git status took 17.6 seconds. With two config lines it took 0.827 seconds. That's GitHub's own benchmark, and both settings have shipped in stock Git for years, turned off by default.
I'm leading with that because on November 2, 2026, OpenAI published Scaling Git at OpenAI, and the reaction I've seen is mostly "see, Git doesn't scale." Read the post itself and the story is different. Meta went off and built Sapling, Mononoke and EdenFS. OpenAI kept the Git protocol and the Git client and rebuilt the server.
If git status is slow on your large repo, look at your config before you look at a new VCS. Six Git settings matter for big repos and monorepos, and each one has published numbers behind it.
What OpenAI changed (it's the server)
The post isn't about laptops. Codex agents multiplied the branches, pushes, merges and fetches hitting the monorepo, and every push could kick off several CI jobs fetching the same commit. By late last year, reliability was at times below 90%. Their answer was Pando, a Git-compatible backend written in Rust. Pushed packfiles go straight into blob storage. Each branch gets its own ordered ref history, so pushes to unrelated branches never contend. Fetches get packfile-uri links to packs that already exist, served mostly from local disk cache, instead of a freshly generated pack.
They report median push latency cut by nearly 5x (roughly 80%), close to a petabyte served per day, and 57 TB in one hour with over 99% of it from cache. Pando reached production in about ten weeks and has served traffic since April. It's internal. OpenAI says it is "exploring ways to share" the tech, which isn't a release date.
None of that will help your git status. The server can be infinitely fast and your laptop will still stat 400,000 files every time you hit enter.
The 6 Git settings that fix a slow large repo
| Setting | Command | What it fixes | Published number |
|---|---|---|---|
| fsmonitor | git config core.fsmonitor true | git status scanning every file | Chromium refresh_index: 12.3s → 0.024s |
| untracked cache | git config core.untrackedCache true | scanning for new files | ~2x alone, ~10x with fsmonitor |
| commit-graph + Bloom filters | git config commitGraph.changedPaths true | slow git log -- path, git log -L, blame | 2-4x typical for git log -L on the Linux kernel |
| partial clone | git clone --filter=blob:none | huge clone, old big blobs | n/a |
| sparse-checkout | git sparse-checkout set <dirs> | checking out code you never touch | 5 min → <1s pattern matching |
| background maintenance | git maintenance start | gc stalls, stale commit-graph | n/a |
1 and 2: fsmonitor and the untracked cache
git config core.fsmonitor true git config core.untrackedCache true git fsmonitor--daemon status core.fsmonitor true uses the builtin daemon from Git 2.37. On macOS and Windows it has worked since then. On Linux it didn't exist until Git 2.55, which added an inotify backend. On Git 2.47 under Linux, git fsmonitor--daemon status just prints fatal: fsmonitor--daemon not supported on this platform. If that's where you gave up, check your version.
GitHub's numbers, from the FSMonitor post:
| Worktree | Files | No FSMonitor | FSMonitor + untracked cache |
|---|---|---|---|
| Chromium | 393K | 17.6s | 0.827s |
| Synthetic 1M | 1M | 41.1s | 0.590s |
| Synthetic 2M | 2M | 85.1s | 0.750s |
Three gotchas worth knowing before you file a bug:
- The first
git statusafter the daemon starts is as slow as before, or slower (17.9s became 19.8s, then 1.06s on the next run). Don't benchmark run one. - On Linux, the daemon docs warn that inotify has a per-user watch limit, "typically 8192 watches per user," and that repos with many directories may need more. inotify watches directories, and Chromium has 33K of them. Raise
fs.inotify.max_user_watchesor it'll fall over. - Network-mounted repos are refused unless you set
fsmonitor.allowRemote true, and the docs call that experimental.
If your build drops artifacts next to source files, that touches directory mtimes and invalidates untracked-cache entries. Move build output out of the tree. Scalar also disables the untracked cache on Windows by default.
3: the commit-graph, plus the part that's still off
The commit-graph file has been on by default since Git 2.24, so you probably already have one. The changed-path Bloom filters aren't on by default, and they're what speed up git log -- some/file and friends. In the commit that wired them into line-log, the full line-log history for arch/x86/kvm/cpuid.c in the Linux kernel dropped from 5.28s to 1.12s. The commit message itself says "A 2-4x speedup is likely the more typical case."
git config commitGraph.changedPaths true git commit-graph write --reachable --changed-paths 4: partial clone, the blobless kind
git clone --filter=blob:none <url> You get every commit and tree. Blobs download only when you need them. GitHub's clone guide calls blobless clones "best for developers and build environments that span multiple builds." It also says treeless clones (--filter=tree:0) are for throwaway CI builds and that it "strongly recommend[s] that developers do not use treeless clones for their daily work." Shallow clones get the same treatment, along with "Never fetch from a shallow clone!" I still see --depth=1 in dev onboarding scripts, and it's wrong there.
5: sparse-checkout in cone mode
git clone --filter=blob:none --no-checkout <url> cd repo git sparse-checkout set --cone git checkout main git sparse-checkout set services/payments web/checkout Use cone mode. Arbitrary patterns cost O(N×M) to match. In GitHub's test on a repo with about 3 million files, cone mode cut pattern matching from "five minutes" to "less than one second." Pair it with blobless clone and you never download contents for directories you don't check out.
6: background maintenance
git maintenance start Per the docs, this registers the repo with systemd timers or cron on Linux, launchctl on macOS and schtasks on Windows. Under the default incremental strategy, gc never runs. commit-graph and prefetch run hourly, loose-objects and incremental-repack run daily, and pack-refs runs weekly. You also stop getting a random "Auto packing the repository" that freezes your terminal mid-rebase.
Or let Scalar do most of it
scalar register # existing repo scalar clone <url> # new clone: sparse + commits/trees only + maintenance Scalar ships with Git. It sets a long list of opinionated config (index.version 4, commitGraph.changedPaths true, gc.auto 0, status.aheadBehind false, fetch.writeCommitGraph false and more) and starts maintenance. scalar clone also enables sparse-checkout, starting from just the top-level files. The docs table I read doesn't list core.fsmonitor, so I'd set that explicitly and check with git config --list --show-origin.
My take: if your repo has more than about 100K files, run scalar register and stop thinking about it. Tuning keys one by one only makes sense if you need to know exactly what changed.
What only helps at OpenAI scale
Don't copy these:
- A custom backend like Pando. It solves push contention from a flood of concurrent agent pushes. With 40 engineers and a CI runner, GitHub or GitLab is not your bottleneck.
-
packfile-uriand the client patches around it (parallel pack downloads, explicit haves). These need a server that hands out pre-built packs. OpenAI ships its own Git build, and several of its fixes are already in upstream Git, but they do nothing for you unless your host supports them. - Advertising only trunk to pushing clients. With millions of branches the full ref list can exceed 100 MiB, so it makes sense there. The cost OpenAI accepts is that pushes resend some history the server already has.
The HN thread points out that Anthropic, Cursor, GitHub and GitLab have published similar work recently. Beyond that it's half "this is a monorepo problem, not a Git problem" and half arguments over whether agent-scale commit volume is anything new (one commenter says Meta handled similar volumes six years ago). I side with the monorepo people here, with one caveat. Most teams complaining that Git is slow have never run git config core.fsmonitor true. Switch VCS after you've tried the free stuff.
How long does git status take in your biggest repo, and what finally made it fast? Or did nothing work, and you're one of the people who left for Sapling?
Sources
- Scaling Git at OpenAI, with the HN discussion
- Improve Git monorepo performance with a file system monitor (GitHub)
- git-fsmonitor--daemon docs
- Git 2.55 adds Linux FSMonitor (Linuxiac)
- line-log Bloom filter commit
- Get up to speed with partial clone and shallow clone (GitHub)
- Bring your monorepo down to size with sparse-checkout (GitHub)
- git-maintenance docs and scalar docs
- Sapling