Skip to content
ExponaBLOG
GIT & GITHUB FOR PROFESSIONAL DEVELOPERS · DAY 052 / 100

Sparse checkout and partial clone: a step-by-step guide

Work with huge repositories.

Expona Admin6 min read

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.

bash
git clone --filter=blob:none https://github.com/your-org/monorepo.git

The --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:

bash
cd monorepo
git rev-parse --show-toplevel
du -sh .git

Compare 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:

bash
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:

bash
git sparse-checkout init --cone
git sparse-checkout set apps/web packages/ui-components packages/shared-utils

The --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:

bash
git sparse-checkout list

To expand or change your sparse checkout:

bash
git sparse-checkout set apps/web packages/ui-components packages/shared-utils packages/logger

To go back to checking out everything:

bash
git sparse-checkout disable

Download 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:

bash
# 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-utils

What 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 ls immediately)
  • 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:

bash
git sparse-checkout set apps/web apps/api packages/shared-utils packages/logger

Git fetches the API code on-demand. They investigate, understand the issue, then revert:

bash
git sparse-checkout set apps/web packages/ui-components packages/shared-utils

The 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:none downloads 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 --cone and git sparse-checkout set paths populates 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.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles