git-worktree

I am not sure how I discovered git-worktrees but I'm sure glad that I did. It has made a big difference in how many branches I can work on at once, while still remaining simple

Git uses worktrees internally but you can use them to make clone from your local repo instead of clone from the origin. However, the big feature is that it shares history with your local repo. So you act on it independently (even push and pull from remotes ) but it's kind of an extension from the local "main" repo. You can think of it as a local fork, if you will, but with a shared history. A good explanation from the main git documentation:

A git repository can support multiple working trees, allowing you to check out more than one branch at a time. With `git worktree add` a new working tree is associated with the repository, along with additional metadata that differentiates that working tree from others in the same repository. The working tree, along with this metadata, is called a "worktree".

This new worktree is called a "linked worktree" as opposed to the "main worktree" prepared by git-init or git-clone. A repository has one main worktree (if it is not a bare repository) and zero or more linked worktrees.

My common use is this: I have a develop branch checked out locally. I then make new worktree and make a new feature branch in that new worktree to work on that feature. If a bug comes up that needs fixing quickly, I either make a new bugfix branch from my main develop worktree or I make a new fix worktree, push and merge it from that folder. Once it is merged into develop, I can use git merge <bugfix-branch> in my feature worktree. I'll give a step-by-step example below.

Note that I don't push, or pull develop from my branches around develop. That is because they are sharing the same history and metadata files. So it simulates doing everything in that folder...but you are actually in different folders. This allows you to have different branches in different folder yet still have the name metadata/history in each. One interesting quirk is that you can't have have the same branch checked out by two different worktrees. So if you are working on BranchA on one worktree repo, you can't work on BranchA in another worktree folder . This seems weird but worktrees are not stand-alone - they all share the same git history.

I like Tomups git-worktree scripts. They not only manage creating the folders, but they also copy over ~.env~ files, node_modules folders, etc. I'll give an example of how I use them with my general workflow:

  1. I have a repo cloned locally and make sure that the develop branch is checked-out.
  2. I run git wtadd ../proj-new-feature which creates a worktree in the parent folder above my project called proj-new-feature
  3. I change to the proj-new-feature folder and make a feature branch just like normal: git checkout -b feature/fancy-new-thing
  4. I start doing my normal development work.
  5. Soon I'm told about a bug in the dev environment. I go to the folder where my develop branch is. It's a one-line fix, so I make a new branch there : git checkout -b bugfix/easy-bug
  6. Once I fix the bug and push it up, I can do back to my proj-new-feature folder.
  7. There I can merge in my bugfix/easy-bug branch easily with git merge bugfix/easy-bug. No pulling from remote, etc because the worktrees share the same history
  8. When I'm done I push the feature/fancy-new-thing branch to remote
  9. After the PR is merged in, I go back to development, pull in remote and then I can delete the feature worktree with git wtremove ../proj-new-feature

The cycle then continues.

With git worktrees I can have different features/branches active and they don't get in the way. It seems like a simple idea but really has made things easier in my workflow