Commit-Graphs, Multi-Pack Indexes, Maintenance, Garbage Collection, and Performance: Configuration, Design Choices, and Tradeoffs
Design maintenance policy around current maintenance strategies, auto-maintenance controls, commit-graph/MIDX settings, FSMonitor, untracked cache, Scalar, and developer/CI/server lifecycle differences.
Learning objectives
- Choose among current maintenance strategies and task-level overrides.
- Distinguish maintenance.auto from traditional gc.auto heuristics.
- Use current commit-graph changed-path controls and recognize deprecated settings.
- Separate FSMonitor/untracked-cache working-tree acceleration from object-store optimization.
- Select policies differently for developer clones, CI checkouts, and central servers.
1. Performance configuration is a policy decision, not a collection of magic switches
Optimization changes CPU, memory, disk, background I/O, network access, and recovery behavior. A developer clone, an ephemeral CI checkout, and a central bare repository have different lifecycles. Configure each environment from measured constraints instead of copying a “fast Git” profile everywhere.
2. Inspect scope and origin before changing behavior
git config --list --show-origin --show-scope
git config --show-origin --get maintenance.strategy
git config --show-origin --get maintenance.auto
git config --show-origin --get gc.auto
git config --show-origin --get core.commitGraph
git config --show-origin --get core.multiPackIndex
git config --show-origin --get commitGraph.changedPaths
git config --show-origin --get core.untrackedCache
git config --show-origin --get core.fsmonitor
Repository-local settings are appropriate for a lab; global settings affect every repository for that user. Scheduled maintenance registration also commonly involves global configuration because one scheduler invocation can iterate over registered repositories.
3. Current maintenance strategies encode different cost/retention models
| Strategy | Current intent | Best fit |
|---|---|---|
none |
No strategy-selected tasks | Explicit/manual control |
gc |
Run the GC task | Traditional/simple maintenance |
geometric |
Geometric repacking plus auxiliary housekeeping; can expire stale data under configured policy | Current recommended large-repository manual strategy |
incremental |
Small scheduled tasks; avoids scheduling GC/data-deleting tasks | Background maintenance with bounded foreground impact |
Current documentation makes geometric the default for
manual maintenance and describes incremental as the
background-oriented small-task strategy. This has evolved across Git
versions, so mixed-version fleets need an explicit documented
strategy.
4. Task-specific configuration overrides strategy defaults
git config --local maintenance.commit-graph.enabled true
git config --local maintenance.commit-graph.schedule hourly
git config --local maintenance.incremental-repack.enabled true
git config --local maintenance.incremental-repack.schedule daily
If git maintenance run receives explicit
--task options, those tasks take precedence. Otherwise
strategy and maintenance.<task>.enabled/.schedule
determine what runs.
5. maintenance.auto and gc.auto are
related but not identical control surfaces
maintenance.auto controls whether eligible foreground
commands trigger git maintenance run --auto.
Traditional gc.auto defines a loose-object threshold
for automatic GC heuristics; gc.autoPackLimit covers
pack-count consolidation. Setting gc.auto=0 disables
the GC auto heuristics, but it is not a universal “disable every
kind of maintenance” switch.
Registration for scheduled maintenance can disable foreground auto-maintenance in the registered repository so background scheduling owns the work.
6. core.commitGraph controls reading the commit-graph;
writing is separate
Current Git defaults core.commitGraph to true. If a
valid commit-graph exists, Git may use it for graph traversal.
Writing/updating the file comes from
git commit-graph write, GC, or the commit-graph
maintenance task.
git config --local core.commitGraph true
git config --local commitGraph.changedPaths true
commitGraph.changedPaths=true makes writes compute
changed-path Bloom filters by default.
7. commitGraph.readChangedPaths is now deprecated
Current Git documents commitGraph.readChangedPaths as
deprecated. New policy should use the current changed-path
configuration/version controls rather than institutionalizing a
deprecated toggle. commitGraph.changedPathsVersion can
affect compatibility: newer Bloom-filter versions may not be
understood by older Git releases.
8. core.multiPackIndex defaults to true, but a MIDX
must exist to help
The setting tells Git to use a multi-pack index when present. It does not create one. Writing, verifying, repacking, compacting, and expiring MIDX structures are separate operations. Current Git 2.54+ also includes version-2/incremental MIDX features with compatibility boundaries for older clients.
9. FSMonitor solves working-tree scanning, not object-store lookup
The built-in filesystem monitor can tell Git which paths may have
changed so commands such as status avoid scanning every
file. Current Git documentation describes the built-in daemon as
platform-dependent; Windows and macOS are explicitly supported in
current configuration documentation. Other platforms may use
different support/build/runtime paths.
git config --local core.fsmonitor true
Do not enable it blindly in a mixed-version toolchain. Older Git
clients historically interpreted boolean
core.fsmonitor values differently.
10. The untracked cache avoids repeated directory scans when filesystem mtimes are reliable
git update-index --test-untracked-cache
git config --local core.untrackedCache true
The untracked cache stores directory information in the index. Its benefit is strongest in large working trees with many untracked paths. The filesystem must update directory mtimes reliably for the cache assumptions to hold.
11. FSMonitor and untracked cache can complement each other
Current status documentation explains that using both can reduce two different costs: identifying modified tracked paths and enumerating changed directories for untracked files. Performance improves after caches warm; benchmark several runs before drawing conclusions.
12. Scalar is an optional large-repository management layer
scalar is shipped as a Git tool for managing large
repositories. It can configure recommended large-repository settings
and maintenance behavior. It is useful when a team wants an
opinionated bundle of features, but it is not a prerequisite for
understanding Git's underlying commit-graph, maintenance,
sparse/partial, and working-tree mechanisms.
scalar version
scalar list
Use Scalar only after verifying its availability and the configuration it will apply. The mandatory chapter labs use core Git commands so learners understand the mechanisms directly.
13. Developer, CI, and server repositories have different maintenance responsibilities
A long-lived developer clone benefits from working-tree acceleration and background maintenance. An ephemeral CI clone may be deleted before background maintenance could repay its cost; checkout depth/transfer choices matter more. A central bare server has no working tree, so FSMonitor/untracked-cache are irrelevant, while pack/commit-graph/ref maintenance can be important at scale.
14. Decision table — justify the operational cost
| Environment | Measured problem | Likely choice | Tradeoff |
|---|---|---|---|
| Long-lived developer monorepo | slow status + growing packs | untracked cache/FSMonitor where supported + scheduled incremental/geometric maintenance | background CPU/I/O; platform/version dependencies |
| Ephemeral CI clone | checkout/fetch dominates | optimize transfer/checkout; minimal local maintenance | less history/auxiliary reuse |
| Bare integration server | many packs/history queries | MIDX/commit-graph and controlled server maintenance | maintenance windows and I/O load |
| Small repository | no measurable bottleneck | defaults | lowest operational complexity |
15. Knowledge check
Question 1. Does
core.multiPackIndex=true automatically create a
MIDX?
Question 2. Why is commitGraph.readChangedPaths a poor new policy knob?
Question 3. Which performance problem does FSMonitor address?
Question 4. Why might an ephemeral CI clone skip background maintenance?
Question 5. When should Scalar be considered?
16. Summary
Configuration should follow repository lifetime and bottleneck. Current Git offers maintenance strategies, task overrides, commit-graph/MIDX defaults, working-tree accelerators, and Scalar; each solves a different problem and carries different portability, retention, and background-work costs.
Authoritative references
git-maintenance configuration
git-config
git-update-index caches
git-fsmonitor--daemon
scalar
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.