Monorepo team focus
A developer on one service in a large monorepo checks out only that service's directory and the shared libraries it needs, so status and checkout stay fast.
Git · Command
git sparse-checkout limits your working tree to a chosen subset of tracked files. You can also use it to change that subset later or to bring back the full checkout.
Last updated
Git keeps your chosen directories or patterns in $GIT_DIR/info/sparse-checkout. Whenever Git updates the working tree, it uses that file to set or clear the skip-worktree bit on each index entry. Files with the bit set are left out of the working tree, and Git does not treat them as missing. In cone mode, which is the default, you list directories and Git turns them into recursive and parent patterns that it can match quickly with hashing. The set and add subcommands write the file and then update the working tree to match.
git sparse-checkout (init | list | set | add | reapply | disable | check-rules | clean) [<options>]| Name | Type | Description |
|---|---|---|
set <dir>... | subcommand | Turns on the required config settings, replaces the sparsity definition with the given directories or patterns, and updates the working tree to match. |
add <dir>... | subcommand | Adds more directories (cone mode) or patterns (non-cone mode) to the current definition. |
list | subcommand | Shows the directories or patterns in the sparse-checkout file. |
reapply | subcommand | Applies the current rules to the working tree again. It also accepts --[no-]cone and --[no-]sparse-index, so you can switch modes without listing your paths again. |
disable | subcommand | Turns off core.sparseCheckout and checks out every file again. |
check-rules | subcommand | Reads paths from stdin and prints the ones that match the sparsity rules. Options: --rules-file <file> to test other rules, and -z for NUL-terminated input and output. |
clean | subcommand | Deletes leftover files that are outside the sparse definition. It only works in cone mode and needs -f/--force unless clean.requireForce is false. Also accepts --dry-run and --verbose. |
init | subcommand | Deprecated. Works like set with no paths and may be removed in the future. |
--stdin | option | For set or add: read directories or patterns from standard input, one per line, instead of from the arguments. |
--[no-]cone | option | Choose directory-based cone mode (the default) or gitignore-style pattern (non-cone) mode. |
--[no-]sparse-index | option | Turn the experimental sparse index on or off. It is off by default. |
Most subcommands change config, the sparse-checkout file and the working tree. list prints the directories that are included (cone mode), and check-rules prints the input paths that match the rules.
set -e
rm -rf demo && mkdir demo && cd demo && git init -q
mkdir -p MY/DIR1 MY/other SUB/DIR2 docs
for f in README MY/a MY/DIR1/b MY/other/c SUB/DIR2/d docs/e; do echo x > "$f"; done
git add . && git -c user.name=me -c user.email=me@x commit -qm init
# Keep only MY/DIR1 and SUB/DIR2 (cone mode is the default)
git sparse-checkout set MY/DIR1 SUB/DIR2
git sparse-checkout list # MY/DIR1, SUB/DIR2
find . -path ./.git -prune -o -type f -print | sort
# Which of these paths would be included?
printf 'docs/e\nMY/DIR1/b\n' | git sparse-checkout check-rules
# Grow the cone, then go back to a full checkout
git sparse-checkout add docs
git sparse-checkout disable
ls MY/other # c is backThe script builds a small repository, limits it to two directory cones, checks paths against the rules, adds a third directory, and then restores the full working tree.
A developer on one service in a large monorepo checks out only that service's directory and the shared libraries it needs, so status and checkout stay fast.
A CI pipeline that builds or tests one component uses set --stdin to read the directories it needs from a generated list, so it only puts those files on disk.
After a rebase writes conflicted files outside the cone, the engineer resolves them and runs reapply, then clean -f, to make the tree sparse again.
A script runs check-rules with --rules-file on a list of changed paths to see whether a proposed sparse definition would include them.
Each index entry has a skip-worktree bit. When Git updates the working tree, it sets or clears that bit according to the rules in $GIT_DIR/info/sparse-checkout. Files with the bit set are left out of the working tree, and Git treats their absence as expected rather than as a deletion. They are still tracked, so commits contain the full tree.
Follow-up: Why does git sparse-checkout list show only directories in cone mode when the file contains many patterns? Answer: In cone mode Git writes the expanded recursive and parent patterns to the file, but list shows only the directories that define the recursive patterns.
In cone mode you list directories, and Git includes everything below them plus the files directly inside their parent directories. Because the rules are this limited, Git can match them quickly with hashing. Non-cone mode accepts any gitignore-style pattern, which costs O(N*M) pattern matches, does not work with --sparse-index, and is deprecated. Use cone mode, which is the default.
Follow-up: What happens if a hand-edited sparse-checkout file no longer fits the cone pattern format? Answer: Git prints a warning and falls back to non-cone matching, whatever core.sparseCheckoutCone is set to.
Resolve the conflicts and commit or undo any changes to those files, then run git sparse-checkout reapply to apply the rules again. If directories outside the cone still contain leftover files, run git sparse-checkout clean, which only deletes with -f/--force. Run it with --dry-run or --verbose first to see what it would remove.
Follow-up: Why might clean still leave a directory in place? Answer: Merge conflicts or modified files outside the definition can keep files that would otherwise be removed. --verbose lists the files in each directory being considered, which helps explain why one is still there.
git-read-treegit-update-indexgit-worktreegit-configgitignoregit-clonegit-submodule