Skip to content

How to Use Git Worktree for Parallel Branch Development

Problem

I was working on a feature branch, and everything was going well. Then my manager asked me to fix a critical bug on the main branch immediately.

The problem? My feature branch had half-done changes. I did not want to commit incomplete code. I also did not want to lose my work.

I tried stashing:

Stashing changes
git stash

But I kept forgetting about my stashed changes. Sometimes I created multiple stashes and lost track of them.

I tried committing with a temporary message:

Temporary commit
git add .
git commit -m "WIP: feature in progress"

But this polluted my commit history. I had to amend or squash later. It was messy.

There had to be a better way.

Environment

  • Git version: 2.43.0
  • Operating System: macOS Sonoma
  • Repository: A monorepo with multiple features in development

What happened?

I was in the middle of developing a new feature on a branch called feat/user-authentication. I had modified several files but the feature was not complete. The tests were failing.

Then I received a bug report. The bug was on the main branch and needed immediate attention.

I ran:

Switching branches with uncommitted changes
git checkout main

Git refused:

Terminal window
error: Your local changes to the following files would be overwritten by checkout:
src/auth/login.ts
src/auth/register.ts
Please commit your changes or stash them before you switch branches.
Aborting

I had to choose between:

  1. Stashing (and risking forgetting about it)
  2. Committing incomplete work (messy history)
  3. Copying files to a backup folder manually (error-prone)

None of these options felt right. I asked a senior developer, and they introduced me to Git worktree.

How to solve it?

Git worktree lets you checkout multiple branches into separate directories from a single repository. You can have multiple working directories, each with a different branch, without cloning the repository multiple times.

Step 1: Create a worktree

I created a new worktree for the bug fix:

Creating a worktree
git worktree add ../bugfix-login main

This created a new directory called bugfix-login at the same level as my main repository. The new worktree was already on the main branch.

Output:

Terminal window
Preparing worktree (checking out 'main')
HEAD is now at a1b2c3d Fix navigation bug

Step 2: List all worktrees

To see all my worktrees:

Listing worktrees
git worktree list

Output:

Terminal window
/Users/zhaocaiwen/projects/myapp a1b2c3d [main]
/Users/zhaocaiwen/projects/bugfix-login a1b2c3d [main]

Wait, both showed the same branch. I needed to create a new branch for my bug fix:

Creating worktree with new branch
git worktree add ../bugfix-login -b fix/login-redirect main

Output:

Terminal window
Preparing worktree (new branch 'fix/login-redirect')
HEAD is now at a1b2c3d Fix navigation bug

Now I could work on the bug fix in the bugfix-login directory while my original feature work remained untouched in the main repository.

Step 3: Work in the new worktree

I navigated to the new worktree:

Navigating to worktree
cd ../bugfix-login

Now I could make changes, run tests, and commit as usual. My original work in the main repository was still there, waiting for me to return.

After fixing the bug:

Committing in worktree
git add .
git commit -m "Fix login redirect issue"
git push origin fix/login-redirect

Step 4: Remove the worktree

After merging the fix, I removed the worktree:

Removing worktree
git worktree remove ../bugfix-login

Or from within the worktree:

Removing current worktree
cd /Users/zhaocaiwen/projects/myapp
git worktree remove bugfix-login

Quick reference

Here are the most common commands:

Git worktree commands
# Create a worktree with an existing branch
git worktree add <path> <branch>
# Create a worktree with a new branch
git worktree add <path> -b <new-branch> <base-branch>
# List all worktrees
git worktree list
# Remove a worktree
git worktree remove <path>
# Prune stale worktree information
git worktree prune

Reason

Why does Git worktree work this way?

Traditional Git has one working directory per repository. When you switch branches, Git replaces the files in your working directory with the files from the new branch. This is why uncommitted changes cause problems.

Git worktree solves this by creating additional working directories. Each worktree has its own working directory but shares the same .git directory (actually, it creates a .git file that points to the main repository’s .git directory).

Benefits:

  • No need to stash: Your uncommitted changes stay in their original worktree.
  • No duplicate cloning: Worktrees share the Git history, so you save disk space.
  • Faster context switching: No need to wait for Git to swap files in and out.
  • Parallel development: You can have multiple terminals open, each on a different branch.

Summary

In this post, I showed how Git worktree solves the problem of working on multiple branches simultaneously. Instead of stashing, committing incomplete work, or cloning repositories multiple times, you can use worktrees to have multiple working directories from a single repository.

The key commands are:

  • git worktree add to create a new worktree
  • git worktree list to see all worktrees
  • git worktree remove to clean up

Next time you need to context-switch between branches, try worktree. Your uncommitted changes will thank you.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments