A bit of vocabulary
Repository, working tree and bare repository
clone a git repository into a directory, you are, by default, left with 2 entities:
- The repository who takes by default the form of a
.gitdirectory. It contains all the technical files and directories needed by git to maintain the project's versions.
- The working tree which is all the files and directories that are under version control.
A bare repository is a repository without a working tree. It only contains
what you would normally find under the
It can be used as a remote! Indeed you can clone a repository from a local directory if this last contains a bare instance of a git repository.
stash is a git command that allows you to record the current state of the
working tree and the index and then go back to a clean working tree. These
records are stored on a stack that can be visualized with
git stash list.
To recover the last record from the stack, run
git stash pop.
Setting the scene
If you had never heard about the command
git worktree before, there is a good
chance you think that you can only have one branch or commit checked out at a
This belief leads you to this inconvenient situation, when, for instance, you need to abandon your work in progress in one branch,
- to support a colleague on another branch,
- address this review comment on your pending pull request,
- fix this bug spotted on QA stage that is a no go for going live,
- or worst in case of LIVE outage and that you need to deliver a hotfix as soon as possible.
If the work is not in a state where you would commit it; quite often, if you are
aware of the
git stash command, you would:
- stage your work
- stash it
- check out the branch that need to be worked on
- do the work
- stage, commit, and push
- check out the branch you were formely on
- pop the last stashed piece of work
And then only you can proceed with you work.
Phew, that is a lot of inconvenience.
git worktree to the rescue
git worktree you can link other working trees to your repository.
Taken we are working on the
new-feature branch and that we need to abandon the
work to create a hotfix for the
In the Terminal, and from the root of the directory that hosts the current working tree, run:
$ git worktree add ../hotfix main
This has created a new working tree, checked out to the
main branch, inside of
Now you can move to this directory to create the fix.
Stage, commit and push.
If you come back to your previous directory, you should still have the
new-feature branch checked out, and you should be able to resume your work
where you left it at. Joy!
At some point you also may want to get rid of the
hotfix worktree. Then run:
$ git worktree remove hotfix
If at anytime you want to show the existing worktree for a repository, run:
$ git worktree list
Adding working trees in the parent or the current directory can quickly become a mess.
A better working trees organization
I find that an organization like the one below is much more tidy!
my-awesome-project - git-technical-directory - new-feature - hotfix
bare repository and .git file to the rescue!
Indeed we can proceed like the following:
$ mkdir my-awesome-project $ cd my-awesome-project $ git clone --bare email@example.com:myname:my-awesome-project.git .bare $ echo "gitdir: ./.bare" > .git
So far, we created a directory for our project,
cd into it, clone
my-awesome-project as a bare repository into a
.bare directory. This
directory contains what the
.git directory contains if we would have gone for
git clone command.
Where it is executed, the
git command either refer to a
.git directory or to
.git file. This last needs though to contain a pointer to the repository
directory. The pointer is the
Actually in every directory created by the
git worktree add command, you can
.git file that contains this
Now it is time to create the 2 worktrees:
$ git worktree add new-feature $ git worktree add hotfix master
At this stage our directory looks like:
my-awesome-project - .bare - .git - new-feature - hotfix
This is pretty close from what we were aiming for and much better than this mess:
hotfix my-awesome-project - .git - .gitignore - assets - index.html - package.json ... - README.md
I hope this
git worktree is as good breaking news for you as it was for me and
that it will improve you git experience.
Update January 14th, 2022
After using Git worktrees for a few weeks, in the manner described in this blog post, I have noted two inefficiencies.
The good news is that I came up with solutions to cover up for them. You will find them as part of these complementary blog posts:
- Workarounds to Git worktree using bare repository and cannot fetch remote branches
- (Coming soon!) Git hook to have a npm based project to install dependencies at checkout