What would I use git-worktree for?

I read Github's post on git-worktree. They write:

Suppose you're working in a Git repository on a branch called feature, when a user reports a high-urgency bug in master. First you create a linked working tree with a new branch, hotfix, checked out relative to master […] You can fix the bug, push hotfix, and create a pull request.

When I'm working on a branch called feature and some high-urgency bug in master is reported, I usually stash away whatever I'm working on and create a new branch. When I'm done, I can continue working. This is a very simple model, I've been working like that for years.

On the other hand, using git-worktree has its own limitations:

For example, it's not allowed to have the same branch checked out in two linked working trees at the same time, because that would allow changes committed in one working tree to bring the other one out of sync.

Why would I choose a more complicated workflow for a problem that's already been solved?

Is there anything about git-worktree that couldn't be done beforehand and that justifies this whole new, complex feature?


Solution 1:

For me, git worktree is the biggest improvement since a long time. I'm working in enterprise software development. There, it is very common that you have to maintain old versions like what you released 3 years ago. Of course you have a branch for each version so that you can easily switch to it and fix a bug. However, switching is expensive, because in the meantime you completely restructured the repository and maybe build system. If you switch, your IDE will run mad trying to adapt the project settings.

With worktree, you can avoid that constant reconfiguration. Checkout those old branches in separate folders using worktree. For each branch, you got an independent IDE project.

Of course this could have been done in the past by cloning the repo several times and this has been my approach so far. However, that also meant wasting hardrive space and worse needing to fetching the same changes from the repo several times.

Solution 2:

I can see some uses for this.

If you have a test suite that runs for a long time, imagine hours, and you start it it effectively blocks that working copy until the tests are completed. Switching branches during those tests would break them in ways that would be hard to understand.

So with git-worktree I could have a second idea launched for another branch doing work there.

Also, when I switch to some other branch to do some quick investigation my IDE thinks a lot of files suddenly changed and will index all those changes, just to have to re-index them again when I'm switching back.

A third use case would be to do file comparison using other tools than git-diff, like normal diff, between two directories instead if two branches.

Solution 3:

One obvious use is to simultaneously compare the behavior (not source) of different versions - for example different versions of a web site or just a web page.

I tried this out locally.

  • create a directory page1.

  • inside create the directory src and git init it.

  • in src create page1.html with a little content and commit it.

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • in src master add more text to page1.html and commit it.

  • $ git branch sty1

  • edit page1.html in the sty1 branch (add some distinctive CSS style) and add commit it.

  • $ git worktree add ../S1 sty1

You can now use a web browser to open and view these 3 versions simultaneously:

  • ..\page1\src\page1.html // whatever git has as current

  • ..\page1\V0\page1.html // the initial version

  • ..\page1\S1\page1.html // the experimentally styled version

Solution 4:

  1. There are legitimate reasons why you may want/need multiple worktrees in the filesystem at once.

    • manipulating the checked out files while needing to make changes somewhere else (eg. compiling/testing)

    • diffing the files via normal diff tools

    • during merge conflicts, I often want to navigate through the source code as it is on source side while resolving conflicts in the files.

    • If you need to switch back and forth a lot, there is wasted time checkout out and rechecking out that you don't need to do with multiple worktrees.

    • the mental cost of mental context switching between branches via git stashing is not really measurable. Some people find that there is mental cost to stashing that isn't there by simply opening files from a different directory.

  2. Some people ask "why not do multiple local clones". It is true that with the "--local" flag you don't have to worry about extra disc space usage. This (or similar ideas) is what I have done up to this point. Functional advantages to linked worktrees over local clones are:

    1. With local clones, your extra worktrees (which are in the local clones) simply do not have access to origin or upstream branches. The 'origin' in the clone will not be the same as the 'origin' in the first clone.

      • Running git log @{u}.. or git diff origin/feature/other-feature can be very helpful and these are either not possible anymore or more difficult. These ideas are technically possible with local clones via an assortment of workarouns, but every workaround you could do are done better and/or simpler through linked worktrees.
    2. You can share refs between worktrees. If you want to compare or borrow changes from another local branch, now you can.

Solution 5:

My absolute favorite and probably the most common use-case where everyone should use git worktree is reviewing the pull requests of team-mates, while still working on your changes in the main worktree. 😎