The Challenge: Working with Monorepos at Scale
Your monorepo contains 15 applications, 40 shared libraries, and terabytes of build artifacts. You're a frontend engineer who only needs the web app, but git clone pulls everything—consuming hours and gigabytes. This is where sparse checkout and partial clone: a step-by-step guide becomes essential. These two Git features work together to let you download only the code you actually need, dramatically speeding up your workflow in large repositories.
We'll walk through both techniques, show you how they complement each other, and demonstrate why they're game-changers for teams working with monorepos.
Understanding Partial Clone with git clone --filter=blob:none
A partial clone doesn't fetch all object data from the remote repository—it defers downloading file contents (blobs) until you actually need them. This is different from a shallow clone, which limits history depth. Instead, Git downloads commit history and tree information but skips blob data, making the initial clone lightning-fast.
Let's say your monorepo is 50GB. A standard clone takes 30 minutes and consumes 50GB locally. A partial clone completes in 2 minutes and takes less than 1GB initially.
git clone --filter=blob:none https://github.com/your-org/monorepo.gitThe --filter=blob:none flag tells Git: "Download commits and trees, but not file contents." When you later access a file, Git fetches just that blob on-demand. Think of it as lazy-loading for your repository.
You can verify this worked by checking your repository's object database:
cd monorepo
git rev-parse --show-toplevel
du -sh .gitCompare this to a normal clone's .git size. You'll see the difference immediately.
Other filter options include --filter=blob:limit=1mb, which fetches blobs smaller than 1MB immediately and defers larger ones. This balances speed with convenience when you have many small text files you'll likely need anyway.
Setting Up Sparse Checkout with git sparse-checkout set
Sparse checkout is the second piece of the puzzle. While partial clone reduces downloaded data, sparse checkout reduces what gets checked out into your working directory. You can have the full repository history available but only populate certain directories on disk.
Let's say your monorepo has this structure:
monorepo/
├── apps/
│ ├── web/
│ ├── api/
│ ├── admin/
├── packages/
│ ├── ui-components/
│ ├── shared-utils/
│ └── logger/
└── docs/You're working on the web app. You need apps/web and the shared packages it depends on, but you don't need the admin app or docs directory taking up space or cluttering your IDE.
Enable sparse checkout and specify what to include:
git sparse-checkout init --cone
git sparse-checkout set apps/web packages/ui-components packages/shared-utilsThe --cone flag uses "cone mode," which is more efficient than full sparse checkout mode. It respects your directory hierarchy, so if you specify packages/, all its subdirectories are included.
Now your working directory contains only those three paths. Everything else exists in Git's object database but isn't checked out to disk. Your workspace is cleaner, tools like IDE indexing are faster, and builds don't accidentally depend on code you shouldn't be touching.
To see what's currently sparse-checked-out:
git sparse-checkout listTo expand or change your sparse checkout:
git sparse-checkout set apps/web packages/ui-components packages/shared-utils packages/loggerTo go back to checking out everything:
git sparse-checkout disableDownload Only What You Need: The Combined Workflow
The real power emerges when you combine partial clone and sparse checkout. They're designed to work together, creating an optimal experience for large repositories.
Here's a complete setup for a new team member joining your monorepo:
# Clone with blob filtering (download history, defer file contents)
git clone --filter=blob:none https://github.com/your-org/monorepo.git
cd monorepo
# Enable sparse checkout in cone mode
git sparse-checkout init --cone
# Check out only your team's code
git sparse-checkout set apps/web packages/ui-components packages/shared-utilsWhat happens now:
- Initial clone: Downloads commit history and tree objects (seconds, small size)
- Sparse checkout: Only directories you specified are populated on disk (you can run
lsimmediately) - First build: As your tools access files, Git fetches blobs on-demand and caches them locally
- Subsequent operations: Everything is cached, performance is normal
Contrast this with a teammate doing a standard clone and checkout of the entire repo: they wait an hour, consume 50GB, then spend 20 minutes waiting for their IDE to index everything. You're productive in 5 minutes.
When teammates push changes, a git pull fetches only the objects for paths you've checked out. Again, bandwidth and time savings.
Great for Monorepos: A Real-World Example
Monorepos are where these features shine. Consider an e-commerce platform with teams across frontend, backend, mobile, and data:
| Team | Sparse Checkout Paths | Why They Only Need These |
|---|---|---|
| Frontend (Web) | apps/web, packages/ui-components, packages/shared-utils |
Doesn't modify backend or mobile code; doesn't need massive data pipelines |
| Backend (API) | apps/api, packages/shared-utils, packages/logger |
Doesn't need UI code or mobile-specific logic |
| Mobile (iOS/Android) | apps/mobile, packages/shared-utils, packages/api-client |
Doesn't need web UI or backend business logic |
| Data Engineering | data-pipelines/, packages/logger, packages/config |
Works independently; rarely touches application code |
Each team clones once with --filter=blob:none, then runs git sparse-checkout set with their relevant paths. They get a 10GB download instead of 50GB, and their working directories reflect their actual responsibilities.
When a frontend engineer needs to investigate an API issue, they can temporarily expand their sparse checkout:
git sparse-checkout set apps/web apps/api packages/shared-utils packages/loggerGit fetches the API code on-demand. They investigate, understand the issue, then revert:
git sparse-checkout set apps/web packages/ui-components packages/shared-utilsThe API code is still in the object database (for quick re-access if needed) but no longer clutters their working directory.
Common Mistakes
Mistake 1: Using partial clone without sparse checkout. --filter=blob:none reduces initial download, but if you don't also use sparse checkout, your entire working directory populates with all files. You get speed gains during clone and pull, but disk usage is still high. Use both together.
Mistake 2: Forgetting to enable cone mode. Running git sparse-checkout init without --cone uses full sparse checkout mode, which is more complex and slower. Always use --cone unless you have unusual requirements.
Mistake 3: Assuming sparse checkout affects remotes. Sparse checkout is local-only. It doesn't change what gets pushed or pulled, just what exists in your working directory. Your commits and pushes are unaffected.
Mistake 4: Not documenting team sparse-checkout patterns. If your monorepo is complex, create a guide or script in your repository that shows each team which paths they should check out. Otherwise, developers guess and end up with bloated or insufficient checkouts.
Mistake 5: Mixing partial clone and shallow clone carelessly. --filter=blob:none with --depth can create confusing states. If you need history limits, prefer --filter=blob:none alone and let Git's on-demand fetching handle the rest.
Key Takeaways
- Partial clone with
--filter=blob:nonedownloads commit history and trees but defers blob (file content) fetching until needed, cutting clone time from hours to minutes. - Sparse checkout with
git sparse-checkout init --coneandgit sparse-checkout set pathspopulates only specified directories on disk, reducing clutter and improving IDE performance. - Used together, they're transformative for monorepos: teams download only their relevant code, work faster, and reduce storage waste.
- Sparse checkout is local-only and doesn't affect commits or pushes—it's purely a working directory optimization.
- Always use cone mode for sparse checkout unless you have niche requirements; document per-team sparse checkout patterns in your repository.
- This workflow scales to repositories with thousands of commits and hundreds of gigabytes of content.






Comments
Loading comments…