# Fix Git GC Auto Packing Interrupting Operations

While running a Git command, you see this message:

bash
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:

bash
error: cannot lock ref 'refs/heads/main': unable to resolve reference 'refs/heads/main': reference broken
fatal: git gc failed

Git'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:

bash
git config --global gc.auto 0

This disables automatic GC. You must run it manually:

bash
git gc --prune=now

Step 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:

bash
0 3 * * 0 /path/to/maintenance.sh

Step 3: GC Failing With Lock Errors

If git gc fails with lock errors:

bash
error: cannot lock ref 'refs/heads/main': reference broken

Fix 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:

bash
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:

bash
cd /path/to/bare/repo.git
git config gc.auto 0

Then schedule manual GC on the server:

bash
# On the Git server
0 4 * * 0 cd /path/to/bare/repo.git && git gc --prune=now

Step 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:

bash
git config gc.pruneExpire
# Default: 2.weeks.ago

This 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:

bash
git gc --prune=now

Warning: 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:

bash
git repack -a -d -f --depth=250 --window=250

This 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.