Git Worktrees

I was recently going through some of the videos on my subscription feed, catching up on new content when I found a video by, perhaps, one of my all-time favorite YouTubers: The Primeagen. His content is pretty amazing and he does a great job of talking about some of the more esoteric subjects of linux and vim, and actually making it interesting and entertaining. The video was named “Git’s Best and Most Unknown Feature”, and it was all about Git worktrees. Here’s a link to the video, I highly recommend it over reading my little schtick on how these wonderful feature works, but I’ll attempt to do it justice.

Worktrees are just directories

The title is exactly as it sounds: git worktrees are just directories. Say that you’re working on a project, especially one at work that has many people working on different branches of varying length and difficulty and are just all over the map. Now, you’ve gotten a call in the morning that there’s a bug that’s been found in the testing environment, and you’re going to be the one to fix it. Now, even worse, you’ve actually been working on the very project that has caused the issue in dev, and have many changes already made that you either need to A: do a gross halfsies commit that you’re going to have to squash later, or B: you need to stash your changes and pop them later. None of these options is very elegant or easy to work with, in fact they’re downright clunky and not all that great, which leads time to question why I had not heard of Git Worktrees before; they solve this problem, along with many other problems that you probably can’t even come up with.

Supplemental

Getting started

There’s nothing different or new I have to say about git clone --bare, other than when you do your clone, also run the following command: config --local --add remote.origin.fetch \"+refs/heads/*:refs/remotes/origin/*\". For some reason that escapes me, Git worktrees do not track remote by default, so effectively what you git without this config is a snaphsot in time. If your coworker adds a commit or a new branch, your local worktree directory will not be aware of this and will not be able to pull down the changes from the repo. What you cloned at the time is what you get.

Making a master worktree

The first thing you’re going to do is create a master worktree, this is literally going to be a directory that will be tracked, called master, that will be on the master branch. It is from this directory in which all other worktree add commands will occur. To create a master worktree is the same as creating any other: git worktree add ./master master. Git worktree add tells git to get the worktree magic going, and ./master master says to create a worktree called master, in the master directory, using the master branch.

Create a workspace

After creating your master worktree, create a directory in your root directory for you to store all your new worktrees. I like to call mine workspace, without this directory your root worktree directory will fill up quickly and it will quickly become confusing what’s a worktree you created vs the tooling for the root directory.

Using the master worktree

I love to use the master worktree when making more worktrees, it really simplifies things. To create more worktrees, use the command git worktree add ../workspace/<directory> <branch name> <commit-ish> while within your master worktree. This creates a worktree one directory back, using the HEAD in master as a source of truth. From here you can basically treat this as a normal project, except instead of just creating new branches, you create a new branch and a new directory.