Skip to content
shellhacks.dev
Git

How to Use git worktree for Several Branches at Once

Work on several branches at once with git worktree: add, list and remove linked checkouts, avoid the one-branch rule traps and clean up stale entries.

6 min read
Summarize in AI
Illustration for "How to Use git worktree for Several Branches at Once": a terminal session, a loop arrow, a signal bolt.

An urgent fix arrives while you are halfway through a feature. The usual routine is to stash, switch branches, fix, switch back and pop the stash, and every step is a chance to lose or mix up work. A worktree gives the second task its own directory, with its own index and checked-out branch, while sharing history with the first. It extends the ideas in stash and branching. The commands assume Git 2.47.

Add a worktree

Shell
cd ~/code/app
git worktree add ../app-hotfix hotfix/login-timeout
git worktree add -b feature/report ../app-report origin/main
git worktree list
Text
/home/ada/code/app          8f2d1c4 [main]
/home/ada/code/app-hotfix   b1f7a92 [hotfix/login-timeout]
/home/ada/code/app-report   8f2d1c4 [feature/report]

The first form checks out an existing branch in a new sibling directory. The second creates a new branch from origin/main and checks it out. Each directory is a normal working tree: build, edit and commit there. Because the history is shared, a commit made in one worktree is visible to all of them at once.

The one-branch rule

Shell
git worktree add ../app-main main
Text
fatal: 'main' is already used by worktree at '/home/ada/code/app'

Git refuses to check out one branch in two places, because commits in one would silently move the branch under the other. For a read-only look at the same commit, use a detached checkout: git worktree add --detach ../app-inspect main. That is also how you check out a tag or a commit hash.

Remove and clean up

Shell
git worktree remove ../app-hotfix
git worktree prune --verbose
git worktree lock --reason "on external drive" ../app-report

remove deletes the directory and the record, and refuses if there are uncommitted changes unless you add --force. If you delete the directory by hand, Git keeps a stale record; prune removes records whose directories are gone. lock protects a worktree on removable media from pruning when the drive is unmounted.

Practical notes

Dependencies and build outputs are per directory, so each worktree needs its own node_modules or virtual environment. Keep them in a predictable place, such as a worktrees directory beside the main checkout, to avoid hunting. Tools that look for a .git directory find a file there instead, which points to the shared repository, and a few old tools do not understand it. Branches you pushed are visible in all worktrees without fetching again.

Where this does not apply

Submodule support in linked worktrees is limited, so repositories that rely on submodules are awkward. For a one-minute detour, stash is simpler. A second full clone is heavier but isolates everything, including hooks and config, if you need that. When you finish a task, merge or delete the branch as in deleting branches.

What a worktree shares and what it does not

A linked worktree is a second working directory attached to the same repository. It shares the object database, the refs and the configuration with the main one, so there is one set of history, and a commit made in either is visible from both at once. It has its own checked-out branch, its own index and its own working files. The metadata for each linked tree lives under .git/worktrees/ in the main repository, and the linked directory holds a small .git file that points back. That design is why creating one takes a moment and little disk space, compared to cloning, which copies the history. It is also why the stash is shared: stashed changes made in one worktree show up in the stash list of the others, which can cause a confusing moment when you pop an entry made somewhere else.

Hooks, the ignore rules in the repository and the local configuration are shared. Per-worktree configuration needs extensions.worktreeConfig enabled, and it is rarely required.

Why one branch cannot be in two places

Git refuses to check out a branch that is already checked out in another worktree, since two working trees moving the same branch would overwrite each other's commits. The error names the path that holds the branch. To work on the same code in a second place, create a new branch for it, or use a detached head with --detach for read-only work such as testing a release. This rule is a protection, and the override option exists but invites lost work. If you see the message and do not remember where the branch is checked out, git worktree list shows every tree and its branch, which solves it. A tree whose directory was deleted without telling Git stays listed as prunable, and git worktree prune removes the record.

Submodules work less smoothly in linked worktrees, and the support is documented as incomplete, so a repository with submodules may need extra care or a plain clone.

Where worktrees pay off

The best uses are the ones where switching branches costs too much. Reviewing a pull request while your own work is half finished is the classic case: add a worktree for the review branch, run the tests there, and return to your own directory with nothing stashed and no files changed. Long builds are another: a worktree keeps its own build output, so switching between releases does not trigger a full rebuild each time. Running the old and new versions side by side to compare behavior, and applying an urgent fix to a release branch without disturbing a feature in progress, both fit. Keep worktrees in a sibling folder named after the branch, so you can see at a glance what exists, and delete them when the work is done.

Editors and tools that index a directory treat each worktree as a separate project, which can double the memory they use and confuse search results across copies. Open one window per worktree and close it when the tree is removed.

Housekeeping and mistakes to avoid

List your worktrees from time to time with git worktree list and remove the ones you no longer need with git worktree remove, which refuses to delete a tree that has uncommitted changes unless you force it. Deleting the folder by hand leaves a stale record that git worktree prune cleans up. A branch that was checked out in a removed worktree is free again afterwards. Lock a worktree on removable or network storage with git worktree lock so a missing drive does not cause the record to be pruned, and release the lock when the drive is back.

Keep installed dependencies in mind. Each tree needs its own packages and build output, so a project with a large dependency folder uses that much space again per worktree, and tools that install into a shared cache help. Create the new tree, install, and run the tests there before you rely on it, since a missing environment file or ignored configuration that exists only in the original directory will make the second copy behave differently, and that is the usual explanation when a bug appears in only one of two checkouts.

See git-worktree and the repository layout that explains the shared data.

Taggedgit
Share

Keep reading

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.