Lesson 1 of 5 in Power Tools
Worktrees
Story: Two eras open at once, Agent. The bureau gives you a desk in each, and one archive behind them both.
You're halfway through something on a branch. Files are changed, and nothing is ready to commit. Then something else needs doing right now, on another branch: a fix on main, or a look at a teammate's work.
So far you've had two ways out: commit the half-done work, or put it away with git stash and bring it back later. Both mean packing up first. A worktree lets you leave everything exactly where it is and work on the other branch in a second folder.
A second folder for the same repository
git worktree add <folder> <branch> makes a new folder with that branch checked out:
$ git worktree add ../hotfix main
Preparing worktree (checking out 'main')
HEAD is now at d93b13a Add a stylesheet
.. is the folder above ~/project, so the new folder is ~/hotfix. Now one repository has two working trees: two folders, each with its own HEAD, its own staging area and its own files. They share everything else, every commit and every branch.
git worktree list lists them, with the commit and the branch each one has checked out:
$ git worktree list
/home/learner/project d93b13a [contact]
/home/learner/hotfix d93b13a [main]
The first one is the main worktree, the folder where the repository was made or cloned. The others are linked worktrees.
cd ../hotfix to work there. Everything you do in ~/hotfix happens on main, and your unfinished files in ~/project stay as they are. When you commit, the commit is on main straight away, in both folders. They're one repository, so there's nothing to push or pull between them.
In the Live Graph, the worktrees share one band, with one HEAD label for each worktree. The label of the worktree the Terminal is in is filled.
One branch, one worktree
A branch can be checked out in only one worktree at a time. Otherwise a commit in one folder would move the branch out from under the other. While ~/hotfix has main, git won't check it out anywhere else:
$ git switch main
fatal: 'main' is already used by worktree at '/home/learner/hotfix'
git worktree add refuses in the same way. git branch marks a branch that another worktree has checked out with a +:
$ git branch
* contact
+ main
The folder's branch, a new branch, or no branch at all
Leave the branch out, and git worktree add uses the branch named after the folder. If you don't have a branch with that name, it makes one:
$ git worktree add ../experiment
Preparing worktree (new branch 'experiment')
HEAD is now at d93b13a Add a stylesheet
The new branch starts at the commit you're on, in the worktree where you typed the command. Check that's where you want it to start.
If you do have a branch with that name, git makes no new branch. It checks out the branch you have, at its own commit, just as if you'd named it: git worktree add ../main is git worktree add ../main main. So while ~/hotfix has main, it refuses:
$ git worktree add ../main
Preparing worktree (checking out 'main')
fatal: 'main' is already used by worktree at '/home/learner/hotfix'
Name a branch you don't have yet, but origin does, and git makes it for you from origin/<branch> and sets it to track that, just as git switch would. Run git fetch first, so your repository knows about the branch.
Name a commit instead of a branch, such as a commit id or origin/main, and the new worktree starts with a detached HEAD:
$ git worktree add ../review d93b13a
Preparing worktree (detached HEAD d93b13a)
HEAD is now at d93b13a Add a stylesheet
To make a new branch with a name of your own, add -b <name> before the folder. The branch starts at the commit you name after the folder, or at the commit you're on if you leave it out:
$ git worktree add -b fix ../fix main
Preparing worktree (new branch 'fix')
HEAD is now at d93b13a Add a stylesheet
~/fix has the new branch fix checked out, starting at main's commit. As with git switch -c, the name must be one you don't have yet, and a branch started at a remote-tracking branch, such as origin/gallery, tracks it.
Removing a worktree
When you're done with a worktree, cd out of it and remove it:
$ cd ../project
$ git worktree remove ../hotfix
This deletes the folder and git's record of it. The branch and its commits stay: they belong to the repository, not to the folder.
git won't remove a worktree that has changes you haven't committed, so nothing gets lost by accident:
$ git worktree remove ../experiment
fatal: '../experiment' contains modified or untracked files, use --force to delete it
Commit the changes, or throw them away, first. And you can't delete a branch while a worktree has it checked out:
$ git branch -d experiment
error: cannot delete branch 'experiment' used by worktree at '/home/learner/experiment'
Remove the worktree first, then delete the branch.
On your own computer
git worktree remove --force removes a worktree even with changes in it, and loses them. If you delete a worktree's folder by hand, git worktree prune clears away git's record of it. This Terminal doesn't run either of them.
| Command | What it does |
|---|---|
git worktree add <folder> <branch> |
Checks the branch out in a new folder. No other worktree can have it checked out. |
git worktree add <folder> |
Checks out the branch named after the folder. If you don't have one, makes it first, from the commit you're on. |
git worktree add -b <name> <folder> <commit> |
Makes a new branch, <name>, at the commit, and checks it out in a new folder. Without the commit, it starts at the commit you're on. |
git worktree list |
Lists the worktrees: each one's folder, commit and branch. |
git worktree remove <folder> |
Deletes a worktree's folder. Its branch and commits stay. |
New commands
git worktree addgit worktree add -bgit worktree listgit worktree remove
Explainer: Two folders, one repository
Graph as text
project: your repo, you are here
- HEAD → contact at d93b13a "Add a stylesheet"
Branches and tags
- contact at d93b13a "Add a stylesheet"
- main at 07bdad5 "Fix a typo on the home page"
Commits, newest first
- 07bdad5 "Fix a typo on the home page"; parent d93b13a; refs: main
- d93b13a "Add a stylesheet"; parent 5393c91; refs: HEAD → contact
- 5393c91 "Add the home page"; no parent
Challenge 1 of 3
Story: Leave your desk exactly as it is, Agent. The urgent job gets a desk of its own.
You're halfway through a contact page on contact, and none of it is committed. Leave that work exactly where it is.
Meanwhile, the teal heading on main is hard to read. Check main out in a second folder, ~/hotfix, and fix it there: change style.css to h1 { color: navy; } and commit it on main.
Unlocks after Rewriting History.
Terminal
Unlocks after Rewriting History.
This Lesson can be played once Rewriting History is complete. Its text and Explainer are open to everyone.