GitSparse Checkout

Sparse Checkout

Sparse checkout lets you check out only a subset of files from a repository into your working directory. Instead of materializing every file from every directory onto disk, Git writes only the paths you specify. The full history and all objects remain in the repository — but your working tree contains only what you asked for. This is a game-changer for large monorepos where a developer working on one package has no reason to have the other 200 packages on disk.

Why Sparse Checkout Exists

Modern monorepos can contain hundreds of packages, services, libraries, and platform-specific apps. A frontend developer working on packages/ui does not need the iOS app, the Kubernetes configs, or the machine-learning pipelines. Checking out all of those files wastes disk space and slows down every tool that scans the working directory — editors, linters, test runners, build systems, and file watchers. Sparse checkout fixes this by limiting the working tree to just the paths you actually need.

Cone Mode vs Non-Cone Mode

Feature

Cone Mode (recommended)

Non-Cone Mode

Pattern format

Directory prefixes only

Full gitignore-style patterns

Performance

Very fast — hash set lookup

Slower — pattern matching per path

Complexity

Simple and predictable

Flexible but complex

Enabled with

git sparse-checkout init --cone

git sparse-checkout init (no --cone)

Supports wildcards

No

Yes (*.ts, **/tests/, etc.)

Recommended for

Monorepo work, CI pipelines

Complex filtering with wildcards

Note
Cone mode (introduced in Git 2.26) is significantly faster because Git uses a hash-set lookup instead of running every path through gitignore-style pattern matching. Use cone mode unless you specifically need wildcard patterns.
Enabling Sparse Checkout (Cone Mode)

Clone and initialize sparse checkout

Bash
# Clone the repository normally first
git clone git@github.com:org/big-monorepo.git
cd big-monorepo

# Enable sparse checkout in cone mode
git sparse-checkout init --cone

# Check the working tree — only root-level files are present
ls

Working tree after init --cone (root files only)

Text
README.md
package.json
turbo.json
.gitignore
.eslintrc.json

After init --cone, only the files at the root of the repository are checked out. All subdirectories have been removed from your working tree but remain intact in the Git object store — nothing is lost.

Setting Paths to Include

Check out specific directories

Bash
# Check out packages/ui and docs/
git sparse-checkout set packages/ui docs/

# The working tree now contains:
#   - all root-level files (always included in cone mode)
#   - packages/ui/ and all its contents
#   - docs/ and all its contents

ls packages/
# ui/
Adding More Paths

Add additional directories without replacing existing ones

Bash
# Add packages/shared to the existing sparse set
git sparse-checkout add packages/shared

# Add multiple paths at once
git sparse-checkout add packages/api services/auth

# Verify what is now included
git sparse-checkout list

Output of git sparse-checkout list

Text
docs
packages/api
packages/shared
packages/ui
services/auth
Disabling Sparse Checkout

To return to a full checkout with all files present, disable sparse checkout. Git will populate every file that exists in the current ref.

Disable sparse checkout and restore all files

Bash
git sparse-checkout disable

# All directories are now visible
ls packages/
# android/  api/  dashboard/  ios/  ml-models/  shared/  ui/  web/
Non-Cone Mode with Patterns

If you need wildcard patterns — for example all TypeScript source files, or all directories named tests — use non-cone mode. Patterns follow the same syntax as .gitignore files but with inverted semantics (lines specify what to include, not exclude).

Non-cone mode with gitignore-style patterns

Bash
# Initialize without --cone flag
git sparse-checkout init

# Patterns are written to .git/info/sparse-checkout
# Include everything at root, exclude all of packages/, re-include packages/ui/
git sparse-checkout set '/*' '!/packages/' '/packages/ui/'

# Inspect the pattern file
cat .git/info/sparse-checkout

.git/info/sparse-checkout file contents

Text
/*
!/packages/
/packages/ui/
Note
The pattern /* includes everything at root level. !/packages/ excludes the entire packages directory. /packages/ui/ re-includes just the ui package. Reading the file top-to-bottom, later rules override earlier ones.
Real Use Case: Monorepo Developer Setup

Example monorepo structure

Text
big-monorepo/
├── README.md
├── package.json
├── turbo.json
├── packages/
│   ├── android/          ← you do not need this
│   ├── api/              ← you need this
│   ├── ios/              ← you do not need this
│   ├── ml-models/        ← you do not need this
│   ├── shared/           ← you need this
│   └── ui/               ← you need this
├── services/
│   ├── auth/             ← you need this
│   ├── billing/          ← you do not need this
│   └── notifications/    ← you do not need this
└── docs/                 ← you need this

Set up sparse checkout for a frontend developer

Bash
git sparse-checkout init --cone
git sparse-checkout set packages/api packages/shared packages/ui services/auth docs

# Working tree is now only ~15% of the full repo size
du -sh .
Combining Sparse Checkout with Shallow Clone

For the fastest possible repository initialization — minimal history AND minimal files — combine --depth=1 with sparse checkout. This is ideal for CI/CD pipelines working on monorepos where neither full history nor all packages are needed.

Maximum speed: shallow clone plus sparse checkout

Bash
# 1. Clone with depth=1 and skip the initial file checkout
git clone --depth=1 --no-checkout git@github.com:org/big-monorepo.git
cd big-monorepo

# 2. Enable sparse checkout
git sparse-checkout init --cone

# 3. Set the paths you need
git sparse-checkout set packages/ui packages/shared

# 4. Perform the checkout
git checkout main

Size comparison

Text
Full clone (all history, all files):          2.1 GB   4m 20s
Shallow clone (1 commit, all files):           340 MB   40s
Shallow + sparse (1 commit, 2 packages):        48 MB    8s
Common Errors
  • Files appear missing but git status shows nothing — sparse checkout is hiding them. Run git sparse-checkout list to see active paths.

  • "error: pathspec did not match any files" — the path you specified does not exist in the repository at the current branch.

  • Build tool reports missing packages — your build references a package not in your sparse set. Add it with git sparse-checkout add packages/missing.

  • After switching branches, files disappear — the new branch may have a different directory layout. Re-run git sparse-checkout set with correct paths.

Warning
Running git sparse-checkout set REPLACES the entire list of checked-out paths. Use git sparse-checkout add to append without losing existing paths. If you accidentally run set with only one path, all other previously included paths will be removed from your working tree immediately.
Tip
In VS Code and JetBrains IDEs, the file explorer shows only the files that are checked out via sparse checkout. This dramatically reduces noise and speeds up file-tree indexing in large monorepos — a repository that would show 10,000 files normally may show only 200.