Git Course 0%

Worktrees, sparse checkout, shallow and partial clone

Expert Git CLI ≈ 10 min

Before this lesson

What you will learn

  • How a worktree lets two branches exist side by side
  • Sparse checkout, for a monorepo you only need part of
  • What shallow and partial clones trade away

After this lesson you can

  • I can work comfortably in a repository that is too big or too busy for one checkout

Why this matters

Four tools for two annoyances: switching branches constantly to review someone's work, and a repository so large that a full clone or checkout is painful. None is needed on a small project, and each one saves real time on a large one.

Worktrees: two branches at once

A worktree is a second working directory attached to the same repository. Both share one .git, so all the commits, branches and objects are common, and each has its own checked-out branch.

Terminal
$ git worktree add ../trailguide-review HEAD~1
Preparing worktree (detached HEAD b81702c)
HEAD is now at b81702c docs: add getting started guide and FAQ
Terminal
$ git worktree list
~/dev/trailguide         d3b92ec [main]
~/dev/trailguide-review  b81702c (detached HEAD)

Now ~/dev/trailguide-review is a full working copy of that commit, and your original directory is untouched. Editors can open both at once.

Use it for Instead of
Reviewing a colleague's branch while yours stays open Stashing and switching
A long build in one directory while you edit in another Waiting
Comparing two versions side by side in an editor Two clones
Terminal
$ git worktree add ../trailguide-hotfix -b hotfix/23 v1.2.0
$ git worktree remove ../trailguide-review

Two rules: one branch can be checked out in only one worktree at a time, and removing the directory by hand leaves a stale entry, cleaned up with git worktree prune.

Worktrees are much lighter than a second clone: no second copy of the history, and no second remote to keep in sync.

Sparse checkout: part of a repository

In a monorepo, you may need docs/ and nothing else (lesson 13.10). Sparse checkout puts only what you name in your working directory, while the repository still contains everything.

Terminal
$ git sparse-checkout set docs
$ git sparse-checkout list
docs
Terminal
$ git sparse-checkout disable

Commits still cover the whole project, and a merge still merges everything; only the files on disk are limited. That distinction matters: sparse checkout is a working-directory feature, not a permissions feature, and it hides nothing from anyone.

Combine it with git clone --filter=blob:none for a large repository, and the clone fetches content only for the paths you check out.

Shallow clone

Terminal
$ git clone --depth 1 <url>

Fetches only the most recent commit. The clone is fast and small, and the trade is real:

Works Does not
Building, running, reading current files git log beyond the fetched depth
Making commits and pushing git blame for older lines
Ordinary branch work, mostly Merging with a base outside the fetched history

Shallow clones belong in throwaway environments, mainly CI, where speed matters and history does not. git fetch --unshallow converts one back into a full clone.

Partial clone

Terminal
$ git clone --filter=blob:none <url>

Fetches all the commits and trees but no file contents until something needs them. The history is complete, so git log works everywhere; the first git blame or checkout of an old commit fetches what it needs on demand.

For a large repository this is usually the better of the two: --depth truncates history, --filter merely defers content. It needs a server that supports it, which both platforms do.

Option Fetches Keeps working
--depth 1 One commit's history and content Only recent history
--filter=blob:none All history, content on demand Everything, with occasional pauses
--filter=tree:0 Even less, for automation Only with care

How to do it

Terminal
$ git worktree add ../review <branch>
$ git worktree list
$ git worktree remove ../review
$ git sparse-checkout set docs src
$ git clone --filter=blob:none <url>
$ git fetch --unshallow

Common mistakes

  • Checking out the same branch in two worktrees. Git refuses; use a detached checkout or a different branch.
  • Deleting a worktree folder by hand, leaving a stale entry until git worktree prune.
  • Using --depth 1 for daily work, then finding git blame and old history unavailable.
  • Expecting sparse checkout to hide files from others. It is local, and a merge still merges everything.
  • Forgetting a worktree exists, and wondering why a branch is "already checked out".

Try it yourself

Goal: review a branch without disturbing your own work.

  1. In your practice repository, leave an uncommitted change in place.
  2. Run git worktree add ../practice-review HEAD~1 and open that folder in your editor.
  3. Confirm your original folder still has the uncommitted change and its own branch.
  4. Run git worktree list and read both entries.
  5. Remove the worktree with git worktree remove ../practice-review, then try git sparse-checkout set docs and list before disabling it.

Expected result: two working directories on one repository, your unfinished work untouched, and a sparse checkout tried and reversed.

Show solution

Step 3 is the point. Everything a stash-and-switch does to your working directory, a worktree avoids entirely, because the second checkout is somewhere else. Once you have used it for a review, the "stash, switch, look, switch back, pop" routine starts to feel unnecessary.

Check yourself

1. What is a worktree?
2. What does --filter=blob:none fetch?
3. Does sparse checkout hide files from other people?

Key terms

Clone Branch Repository (repo) Monorepo