git sparse-checkout --cone: Partial Checkouts in CI
git sparse-checkout in cone mode (the default since Git 2.27) restricts the working tree to chosen directories, so a monorepo job only materializes the paths it needs.
For a monorepo, checking out everything wastes runner time and disk. Cone-mode sparse-checkout limits the working tree to a set of directories using fast directory-prefix matching instead of arbitrary patterns.
What it does
git sparse-checkout set <dirs> writes a sparse pattern set and updates the working tree to contain only those directories (plus files at the repo root). Cone mode (--cone, default) restricts patterns to directory prefixes, which is far faster than full pattern matching on large trees. Combine with a partial clone (--filter=blob:none) to also skip downloading unneeded blobs.
Common usage
git clone --filter=blob:none --no-checkout https://github.com/org/monorepo
cd monorepo
git sparse-checkout init --cone
git sparse-checkout set services/api libs/common
git checkout main
# inspect / widen later
git sparse-checkout list
git sparse-checkout add tools/ciOptions
| Command / flag | What it does |
|---|---|
| init --cone | Enable sparse-checkout in cone (directory) mode |
| set <dir>... | Replace the set of included directories |
| add <dir>... | Add directories to the existing set |
| list | Show the current sparse patterns |
| reapply | Re-evaluate patterns against the index |
| disable | Turn sparse-checkout off and check out everything |
In CI
Pair --filter=blob:none --no-checkout with sparse-checkout so the clone skips both unneeded blobs and unneeded files: a big win on monorepo runners. Note actions/checkout exposes a sparse-checkout input that runs these commands for you. Files at the repo root are always included regardless of the set.
Common errors in CI
"warning: disabling cone pattern matching" means a pattern you added is not a plain directory prefix; cone mode only takes directories. "fatal: this operation must be run in a work tree" appears if you ran set in a bare repo. If expected files are missing, the directory is simply not in the set; git sparse-checkout add it.
Using this in CI
CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # history, tags, and git describe all need this
- run: |
git rev-parse --is-shallow-repository # expect false
git rev-parse --abbrev-ref HEAD # prints HEAD when detached