← blog.mackieburgess

Git Worktrees

One of the most useful git extras which seemingly nobody knows about.

Mackie Burgess · 2023-11-06

Git Worktrees are amazing, I reap the benefits of them on a weekly basis, and can’t really imagine git without them; but if I imagine myself a few years ago I don’t think I’d even be able to begin wrapping my head around them.

A second pointer

A way to visualise a git repository is that you are sitting with a Directed Acyclic Graph of commits, and when you are looking at a project on your computer you are pointing to a singular commit.

There is a notion of named branches which simplifies moving around – you can git checkout <branch-name> to quickly hop over and see what’s going on – but you can also go to a commit with git checkout <commit>. You can find <commit> for commits on the graph by running git log --oneline --graph. This allows you to look at any point in the history for your project, including things outside of the main branch.

Generally this will put you into “detached head mode”, because you’re on a part of a branch which has since been updated. To get back to wherever you were, run git switch -, or you can turn your current location into the start of a new branch with git switch -c <new-branch-name>.

So Git is keeping track of this big graph, you can interface with one commit at a time, and you can jump somewhere else by pointing at a commit/branch. The beauty of worktrees is that they give you more pointers.

How to use Git worktrees

git worktree add <path/to/somewhere> <commit or branch>

That’s it. cd to the path you gave it, you’re now sitting in a copy of your project

You can also make a worktree which points to the same location as the original pointer by omitting the commit and branch.

What’s so good about this?

This feature opens up several different workflow opportunities which help me out regularly.

Showing two versions running at the same time

I seriously can’t think of another clean way to do this, and I’d be seriously annoyed having to live without it. A common use-case is wanting to show what the feature branch feature/bar looks like compared to dev, but dev isn’t deployed anywhere:

git worktree add ../feat-bar feature/bar

Or you could show the changes which have been made to a project in the past month:

# This is dumb but also amazing, and relatively practical.
git worktree add ../old main@{30.days.ago}
# Or...
git worktree add ../old main@{2023-10-01}

Multitasking without git stash

git stash is a great thing to compete with because quite a lot of people agree an alternative would be nice.

For the uninitiated, git stash gives a stack you can push changes to, and pop changes from. If you are working on something and need to quickly swap to something else, you must git stash -u your changes, change branch, make the change, reconcile the branch, change back to your original branch, then git stash pop.

With worktrees, your flow is simplified:

git worktree add ../zut-alors HEAD
cd ../zut-alors
# Do the fix; commit, merge, push, etc.
cd ../repo-name
rm -rdf ../zut-alors

git worktree prune can be used to clean things up after deleting the worktree file, but this isn’t necessary unless you reuse the worktree name.

Conclusion

Hopefully this has convinced you that worktrees are an awesome feature, but there is also a “friends we made along the way” conclusion I hope you can take away: there are a bunch of mechanisms for dancing around in Git, you just need to figure out how to take advantage of them.

If you knew about pretty much everything in this article, hopefully the main@{30.days.ago} caught you pleasantly by surprise :)