fatal: shallow file has changed since we read it
ID: git/shallow-clone-limitation
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 2 | active | — | — | — |
Root Cause
Shallow clones (depth=1) lack full commit history, breaking operations that require ancestry information like git log, git blame, git merge-base, and certain merge strategies. The shallow boundary file can also become stale during concurrent fetches.
genericWorkarounds
-
95% success Convert shallow clone to full clone with git fetch --unshallow
Run 'git fetch --unshallow' to download the complete commit history. This converts the shallow clone into a full clone. After this, all git operations (log, blame, merge-base, rebase) work correctly. In CI, add this step before any operation that requires history.
Sources: https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---unshallow
-
85% success Fetch a specific depth sufficient for the required operation
Run 'git fetch --depth=N' where N is large enough to include the commits you need (e.g., depth=100 for recent blame, depth=500 for a merge-base within the last year). Check with 'git rev-list --count HEAD' to confirm you have enough history.
Sources: https://git-scm.com/docs/git-fetch
-
92% success Use blobless clone (--filter=blob:none) instead of shallow clone
Clone with 'git clone --filter=blob:none <repo-url>'. This downloads all commits and trees but fetches file contents (blobs) on demand. You get full commit history for log, blame, and merge-base, while still saving significant bandwidth and disk space on initial clone.
Dead Ends
Common approaches that don't work:
-
Expecting full git log or git blame output to work correctly with --depth=1 clone
92% fail
A shallow clone with depth=1 only has the tip commit. git log shows a single commit, git blame cannot trace line origins beyond the shallow boundary, and any tool depending on full history produces incomplete or misleading results. This is by design, not a bug.
-
Running git merge-base to find common ancestors in a shallow clone
88% fail
merge-base requires reachable common ancestors between branches. In a shallow clone the commit graph is truncated, so merge-base either fails with a fatal error or returns incorrect results. This breaks rebase workflows and merge conflict resolution that depend on accurate base detection.
-
Repeatedly fetching with small incremental depth increases to avoid downloading full history
70% fail
Each git fetch --depth=N fetches from the tip, not from the current shallow boundary. Incrementally increasing depth is unreliable for reaching specific commits and can trigger 'shallow file has changed' race conditions when done concurrently. The total data transferred often exceeds a single --unshallow operation.