Linear tools, exponential repos
Git was originally tuned for the Linux kernel — large by 2005 standards but tiny by today's. Modern repos can hold millions of files, hundreds of gigabytes of history, and tens of thousands of refs. Many Git operations were O(working tree size) or O(history) by default, and at scale they became visibly slow. Performance work since 2018 has added optional features that turn many operations into O(changed) rather than O(total).
Where time goes
Common slow paths:
git statuswalks the working tree to detect changes.git log,git blame, and merge-base calculations walk commit graphs.git fetchnegotiates with the server over many ref changes.git gcrepacks every object, even unchanged ones.- The index is read and written many times per command, and grows linearly with tree size.
Measuring
Before tuning, measure. Trace2 emits structured events for every Git invocation:
GIT_TRACE2_PERF=1 git status
GIT_TRACE2_EVENT=/tmp/trace.json git status
git -c trace2.eventTarget=/tmp/trace git fetch
See "Measuring Git performance with Trace2" for analysis.
The performance toolbox
Modern Git provides:
- commit-graph: precomputed reachability data.
- changed-path Bloom filters: skip irrelevant commits in
log -- path. - multi-pack-index: one lookup index across many packs.
- reachability bitmaps: O(1) set operations on huge histories.
- fsmonitor: filesystem change notifications instead of stat walking.
- partial clone and sparse index: shrink local data.
- geometric repack: avoid full repack costs.
- protocol v2: efficient ref negotiation.
- git maintenance: keep all of this fresh in the background.
Quick wins
git config feature.manyFiles true
git config core.fsmonitor true
git config core.untrackedCache true
git config index.version 4
git maintenance start
For most users, this trio cuts git status from seconds to milliseconds on repos with hundreds of thousands of files.
Common mistakes
Tuning before measuring. Enabling features without understanding them — for example, core.fsmonitor=true requires Git 2.37+ for the built-in daemon; older versions need an external one. Skipping git maintenance start, leaving the commit-graph and MIDX stale.
Related
See every page in this section. Start with "Measuring Git performance with Trace2".