# git gc --prune=now --aggressive in CI Caches

> git gc compacts the object store and prunes unreachable objects; --prune=now removes them immediately. Reference for the flags and the "gc.log" warning in CI.

Source: https://latchkey.dev/learn/command-reference/git-gc-prune-now  
Updated: 2026-06-30

git gc repacks objects and prunes ones older than the grace period; git gc --prune=now drops all unreachable objects immediately to reclaim disk on cached runners.

On persistent runners a .git directory grows without bound as branches and rewrites pile up. gc compacts it, and --prune=now reclaims space now instead of after the default two-week grace window.

## What it does

git gc consolidates loose objects into packfiles, prunes unreachable objects older than the grace period (default 2 weeks), expires reflogs, and packs refs. --prune=now drops the grace period so all currently-unreachable objects go immediately. --aggressive spends more CPU for a tighter pack; it is rarely worth it routinely.

## Common usage

```Terminal
git gc
# reclaim everything unreachable right now
git reflog expire --expire=now --all
git gc --prune=now
# quick, only if the auto threshold is hit
git gc --auto
# tighter (slow) repack
git gc --aggressive --prune=now
```

## Options

| Flag | What it does |
| --- | --- |
| --prune=<date> | Prune unreachable objects older than <date> (now = all) |
| --no-prune | Repack but keep unreachable objects |
| --aggressive | Spend extra CPU for a more compact repository |
| --auto | Run only if enough loose objects/packs have accumulated |
| --quiet | Suppress progress output |

## In CI

Reflogs keep dropped commits reachable, so run git reflog expire --expire=now --all before git gc --prune=now to actually free them. Avoid --aggressive in regular CI: it is slow and the gain is marginal. Note that a concurrent git process can race gc and leave a gc.log warning; the next operation usually clears it.

## Common errors in CI

"warning: There are too many unreachable loose objects; run 'git prune' to remove them." is a hint, not a failure. "fatal: gc is already running on machine ..." means a stale gc.pid lock from a killed job; remove .git/gc.pid. "error: The last gc run reported the following ... see .git/gc.log" surfaces a prior failure; read gc.log and resolve, then it clears.

## Using this in CI

CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.

```.github/workflows/ci.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0   # history, tags, and git describe all need this

- run: |
    git rev-parse --is-shallow-repository   # expect false
    git rev-parse --abbrev-ref HEAD          # prints HEAD when detached
```

> `git rev-parse --abbrev-ref HEAD` returns the literal string `HEAD` on a detached checkout rather than a branch name. On GitHub Actions read `github.ref_name` instead; the git command cannot know what it was checked out for.

## FAQ

### git gc --prune=now --aggressive in CI Caches?

On persistent runners a .git directory grows without bound as branches and rewrites pile up. gc compacts it, and --prune=now reclaims space now instead of after the default two-week grace window.

### What it does?

git gc consolidates loose objects into packfiles, prunes unreachable objects older than the grace period (default 2 weeks), expires reflogs, and packs refs. --prune=now drops the grace period so all currently-unreachable objects go immediately. --aggressive spends more CPU for a tighter pack; it is rarely worth it routinely.

### In CI?

Reflogs keep dropped commits reachable, so run git reflog expire --expire=now --all before git gc --prune=now to actually free them. Avoid --aggressive in regular CI: it is slow and the gain is marginal. Note that a concurrent git process can race gc and leave a gc.log warning; the next operation usually clears it.

### Common errors in CI?

"warning: There are too many unreachable loose objects; run 'git prune' to remove them." is a hint, not a failure. "fatal: gc is already running on machine ..." means a stale gc.pid lock from a killed job; remove .git/gc.pid. "error: The last gc run reported the following ...

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
