SWORUP.DEV

Git Worktree - A Practical Guide

By Sworup Shakya|August 19, 2025|git

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:

  1. git stash: Stash your messy, in-progress work, switch to main, fix the bug, commit, switch back to feature-A, and then git stash pop. This works, but it can be disruptive, and stash conflicts are common.

  2. 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

  1. You're in the middle of work on feature/user-profile with uncommitted changes.

  2. An urgent bug is reported on main. Instead of stashing, you create a worktree:

    git worktree add ../project-hotfix main
    
  3. 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
    
  4. 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, their HEAD 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 a develop 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.