Skip to content
Latchkey

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.

CI log
$ git describe --tags
fatal: No names found, cannot describe anything.

$ git merge-base origin/main HEAD
fatal: Not a valid object name origin/main

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

.github/workflows/ci.yml
- 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)" | head

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

.github/workflows/ci.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0      # all commits
    fetch-tags: true    # ensure tags are present

Fetch just the base branch you compare against

If full history is too heavy, fetch only the ref you diff against.

Terminal
git fetch --no-tags --depth=1 origin main
git diff --name-only origin/main...HEAD

The checkout options that fix most of this

.github/workflows/ci.yml
- 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 token

How to prevent it

  • Use fetch-depth: 0 for 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.

Frequently asked questions

What causes Git shallow clone missing history?
There are 2 common causes: default fetch-depth is 1 and only one branch was fetched. actions/checkout defaults to fetch-depth: 1, fetching only the checked-out commit.
How do I fix Git shallow clone missing history?
There are 2 fixes depending on which cause you have: fetch full history and tags and fetch just the base branch you compare against. Work through them in order, since the first is the most common.
What does Git shallow clone missing history actually mean?
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.
How do I stop Git shallow clone missing history happening again?
Use fetch-depth: 0 for release/versioning jobs that read tags. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card