Best practice · Caching & Setup

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

Default depth, or just enough for a diff
# 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: 2

Avoid this

Every run downloads the entire history, even though the job only needs the latest commit.

Full history on every run
- uses: actions/checkout@v4
  with:
    fetch-depth: 0   # clones the ENTIRE git history, slow on large repos

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

Prompt for your coding agent
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?
  1. Search for the setting: grep -rn 'fetch-depth' .github/workflows/.

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

  3. A missing fetch-depth is fine, the default is already 1.

More best practices for GitHub Actions

Where to go next in the CI best-practices catalog.

All CI best practices

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

1actions/checkout · fetch-depth (opens in new tab)

Last updated 2026-07-06

Get started

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.