Worktrees, sparse checkout, shallow and partial clone
Expert Git CLI
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.
$ git worktree add ../trailguide-review HEAD~1Preparing worktree (detached HEAD b81702c)
HEAD is now at b81702c docs: add getting started guide and FAQ$ 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 |
$ git worktree add ../trailguide-hotfix -b hotfix/23 v1.2.0
$ git worktree remove ../trailguide-reviewTwo 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.
$ git sparse-checkout set docs
$ git sparse-checkout listdocs$ 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
$ 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
$ 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
$ 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 --unshallowA worktree is an ordinary folder, so File → Open Folder on it works and gives you two windows on the same repository. VS Code has no sparse-checkout interface; set it in the terminal and the Explorer follows.
The same: open the worktree as a project. IntelliJ handles multiple roots, and the worktree level of configuration exists for exactly this case (lesson 18.2).
Nothing platform-specific. Large-repository features that do concern the platform are LFS and the repository size limits (lesson 18.9).
The same; GitHub's servers support partial clone filters.
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 1for daily work, then findinggit blameand 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.
- In your practice repository, leave an uncommitted change in place.
- Run
git worktree add ../practice-review HEAD~1and open that folder in your editor. - Confirm your original folder still has the uncommitted change and its own branch.
- Run
git worktree listand read both entries. - Remove the worktree with
git worktree remove ../practice-review, then trygit sparse-checkout set docsandlistbefore 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.