Git Shallow Clone Missing History - fetch-depth Too Small in CI
A shallow clone is fast but only contains the most recent commit(s). Any command that needs older history - a version derived from tags, a diff against main, a commit count - fails or returns wrong results.
What this error means
A build works locally with full history but in CI a step like git describe, git merge-base origin/main HEAD, or a "changed files since base" diff fails or yields empty/incorrect output. The repo was cloned with the default shallow depth.
$ git describe --tags
fatal: No names found, cannot describe anything.
$ git merge-base origin/main HEAD
fatal: Not a valid object name origin/mainDiagnose it: depth, refs, or credentials?
CI checkouts are shallow and detached by default, which breaks anything that needs history or a branch name. Before treating it as a credential problem, confirm what the runner actually fetched.
- run: |
git rev-parse --is-shallow-repository
git rev-parse --abbrev-ref HEAD # prints HEAD when detached
git log --oneline -3
git remote -v
git for-each-ref --format="%(refname)" | headCommon causes
Default fetch-depth is 1
actions/checkout defaults to fetch-depth: 1, fetching only the checked-out commit. Tags, the base branch, and prior commits are absent, so history-dependent commands have nothing to work with.
Only one branch was fetched
A shallow single-branch clone has no origin/main ref locally, so diffs and merge-base calculations against the base branch fail outright.
How to fix it
Fetch full history and tags
For version derivation and base-branch diffs, fetch everything.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # all commits
fetch-tags: true # ensure tags are presentFetch just the base branch you compare against
If full history is too heavy, fetch only the ref you diff against.
git fetch --no-tags --depth=1 origin main
git diff --name-only origin/main...HEADThe checkout options that fix most of this
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history: diffs, tags, git describe
submodules: recursive # submodules are NOT fetched by default
persist-credentials: false # if a later step pushes with its own tokenHow to prevent it
- Use
fetch-depth: 0for release/versioning jobs that read tags. - Explicitly fetch the base branch before any diff-against-base step.
- Keep shallow clones for plain build/test jobs that need no history.