git maintenance (Git 2.29+)
Introduced in Git 2.29, git maintenance is the modern, structured approach to keeping a repository healthy in the background. Unlike git gc — which runs as a blocking operation in your terminal — git maintenance start registers an OS-level scheduled task that runs maintenance jobs at regular intervals while you work, without interrupting any Git operation. It is particularly valuable for large repositories and monorepos where gc can take minutes.
Starting Background Maintenance
git maintenance start registers OS-level scheduling mechanisms: launchd on macOS, systemd timers or cron on Linux, and Windows Task Scheduler on Windows. After registering, maintenance tasks run automatically on schedule.
Start background maintenance for the current repo
git maintenance start
Example output on macOS
Created symlink /Users/you/Library/LaunchAgents/org.git-scm.git.fetcher.plist. Created symlink /Users/you/Library/LaunchAgents/org.git-scm.git.housekeeping.plist.
Stopping Background Maintenance
Unregister background maintenance
git maintenance stop
Running Maintenance Manually
Run all maintenance tasks now
# Run all registered tasks git maintenance run # Run a specific task only git maintenance run --task=gc git maintenance run --task=commit-graph git maintenance run --task=prefetch git maintenance run --task=loose-objects git maintenance run --task=incremental-repack
Available Maintenance Tasks
Task | What it Does | Default Schedule |
|---|---|---|
gc | Full garbage collection — packs loose objects, prunes expired reflog | Daily (if enabled) |
commit-graph | Writes/updates the commit graph file for faster history queries | Hourly |
prefetch | Fetches updates from all remotes in background (does not update branches) | Hourly |
loose-objects | Packs loose objects into pack files incrementally | Daily |
incremental-repack | Repacks existing packs into more efficient arrangements over time | Daily |
pack-refs | Packs loose refs into packed-refs file for faster ref lookups | Weekly |
The Commit Graph File
The commit graph is a binary data file at .git/objects/info/commit-graph that caches information about commits — parents, generation numbers, tree hashes — enabling Git to answer reachability queries in O(1) instead of traversing the full object graph. Operations like git log, git blame, git merge-base, and git push all benefit from a populated commit graph.
Manually write the commit graph
# Write commit graph for all reachable commits git commit-graph write --reachable # Write an incremental chain (faster for large repos) git commit-graph write --reachable --split # Check if commit graph exists ls .git/objects/info/
Commit graph files
.git/objects/info/
commit-graph ← monolithic commit graph
# or, with --split:
commit-graphs/
graph-abc123.graph ← incremental chain files
graph-def456.graph
commit-graph-chain ← lists which chain files to useSee the performance impact
# Without commit graph time git log --oneline main..feature/big-branch | wc -l # real 0m4.231s # After writing commit graph git commit-graph write --reachable time git log --oneline main..feature/big-branch | wc -l # real 0m0.087s
Configuring Maintenance Tasks
Each task's behavior and schedule can be tuned through the repository's .git/config or global ~/.gitconfig.
Enable and configure maintenance tasks
# Enable a specific task git config maintenance.commit-graph.enabled true git config maintenance.gc.enabled true git config maintenance.prefetch.enabled false # disable if bandwidth is a concern # Schedule options: hourly, daily, weekly git config maintenance.commit-graph.schedule hourly git config maintenance.loose-objects.schedule daily git config maintenance.incremental-repack.schedule daily
.git/config section after setup
[maintenance] auto = false strategy = incremental [maintenance "commit-graph"] enabled = true schedule = hourly [maintenance "prefetch"] enabled = true schedule = hourly [maintenance "gc"] enabled = true schedule = daily [maintenance "loose-objects"] enabled = true schedule = daily [maintenance "incremental-repack"] enabled = true schedule = daily [maintenance "pack-refs"] enabled = true schedule = weekly
Maintenance Strategy Presets
Use a built-in strategy
# incremental: no full gc, use incremental tasks instead (best for active repos) git config maintenance.strategy incremental # aggressive: runs gc periodically (smaller repos or archival repos) git config maintenance.strategy aggressive