Skip to main content

Fast full-history checkouts

actions/checkout fetches one commit by default (fetch-depth: 1). That is the fastest checkout, and the right one for most jobs.

Some jobs need history: comparing a pull request against its base branch, finding the last release tag, or generating a changelog. Those set fetch-depth: 0, which downloads every version of every file the repository has ever had. Most of those jobs only read commits and file names, never the old file contents.

Add one line

- uses: actions/checkout@v4
  with:
    fetch-depth: 0
    filter: blob:none

filter: blob:none makes a partial clone: all commits and directory listings, and file contents only for the commit you check out. If a later step reads an older version of a file, git downloads it at that moment.

What it saves

Measured on fremforge’s own largest repository (about 5,000 files, 4,600 commits), on hosted runners, October 2026:

CheckoutFetchCheck out filesTotal
fetch-depth: 023.4 s0.5 sabout 24 s
fetch-depth: 0 + filter: blob:none3.4 to 3.9 s6.4 to 6.5 sabout 10 s

The saving grows with the repository’s history. A young repository with few commits gains little.

When to use it

Use it when the job’s git commands read commits, branches, tags or names of changed files, for example:

  • git diff --name-only origin/main...HEAD
  • git log --oneline, git describe --tags
  • git merge-base

Leave it off when the job reads old file contents across many commits, for example git log -p over a long range, git blame on many files, or a tool that walks every historical version. Each missing file is then downloaded on demand, which can be slower than the full clone.

A git diff that shows content (not just names) between two commits downloads only the files that changed, in one batch. That is usually still faster than a full clone.

Why this is not the default

fremforge does not turn this on for every job, for two reasons:

  • It slows the default checkout. With fetch-depth: 1, a partial clone needs a second round trip for the files, so it is slower, not faster.
  • The repository needs its own settings to work. The filter input writes the partial-clone settings into the checked-out repository, so any later step can fetch what it needs. A setting applied to the runner as a whole would not travel with the repository, and a step running with a different home directory, for example inside a job container, would fail on the first missing file.

So the choice stays with you, per workflow.