git fetch --deepen and --unshallow in CI
git fetch --deepen=<n> extends a shallow clone by n more commits, and git fetch --unshallow downloads the full remaining history.
CI defaults like actions/checkout fetch-depth: 1 break any step that needs older commits: diffs, blame, describe, merge-base. --deepen and --unshallow are the targeted fixes that avoid re-cloning.
What it does
A shallow clone has a truncated history. git fetch --deepen=<n> adds n commits of history below the current shallow boundary. git fetch --unshallow fetches everything left, converting it to a full clone. --depth=<n> (on fetch) sets the absolute depth rather than adding to it.
Common usage
# add 50 more commits of history
git fetch --deepen=50
# fetch all remaining history
git fetch --unshallow
# fetch tags too (needed for git describe)
git fetch --tags --unshallow
# deepen just one branch
git fetch --deepen=100 origin mainOptions
| Flag | What it does |
|---|---|
| --deepen=<n> | Add n commits below the shallow boundary |
| --depth=<n> | Set absolute depth (may add or truncate) |
| --unshallow | Fetch the complete remaining history |
| --shallow-since=<date> | Deepen to a date instead of a count |
| --tags | Also fetch tags (often needed after deepening) |
In CI
With actions/checkout, set fetch-depth: 0 for a full history or a number for partial, instead of deepening afterward. If you must deepen in-job, run git fetch --unshallow --tags before any git describe step, since shallow clones usually omit tags. --unshallow errors on a clone that is already complete.
Common errors in CI
"fatal: --unshallow on a complete repository does not make sense" means the clone is not shallow; guard with git rev-parse --is-shallow-repository. "fatal: error in object: unshallow <sha>" can appear with corrupt shallow boundaries; re-clone. A later "fatal: No names found, cannot describe anything" usually means tags were not fetched, not a depth issue.
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.
- 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