Git Worktrees: Work on Multiple Branches at Once
Table of Contents
Git normally only lets you have one branch checked out at a time. Want to review a coworker's PR while you're halfway through a refactor? You're either stashing, committing WIP garbage, or cloning the whole repo again. Git worktrees fix this: they let you check out multiple branches at once, each in its own directory, all connected to the same repository.
All the content from our Boot.dev courses are available for free here on the blog. This one is the "Worktrees" chapter of Learn Git 2. If you want to try the far more immersive version of the course, do check it out!
What Is a Git Worktree?
Here's a fun fact: if you've ever used Git, you've been using a worktree the whole time, probably without knowing it had a name.
A worktree (or "working tree" or "working directory") is just the directory on your filesystem where the code you're tracking with Git lives. Usually, it's just the root of your Git repo (where the .git directory is). It contains:
- Tracked files (files that Git knows about)
- Untracked files (files that Git doesn't know about)
- Modified files (files that Git knows about that have been changed since the last commit)
But where it gets fun is that you can have more than one worktree for the same repo. Git ships with the git worktree command to manage them. Say you've got a repo called megacorp cloned at /home/prime/megacorp:
git worktree list
# /home/prime/megacorp d5f2a1b [main]
One repo, one worktree. Boring. Let's make more.
Worktrees vs Branches, Stash, and Clone
Git already gives you a few ways to work on different changes without losing work:
- Stash (temporary storage for changes)
- Branches (parallel lines of development)
- Clone (copying an entire repo)
Worktrees accomplish a similar goal, but they're particularly useful when:
- You want to switch back and forth between two change sets without running a bunch of
gitcommands (rules out branches and stash) - You want to keep a light footprint on your machine that's still connected to the main repo (rules out clone)
A second clone technically works, but now you have two full copies of the repo's entire history eating your disk, and they don't know about each other. Worktrees give you two directories without the duplication.
Main Worktrees vs Linked Worktrees
There are two kinds of worktrees, and the difference comes down to what's inside them.
The main worktree:
- Contains the
.gitdirectory with the entire state of the repo - Heavy (lots of data in there!). Getting a new main working tree requires a
git cloneorgit init
A linked worktree:
- Contains a
.gitfile with a path to the main working tree - Light (essentially no data in there!), about as light as a branch
- Can be complicated to work with when it comes to env files and secrets
| Main worktree | Linked worktree | |
|---|---|---|
.git |
Directory with full repo state | File pointing at the main worktree |
| Weight | Heavy | About as light as a branch |
| How you get one | git clone or git init |
git worktree add |
If you want to understand what's actually inside that .git directory, read Git Internals.
How Do You Create a New Worktree?
To create a linked worktree at a given path:
git worktree add <path> [<branch>]
The <branch> is optional. If you leave it off, Git uses the last part of the path as the branch name.
From the root of megacorp, add a second worktree as a sister directory:
git worktree add ../ultracorp
# Preparing worktree (new branch 'ultracorp')
Now peek at the .git file inside the new worktree. Notice it's just a path back to the main working tree:
cat ../ultracorp/.git
# gitdir: /home/prime/megacorp/.git/worktrees/ultracorp
And git worktree list shows both:
git worktree list
# /home/prime/megacorp d5f2a1b [main]
# /home/prime/ultracorp d5f2a1b [ultracorp]
You can now cd between two branches like they're just... directories. Because they are.
One Branch Per Worktree
Linked worktrees behave just like a "normal" Git repo. You can create new branches, switch branches, delete branches, create tags, etc.
BUT there is one thing you cannot do: you cannot work on a branch that is currently checked out by any other working tree (main or linked). Try to git switch to main from a linked worktree while your main worktree has it checked out, and Git shuts you down:
git switch main
# fatal: 'main' is already used by worktree at '/home/prime/megacorp'
The official recommended workflow here is: attempt the switch, read the error, cry.
It makes sense though. If two worktrees had the same branch checked out, a commit in one would leave the other pointing at a stale state of the same branch. Git just refuses to let that happen.
How Does Git Track Linked Worktrees?
So how does your main worktree know about your linked worktrees? The references are stored in the .git/worktrees directory of the main worktree:
ls .git/worktrees
# ultracorp
And when you make a change in a linked worktree, that change is automatically reflected in the main worktree! It makes sense: the linked worktree doesn't have a .git directory, so it's not a separate repository. It's just a different view of the same repository.
Commit on the ultracorp branch from the linked worktree, and the main worktree sees it immediately. Check the log from the root of megacorp:
git log ultracorp --oneline -1
# 8f3e2a1 draft hostile takeover plans
You can almost think of a linked worktree as just another branch in the same repo, but with its own space on the filesystem. Same object database, same remotes, same history. Just more directories.
How Do You Remove a Worktree?
You may never need to stash again! Okay, stash is still useful for tiny stuff, but worktrees are so much better for long-lived changes.
At some point though, you'll need to clean up your worktrees. The simplest way is the remove subcommand:
git worktree remove ultracorp
An alternative is to delete the directory manually, then prune all the worktrees, which removes the references to deleted directories:
rm -rf ../ultracorp
git worktree prune
One gotcha: removing a worktree does not delete its branch. Run git branch after the removal and you'll see the ultracorp branch is still there, only the worktree is gone. Delete the branch separately with git branch -d if you're done with it.
Worktrees are one of those features that most Git users never touch, right up there with reflog and bisect. If you're still getting comfortable with the fundamentals, start with Learn Git; if you're ready for the power tools, Learn Git 2 covers worktrees and the rest of the advanced workflows hands-on.
Frequently Asked Questions
What is a git worktree used for?
A worktree is the directory where your tracked code lives. Extra linked worktrees let you check out multiple branches at the same time in separate directories, all connected to the same repository.
What is the difference between a git worktree and a branch?
A branch is a line of development inside the repo, while a worktree is a directory on disk. A linked worktree gives a branch its own directory so you can work on two branches at once without switching.
Can two worktrees check out the same branch?
No. Git refuses to let a branch be checked out in more than one worktree at a time, because commits in one worktree would leave the other pointing at a stale state.
Does git worktree remove delete the branch?
No. git worktree remove only deletes the worktree directory and its reference. The branch it had checked out still exists and must be deleted separately with git branch -d.
What does git worktree prune do?
It cleans up stale worktree references in the .git/worktrees directory, which is useful after you delete a linked worktree's directory manually instead of using git worktree remove.
