Every CI run starts the same way: clone the repo. As the repo grows - years of history, old assets, deleted binaries that still live in the past - that clone quietly becomes the slowest part of the pipeline. The fix is usually two flags, but they come with sharp edges worth knowing about.
Shallow clone: —depth#
A shallow clone downloads only the most recent commits:
git clone --depth 1 https://github.com/your-org/your-app.git
No history, no old blobs, a fraction of the download. For a pipeline that installs dependencies and runs PHPUnit, history is dead weight. GitHub Actions spells the same idea fetch-depth: 1 in actions/checkout; GitLab CI calls it GIT_DEPTH: "1".
Partial clone: —filter#
A partial clone keeps all commits but skips blobs until they are actually needed:
git clone --filter=blob:none https://github.com/your-org/your-app.git
You get the full commit graph instantly; file contents are fetched on demand from the remote. This suits developer machines working on a huge repo more than CI - CI usually wants no history at all, which is the shallow clone’s job.
The two gotchas#
Tags and versions. A shallow clone may not include tags, which breaks tooling that derives a version from git describe or the nearest tag. If your deploy step stamps a version this way, either fetch tags explicitly (git fetch --tags --depth 1 or fetch-depth: 0 in Actions) or pass the version in from the pipeline. Our post on deploying with tags covers the tagging side.
Anything that diffs against the past. A changelog generated from history, git blame, an incremental static-analysis baseline, git log for a “what changed since last deploy” note - all of these silently degrade or fail on a depth-1 clone. The rule of thumb: if a step reads history, give it history; if a step only builds and tests, shallow is safe.
Measure first: time the checkout step of your slowest pipeline. If it is more than thirty seconds, a shallow clone is likely the cheapest speedup available to you - one line in the CI config, no code changes, every run a little faster.
Share this post
Keep reading
Annotating Commits with git notes: Metadata Without Rewriting History
Some things belong on a commit but not in it: review links, benchmark results, the ticket nobody remembered to reference. git notes adds them after the fact, no rebase required.
Backing Up Your Git Server So It Actually Restores
Every clone is a partial backup - but hooks, config and server state live outside the repo. Mirror, bundle, copy off-site, and rehearse the restore.
Cherry-Picking: One Commit Without the Branch
Cherry-pick copies a single commit onto your branch and leaves the rest behind. Right for hotfixes across release branches, wrong as a sync strategy.