What is this?1
It basically solve the problem of caching your changes when you want to switch from a feature to another without committing.
Before that, I generally used to do this by stashing my changes then reapplying them afterwards, but clearly that was slow and error prone.
How to
First, this workflow makes more sense with bare repos, you can of course create worktrees out of regular repositories, but in that case make sure to place them outside the original repo.
Let’s begin by cloning a repo using the --bare
option:
/tmp
⟩ git clone --bare https://github.com/xmonad/xmonad.git
A bare repo is just the content of the .git
directory:
/tmp/xmonad.git · (master)
⟩ ll
Permissions Size User Date Modified Name
drwxr-xr-x - david 18 juil. 12:23 branches
.rw-r--r-- 128 david 18 juil. 12:23 config
.rw-r--r-- 73 david 18 juil. 12:23 description
.rw-r--r-- 23 david 18 juil. 12:23 HEAD
drwxr-xr-x - david 18 juil. 12:23 hooks
drwxr-xr-x - david 18 juil. 12:23 info
drwxr-xr-x - david 18 juil. 12:23 objects
.rw-r--r-- 2,2k david 18 juil. 12:23 packed-refs
drwxr-xr-x - david 18 juil. 12:23 refs
Add a worktree:
/tmp/xmonad.git · (master)
⟩ git worktree add master
Preparing worktree (checking out 'master')
HEAD is now at af354f7 Merge pull request #312 from mzrinsky/update-cheatsheet
We can see that a new directory "master"
has appeared2:
/tmp/xmonad.git · (master)
⟩ ll
Permissions Size User Date Modified Name
drwxr-xr-x - david 18 juil. 12:23 branches
.rw-r--r-- 128 david 18 juil. 12:23 config
.rw-r--r-- 73 david 18 juil. 12:23 description
.rw-r--r-- 23 david 18 juil. 12:23 HEAD
drwxr-xr-x - david 18 juil. 12:23 hooks
drwxr-xr-x - david 18 juil. 12:23 info
drwxr-xr-x - david 18 juil. 12:24 master
drwxr-xr-x - david 18 juil. 12:23 objects
.rw-r--r-- 2,2k david 18 juil. 12:23 packed-refs
drwxr-xr-x - david 18 juil. 12:23 refs
drwxr-xr-x - david 18 juil. 12:24 worktrees
In it, there is indeed the content of master:
/tmp/xmonad.git/master · (master)
⟩ ll
Permissions Size User Date Modified Name
.rw-r--r-- 130 david 18 juil. 12:24 cabal.haskell-ci
.rw-r--r-- 43 david 18 juil. 12:24 cabal.project
.rw-r--r-- 8,2k david 18 juil. 12:24 CHANGES.md
.rw-r--r-- 2,3k david 18 juil. 12:24 CONFIG
.rw-r--r-- 5,9k david 18 juil. 12:24 CONTRIBUTING.md
.rw-r--r-- 5,8k david 18 juil. 12:24 INSTALL.md
.rw-r--r-- 1,5k david 18 juil. 12:24 LICENSE
.rw-r--r-- 526 david 18 juil. 12:24 Main.hs
.rw-r--r-- 3,9k david 18 juil. 12:24 MAINTAINERS.md
drwxr-xr-x - david 18 juil. 12:24 man
.rw-r--r-- 4,2k david 18 juil. 12:24 README.md
.rw-r--r-- 76 david 18 juil. 12:24 Setup.lhs
drwxr-xr-x - david 18 juil. 12:24 src
.rw-r--r-- 447 david 18 juil. 12:24 stack.yaml
.rw-r--r-- 771 david 18 juil. 12:24 STYLE
drwxr-xr-x - david 18 juil. 12:24 tests
.rw-r--r-- 51k david 18 juil. 12:24 TUTORIAL.md
drwxr-xr-x - david 18 juil. 12:24 util
.rw-r--r-- 5,5k david 18 juil. 12:24 xmonad.cabal
Let’s go back and add another worktree:
/tmp/xmonad.git · (master)
⟩ git worktree add update_readme
Preparing worktree (checking out 'update_readme')
HEAD is now at af354f7 Merge pull request #312 from mzrinsky/update-cheatsheet
Use git worktree list
to list the worktrees:
/tmp/xmonad.git · (master)
⟩ git worktree list
/tmp/xmonad.git (bare)
/tmp/xmonad.git/master 67b010a [master]
/tmp/xmonad.git/update_readme 67b010a [update_readme]
Let’s go to the update_readme directory and edit the Readme, then commit the changes:
/tmp/xmonad.git/update_readme · (update_readme±)
⟩ git commit -am 'Update readme.'
Then go to the master worktree and merge the changes:
/tmp/xmonad.git/master · (master)
⟩ git merge update_readme
Updating af354f7..67b010a
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
The obvious advantage of this method is that we can easily create as many worktrees as needed, and switch between them in a split second.
Manage worktrees from Emacs with Magit
Magit support worktrees natively, to use them just run the following command:
M-x magit-worktree
A menu will pop, and you will be able to choose between different options, to create a worktree and a branch like above, type “c”.
You will then be asked to provide:
- the path and the name of the worktree
- the branch or tag from which to checkout
- the name of the branch
How to delete a worktree
git worktree remove [name]
Footnotes
I discovered it with this video, go watch it if you prefer this format.↩︎
If you reference an existing branch, then git will add a worktree referencing that branch. In the other case, git will create a new branch from master.↩︎