Boost your productivity with GIT worktree

TL;DR: Use git worktree add instead of git checkout -b for faster and easier development on multiple branches simultaneously.

Employing a git-flow-esque VCS technique in a development team makes you switch branches a lot:

  • working on a new feature
  • working on two features at the same time due to open questions etc.
  • fixing incoming bugs while working on a feature
  • doing code reviews for pull requests that are too inefficient to do in the browser

And everytime before you switch, you need to clean your workspace with a clean commit, “preliminary” commit (read: whatever is in the files at that moment, compiling or not) or stash (you do use named stashes, right?).

At times it can seem like a quarter of your time is spent on switching branches, especially when building the newly checked-out version takes a couple of minutes every time.

Maybe this leads you to clone the repo multiple times in different folders and check-out different commits in each one. Although that solves the original problem you run into new problems, like having to fetch once in each of your repos now and not being able to stash things in one repo and pop them in another, which often comes up when discovering bugs during feature development.

There is a remedy in form of a GIT feature from which I do not hear often, but has been around since version 2.5 in 2015: git worktree.

Git worktree allows you to have multiple checked-out branches in different file system folders without the hassle of having multiple local repos. When checking out a new branch, instead of your usual git checkout -b feature/my-new-feature you can do this

git branch feature/my-new-feature
git worktree add ..\mynewfeature feature/my-new-feature

Assuming you do this in your GIT repo’s root folder (the one with the .git folder in it), this will create a new file system folder mynewfeature at the same hierarchy level as your original repo and provide you with a fresh copy of everything there. You may notice that your git-provided repo folder copy has a .git file (in contrast to .git folder). This is a text file telling git where the original repo (the one with the .git folder with all the git data) is.

If you require files for development that are not under version control (e. g. appsettings.Development.json in an ASP.NET project), you will need to copy them from your original repo folder to the new worktree folder (putting the three lines for git branch, git worktree and cp in a script for easy usage is left as an exercise for the reader).

Once you are done with working that branch, you just do

git worktree remove ..\mynewfeature

from your repo’s root folder and have GIT remove the repo folder copy. The branch will still exist and needs to be deleted separately as usual.

The only limitation is that you cannot have two worktree folders for the same branch.

With multiple worktree folders you only need to git fetch once (it does not matter in which worktree folder). You can also stash and pop and cherry-pick from one worktree folder to another. In case you have a long-running git bisect run you can also let that do its magic on one worktree folder and keep working on other things in another.

Convenient.

My current workflow is in fact to have a file system folder mycurrentproject with a develop subfolder that is the home of the GIT repo and always points to the develop branch. From there I constantly create and remove worktree folders within the mycurrentproject folder, whether for features, bugfixes or code reviews.

No need to save the work and later remember to amend/pop/whatever again. Just leave the feature folder like it is and get a fresh checkout via git worktree!