Skip to main content
RunBook Academy

Git, CI/CD & GitOpsCII · Large Repository PerformanceShallowAndPartial

Shallow clones and partial checkouts — fetching less history

Intermediate⏱ ~20 mingit

What you'll learn

  • Distinguish a shallow clone from a partial clone and explain when each helps
  • Choose `--depth`, `--shallow-since`, `--filter=blob:none`, `--filter=tree:0` for the workload
  • Recognise the operations a shallow or partial clone does not support
  • Apply the right combination for an engineer workstation versus a CI runner

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

A shallow clone truncates history at a depth; a partial clone defers blobs on demand. Both cut bandwidth; both impose limits. The trade is fetch cost versus local capability.

Shallow clones

git clone --depth 1 "$REPO_URL" repo
git clone --depth 50 --branch main "$REPO_URL" repo
git clone --shallow-since="2024-01-01" "$REPO_URL" repo

--depth 1 fetches only the tip (cheapest). --shallow-since is date-bounded.

flowchart LR
    A[("full")] -->|"depth 1"| B[("tip")]
    A -->|"depth 50"| C[("last 50")]
    A -->|"shallow-since"| D[("since date")]

Shallow clones cannot run most history ops: git log --all shows only the present window; git bisect cannot reach older bugs.

Partial clones

git clone --filter=blob:none "$REPO_URL" repo
git clone --filter=tree:0 "$REPO_URL" repo
git clone --filter=blob:limit=1m "$REPO_URL" repo

--filter=blob:none defers all blobs. --filter=tree:0 defers all trees (rarely useful). --filter=blob:limit=1m defers blobs above 1 MB.

flowchart LR
    A[("full")] -->|"filter blob:none"| B[("commits+trees")]
    B -->|"checkout needs blob"| C["on-demand"]

A partial clone has full history, but ops that read a blob trigger fetches. git log -p fetches per hunk.

Choosing a strategy

  • CI cold cache. --depth 1, no --filter.
  • Engineer workstation. --filter=blob:none, no --depth.
  • CI release tag. --branch $TAG --depth 1.
  • Long-lived feature. No shallow, no partial; the history is the value.

Shallow can git fetch --unshallow; partial can git fetch --filter= to materialise.

Production discipline

  1. Default CI to --depth 1, no --filter.
  2. Default workstations to --filter=blob:none, no --depth.
  3. Pin release builds to --branch $TAG.
  4. Document the unshallow path.

Cross-course references

  • Linux for Production Sysadmins Part XXVI: filesystem analogue.
  • Terraform for Production Sysadmins Part IX: state in a backend.

Quiz

Knowledge check · 4 questions

  1. Q1. An engineer runs `git clone --depth 1`, then `git bisect start` for a year-old regression. What fails?

  2. Q2. A partial clone (`--filter=blob:none`) defers all reachable blobs and is equivalent to a shallow clone in capability.

  3. Q3. Name the two shallow-clone flags that bound commits by depth and by date, and the two partial-clone flags that defer all blobs and blobs above a size limit.

  4. Q4. Recommend the right shallow/partial strategy for engineer workstation versus CI runner.

    Team J: 5 GB Terraform monorepo with 8 GB packfile. Engineer cold clone is 22 min; CI cold cache is 18 min. Team wants to cut both.

Passing score: 75%. Answers are checked in this browser.