Git Worktree - A Practical Guide
git worktree
allows you to have multiple working trees—the actual directories containing your project files—attached to a single Git repository. This powerful feature means you can have different branches, like a feature branch and a hotfix branch, checked out in separate folders simultaneously. You no longer need to constantly stash your changes or disrupt your flow by switching branches in your main directory. Imagine having several lightweight clones of your repo; each worktree acts as an independent workspace but intelligently shares the same underlying .git
database of history, objects, and references. This shared foundation makes creating a new worktree nearly instantaneous and incredibly efficient with disk space compared to a full git clone
.
👶 Beginner Level: The Basics
At its core, git worktree
solves a common problem: you're deep into working on a new feature on feature-A
, and an urgent bug report comes in. The bug is on the main
branch. Your current work is not ready to be committed.
Without git worktree
, your options are:
-
git stash
: Stash your messy, in-progress work, switch tomain
, fix the bug, commit, switch back tofeature-A
, and thengit stash pop
. This works, but it can be disruptive, and stash conflicts are common. -
Commit WIP: Make a "Work In Progress" commit, switch branches, and then come back and reset that commit later. This pollutes your commit history.
With git worktree
, you can leave your current directory untouched and simply open a new one for the bug fix.
Key Command: git worktree add
This is the primary command you'll use. It can create a worktree from an existing branch or create a new branch at the same time.
-
From an existing branch:
# Syntax: git worktree add <path> <branch> git worktree add ../hotfix-login-bug main
-
While creating a new branch (using the
-b
flag):# Syntax: git worktree add -b <new-branch> <path> <start-point> git worktree add -b feature/new-sidebar ../project-sidebar main
Real-World Use Case: The Urgent Bug Fix
-
You're in the middle of work on
feature/user-profile
with uncommitted changes. -
An urgent bug is reported on
main
. Instead of stashing, you create a worktree:git worktree add ../project-hotfix main
-
Fix the bug in the new directory:
cd ../project-hotfix # ...make code changes... git add . git commit -m "fix: resolve critical login issue" git push origin main
-
Clean up: Once the fix is done, remove the worktree. Your original work is untouched.
cd ../my-project # Go back to your original directory git worktree remove ../project-hotfix
🧑💻 Intermediate Level: Managing Worktrees
Once you have multiple worktrees, you'll need to manage them.
Key Management Commands
-
git worktree list
: Shows all connected worktrees, theirHEAD
commit, and current branch. -
git worktree remove <path>
: Safely removes the specified worktree. -
git worktree move <old-path> <new-path>
: Relocates a worktree directory and updates Git's internal records. -
git worktree prune
: Cleans up stale references if you ever manually delete a worktree directory. -
git worktree lock <path>
: Prevents a worktree from being pruned. Useful if it's on a removable drive.
How It Works Under the Hood
All worktrees share the single .git
directory of the main repository. Inside .git/worktrees/
, Git creates a separate folder for each additional worktree. This folder contains its own HEAD
and index
but links back to the shared objects (your commits, etc.) in the main .git/objects
directory. This is why it's so efficient.
🧙♂️ Advanced Level: Power User Techniques
Worktrees enable highly parallel and complex workflows.
Cross-Worktree Git Operations
A powerful implication of the shared .git
directory is that you can perform operations between branches across different worktrees without ever leaving your current directory.
For example, if a critical commit (a1b2c3d
) was just made in your hotfix
worktree, you can cherry-pick it into your feature
worktree directly:
# While in your feature branch directory:
git cherry-pick a1b2c3d
It just works, because it's all one repository. This makes integrating changes between contexts incredibly seamless.
Detached HEAD Worktrees
You can create a worktree from any commit hash, not just a branch. This is perfect for running tests against a specific historical commit without creating a temporary branch.
git worktree add ../ci-test-a1b2c3d a1b2c3d
Long-Running Processes
-
E2E Tests: Kick off a 30-minute test suite in one worktree while continuing to code in another.
-
Large Compilations: Start a release build for your .NET project in a
release
branch worktree while simultaneously fixing a bug in adevelop
worktree. -
CI/CD Pipelines: Use worktrees on a build server to test multiple branches in parallel without performing multiple clones, saving significant disk space and time.
Potential Pitfalls and Considerations
-
IDE Confusion: Modern IDEs like VS Code handle this well, but it's best to open each worktree in a separate window (
code <path-to-worktree>
). -
Branch Uniqueness: You cannot have the same branch checked out in more than one worktree at a time. This is a safety mechanism.
-
Submodules: If your project uses submodules, you'll need to run
git submodule update
in each new worktree. -
Shared Config and Hooks: All worktrees share the same
.git
configuration and hooks (pre-commit
, etc.). This ensures consistency but be aware that a hook will run in every worktree.