This post is about the awesome
git worktree, that simplified my personal workflow with git very much.
In the past I had at least 2 versions of repository checked out locally or fiddled around with
git stash to find
a thing I did weeks ago.
But let’s talk about how I use git and how
git worktree helped me.
When I’m reviewing a Pull or Merge Request, sometimes I would like to see the code in my own IDE instead of the
GitLab or GitHub UI.
Normally I have a single clone of a repository on my local machine and I’m in the process of adding new features or
fixing a bug myself.
So I don’t want to commit things just yet, but just check out another branch.
I know I could use
git stash or create a
WIP commit and then amend by providing a good
commit message later, but almost all the time I forget about my existing stash or the earlier
Another time I’m starting to work on an improvement or simply experimenting with an implementation detail and therefore also don’t want to commit anything just yet.
At last, I want to update one of my branches with the current state of the
main branch or want to verify that something
is working or not working on the current
main branch in comparison to my branch.
Working with worktree
The solution to all of these problems is to use
git worktree and have multiple branches checkout out locally at the
To be as flexible as possible I tend to use the following structure for all repositories where I think I’ll need multiple branches checkout out at the same time:
➜ upstream-watch pwd /home/aps/Code/github/upstream-watch ➜ upstream-watch ls -l total 8 drwxr-xr-x 5 aps aps 4096 Jan 11 08:27 my-feature-1 drwxr-xr-x 6 aps aps 4096 Jan 11 08:26 upstream-watch-main
So I got a
<repo-name>--main for the main branch and additional branches was
Another feature you get with this is you get a clean state and can open your IDE in a new folder.
This could be annoying if you have a lot of custom configuration (like local
.env files, which are ignored by
git), but for most of the changes I don’t need these.
The main clone of the repository is always repository-name-main.
To not pollute my local file structure I tend to have each project in a dedicated directory under my
To create a new worktree checkout you simply have to use
git worktree add -b my-feature-1 ../my-feature-1.
If you don’t want to create a new branch then simply skip the
-b my-feature-1 from the command above and use it like this
git worktree add ../my-feature-1.
You can also list all your existing worktrees with from any worktree of the cloned repository:
➜ my-feature-1 git:(my-feature-1) git worktree list /home/aps/Code/github/upstream-watch/upstream-watch-main c477b51 [main] /home/aps/Code/github/upstream-watch/my-feature-1 c477b51 [my-feature-1]
I’m lazy, so I’m mostly using this very simple wrapper script to create new worktrees.
Then I’ll simply call
cw my-feature, when you store the scrip below as
cw (short for create worktree) in your local
#!/bin/bash set -euo pipefail name=$1 git worktree add ../$name -b $name printf "Created worktree at: %s \n" "../$name"
Deleting a worktree is as simple as
git worktree remove ../my-feature-1.
This also enables the usage of
git cherry-pick between multiple worktrees, which is very neat when you find a bug while
working on another task.
Simply commit it on your current working branch and pick it into a
fix-bug-xxx branch afterwards and create
a dedicated MR/PR for this fix.
git worktree simplified my personal workflow with git and saves some (not so expensive anymore) space on my local disk,
as I don’t need multiple versions of a repository on my local machine.
worktree is a rather old git feature, but nevertheless it is very useful and I know a lot of people that are not using it (yet).