Use a shallow checkout in GitHub Actions
Let `actions/checkout` fetch only the commit under test (its default `fetch-depth: 1`) instead of the whole git history, and reach for `fetch-depth: 0` only when a job genuinely needs history.
Do this
actions/checkout runs at its default depth of 1, a single commit, for the vast majority of jobs. When a job needs the PR diff, fetch-depth: 2 is enough. Full history (fetch-depth: 0) is reserved for the specific jobs that actually need it: release-notes generation, git blame, or tools that walk tags.1
# Most jobs: the default fetches only the commit under test
- uses: actions/checkout@v4
# Need the PR diff? Depth 2 is enough, not the whole history
- uses: actions/checkout@v4
with:
fetch-depth: 2Avoid this
Every run downloads the entire history, even though the job only needs the latest commit.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # clones the ENTIRE git history, slow on large reposWhy it matters
On a repo with a long history, fetch-depth: 0 downloads far more than the job needs, and it pays that cost on every run. The default shallow fetch is often the single easiest checkout win. The fix is safe as long as you keep full history on the few jobs that require it.
When to use
Use it when
Almost every job. Drop an explicit fetch-depth: 0 unless you can name why the job needs history.
Be careful when
Keep full history when a job runs changelog/release tooling, git blame, git describe, or anything that walks tags or the full commit graph. For those, fetch-depth: 0 is correct.
Verify on your repo
Hand this prompt to your coding agent (Claude Code, Cursor, and the like) to audit and fix this practice in your own repo.
Inspect this repo's .github/workflows for `fetch-depth` on `actions/checkout`. Find every step that sets `fetch-depth: 0` (full history) and, for each, determine whether the job actually needs history: changelog or release tooling, `git blame`, `git describe`, or anything that walks tags. If nothing in the job needs history, remove the `fetch-depth: 0` (back to the default shallow depth of 1), or drop it to `fetch-depth: 2` when only a parent diff is needed. Leave jobs that genuinely need full history untouched. Show me the diff and open a PR rather than applying it blindly.Prefer to check by hand?
Search for the setting:
grep -rn 'fetch-depth' .github/workflows/.For each
fetch-depth: 0, ask what in the job needs history. If nothing does, remove it (back to the default 1) or drop to 2 for diff detection.A missing
fetch-depthis fine, the default is already 1.
More best practices for GitHub Actions
Where to go next in the CI best-practices catalog.
- Caching & Setup
Cache dependencies in GitHub Actions
Cache your package manager's downloads so CI restores dependencies from a keyed cache instead of reinstalling them from scratch on every run.
- Trigger Scope
Filter workflows by path in GitHub Actions
Add
pathsorpaths-ignoreto expensive workflows so a docs-only or unrelated change doesn't trigger the full test suite.
FAQ
What's the difference between fetch-depth 1, 2, and 0?
1 (the default) fetches only the commit being tested. 2 adds its parent, which is enough to diff the merge commit's two parents (the default checkout) or a single-commit PR; a multi-commit PR checked out at its head ref needs the merge base instead. 0 fetches the complete history and all tags, needed only for tooling that walks the full graph.
My diff-based tool broke after I removed fetch-depth: 0. Why?
It needs more than one commit to compare against. Use fetch-depth: 2 for a simple parent diff, or fetch the specific base ref your tool diffs against, rather than the whole history.
Sources
Last updated 2026-07-06
Clone only the history your build needs.
One line to install. Faster runs on day one, and agents that open reviewable PRs to keep your pipeline following practices like this one.