# Fix Git GC Auto Packing Interrupting Operations
While running a Git command, you see this message:
Auto packing the repository in background for optimum performance.
See "git help gc" for manual housekeeping.And the current operation slows down significantly, or worse:
error: cannot lock ref 'refs/heads/main': unable to resolve reference 'refs/heads/main': reference broken
fatal: git gc failedGit's automatic garbage collection has triggered during an operation, causing delays or failures.
Understanding Git Garbage Collection
Git GC performs maintenance tasks: - Packs loose objects into pack files (reducing disk space) - Removes unreachable objects older than the pruning threshold - Optimizes the repository for performance
GC runs automatically when certain thresholds are met:
```bash git config gc.auto # Default: 6700 (triggers when 6700+ loose objects exist)
git config gc.autopacklimit # Default: 50 (triggers when 50+ pack files exist) ```
Step 1: Disable Automatic GC During Critical Operations
If GC is interrupting CI builds or deployments:
git config --global gc.auto 0This disables automatic GC. You must run it manually:
git gc --prune=nowStep 2: Run GC Manually During Maintenance Window
Schedule GC during off-peak hours:
```bash #!/bin/bash # maintenance.sh cd /path/to/repo
# Aggressive packing for best performance git gc --aggressive --prune=now
# Check repository health git fsck --full
# Report sizes du -sh .git/objects echo "Pack files: $(ls .git/objects/pack/*.pack 2>/dev/null | wc -l)" echo "Loose objects: $(find .git/objects -type f ! -path '*/pack/*' | wc -l)" ```
Run via cron:
0 3 * * 0 /path/to/maintenance.shStep 3: GC Failing With Lock Errors
If git gc fails with lock errors:
error: cannot lock ref 'refs/heads/main': reference brokenFix the broken reference:
```bash # Find broken refs git fsck
# If a specific ref is broken, try to repair it git update-ref -d refs/heads/broken-branch
# Or recover from the reflog git reflog show main git branch -f main HEAD@{0} ```
Step 4: GC Interrupting Push Operations
If GC triggers during a push, the push may fail:
remote: Auto packing the repository in background.
remote: error: cannot lock ref ...
To https://github.com/user/repo.git
! [remote rejected] main -> main (failed)On the remote server (e.g., bare repository on the Git server), disable auto GC:
cd /path/to/bare/repo.git
git config gc.auto 0Then schedule manual GC on the server:
# On the Git server
0 4 * * 0 cd /path/to/bare/repo.git && git gc --prune=nowStep 5: Large Repository GC Optimization
For large repositories, GC can take a very long time. Optimize the process:
```bash # Use multiple threads for delta compression git config pack.threads 4
# Increase pack window for better compression git config pack.windowMemory 256m git config pack.packSizeLimit 1g
# Run with aggressive packing (takes longer but produces smaller packs) git gc --aggressive ```
The --aggressive flag produces better compression but takes significantly longer. Use it only during planned maintenance windows.
Step 6: GC Pruning Old Objects
By default, GC only prunes objects older than 2 weeks:
git config gc.pruneExpire
# Default: 2.weeks.agoThis is a safety measure -- if you create a commit and then realize it was wrong, you have 2 weeks to recover it from the object database.
If you need to free disk space immediately:
git gc --prune=nowWarning: This permanently removes all unreachable objects. You cannot recover deleted branches or commits after this.
Step 7: Monitoring Repository Health
Set up monitoring for Git repository health:
```bash #!/bin/bash # git-health-check.sh REPO=$1
cd "$REPO" || exit 1
loose=$(find .git/objects -type f ! -path '*/pack/*' | wc -l) packs=$(ls .git/objects/pack/*.pack 2>/dev/null | wc -l) size=$(du -sm .git/objects | awk '{print $1}')
echo "Repository: $REPO" echo "Loose objects: $loose" echo "Pack files: $packs" echo "Objects size: ${size}MB"
if [ "$loose" -gt 5000 ]; then echo "WARNING: High number of loose objects. Consider running git gc" fi
if [ "$packs" -gt 40 ]; then echo "WARNING: Too many pack files. Consider running git gc --aggressive" fi ```
Step 8: Repack Instead of Full GC
If you only need to optimize packing without pruning:
git repack -a -d -f --depth=250 --window=250This repacks all objects into new pack files without removing unreachable objects. It is faster than git gc and does not affect the reflog or recovery capabilities.
Best Practice: Separate GC From Other Operations
Never run GC in the same script or cron job as other Git operations. GC acquires locks on the entire repository, which can block concurrent reads and writes:
```bash # WRONG: GC mixed with pull git pull && git gc
# CORRECT: Separate maintenance git pull # Production operations # ... later, during maintenance window ... git gc --prune=now # Maintenance operations ```
For multi-user repositories, coordinate GC windows to avoid interrupting developers' work.