Skip to content
ExponaBLOG
GIT & GITHUB FOR PROFESSIONAL DEVELOPERS · DAY 023 / 100

git worktree in Git & GitHub for Professional Developers

Work on several branches at once.

Expona Admin6 min read

The context-switching problem in team development

You're mid-sprint, deep in a feature branch, when urgent production issues surface. Switching branches means stashing work, losing your mental state, and rebuilding the local environment. git worktree in Git & GitHub for Professional Developers solves this by letting you work on multiple branches simultaneously in separate folders, each with its own working directory. This Day 23 technique transforms how teams handle interruptions and parallel work.

What git worktree actually does

A worktree is a separate working directory linked to your repository. Instead of one folder containing one branch, you maintain multiple folders—each checked out to a different branch—all pointing to the same underlying repository. They share the object database and configuration but keep work isolated.

Think of it like having multiple desks in the same office. Your main desk (the original clone) is still there, but you've added a second or third desk with its own project layout. Switch desks, and your work remains exactly as you left it. No stashing, no branch-switching ceremony, no lost context.

The typical workflow creates a worktree with a base branch, then makes it a linked directory:

bash
git worktree add ../hotfix main

This creates a new folder ../hotfix checking out the main branch. You now have two working directories: your original folder (usually on your feature branch) and the hotfix folder (on main). You can edit, test, and commit in each independently.

Separate folders, one repository

The elegance here is architectural. You're not duplicating the entire repository. Each worktree has its own working directory and staging area, but they share:

  • The same object database (.git/objects)
  • The same refs and branch pointers
  • The same configuration
  • One set of hooks (with care)

This saves disk space and keeps history unified. When you push from one worktree, all worktrees see the updated refs immediately. When you fetch in one, all benefit from the downloaded objects.

Here's a realistic scenario. Your main clone sits on feature/user-dashboard. You run:

bash
git worktree add ../hotfix-auth main

Now your disk layout looks like:

bash
project/
├── .git/                    (shared)
├── src/
│   └── dashboard.tsx         (feature/user-dashboard)
├── tests/
└── hotfix-auth/             (new worktree)
    ├── src/
    │   └── auth.ts          (main branch)
    └── tests/

You can cd ../hotfix-auth, fix the auth bug, run tests, and commit. Meanwhile, your original terminal is still in the main folder working on the dashboard. Both checkouts are independent and up-to-date with the repository state.

No stashing to switch context

This is where worktrees shine in team environments. Before worktrees, switching branches required discipline:

  1. Commit or stash your current work
  2. Switch branches
  3. Handle merge conflicts or slow checkouts on large repositories
  4. Switch back and unstash

Mental load is high. You're juggling state across a single working directory. Stash conflicts happen. You forget which stash holds which work. Build times reset.

With worktrees, you open a second terminal and switch to the worktree folder. Your original work is untouched. Your build artifacts in the main folder remain. Your IDE might even keep the original project open in one window and open the worktree in another (VS Code and JetBrains support this well).

Example: You're testing a feature, run a long test suite, and a slack notification arrives—production is down. Instead of cancelling the test (losing time) or stashing work (losing context), you simply:

bash
cd ../hotfix-prod
git pull
# Fix the issue
git add . && git commit -m "Fix prod issue"
git push

Back to the original terminal, your tests finish. No interruption. No mental context-switch tax.

For teams using pair programming or code reviews with tight feedback loops, this is invaluable. One engineer can stay in the feature branch while another quickly spins up a worktree to validate the approach or test an integration point.

Creating and managing worktrees

The syntax is straightforward. The basic form:

bash
git worktree add <path> <branch>

Create a worktree for an existing branch:

bash
git worktree add ../staging staging

Create a worktree and a new branch at the same time:

bash
git worktree add -b feature/new-api ../api-work main

This creates a folder ../api-work on a fresh branch feature/new-api based on main.

List all worktrees and their details:

bash
git worktree list

Output shows branch, commit, and folder path:

bash
/Users/dev/project                       abc1234 [main]
/Users/dev/hotfix-auth                   def5678 [hotfix/auth-token]
/Users/dev/api-work                      ghi9012 [feature/new-api]

You can also repair broken worktrees (useful if you delete a folder without cleaning up):

bash
git worktree repair

And prune references to worktrees that no longer exist on disk:

bash
git worktree prune

Remove with git worktree remove

When work is complete, clean up. The command:

bash
git worktree remove ../hotfix-auth

This deletes the worktree folder and cleans up internal references. The branch remains in the repository (unless you specify --prune-worktree, which also deletes the branch).

If the worktree is locked (perhaps an IDE has it open), add --force:

bash
git worktree remove --force ../hotfix-auth

Always use remove rather than manually deleting the folder. Git maintains metadata for each worktree, and removing it through the command ensures that metadata is cleaned up. Orphaned metadata can clutter your repository and cause confusion later.

If you do accidentally delete a worktree folder, running git worktree prune will clean up the dangling references.

Real-world team workflows with worktrees

In e-commerce platforms, we've used worktrees for parallel testing. One engineer maintains the main feature branch while another spins up a worktree on the integration branch to validate database migrations. Both run tests simultaneously without blocking each other.

For urgent patches, we keep a standing worktree on the production branch. When an issue surfaces, the fix goes there immediately, gets tested and reviewed separately from ongoing feature work, and merges back independently. The main branch's CI pipeline isn't disrupted by a context switch.

Pair programming becomes smoother. One engineer drives feature development in the main checkout while a second engineer uses a worktree to explore refactoring or test edge cases in parallel. Communication stays high because both can see each other's terminals and ask "what if we try this in the other worktree?"

Common mistakes

Not checking out the same branch in multiple worktrees. Git prevents this—one branch can only be checked out in one worktree at a time. Attempting to create a second worktree on an already-checked-out branch fails. This is by design to avoid merge chaos.

Forgetting to remove old worktrees. Over time, you accumulate folders. Use git worktree list regularly and clean up. Old worktrees take disk space and can confuse your team if they're left behind.

Assuming hooks run in all worktrees identically. Pre-commit hooks execute in each worktree independently, which is usually fine. But if a hook writes to shared files or has side effects, you might see unexpected behavior. Test your hooks across worktrees.

Not communicating worktree usage to your team. If your team shares a code review process or has conventions around branch management, worktrees can create confusion if others don't expect multiple checkouts. Document when and how your team uses them.

Using worktrees for long-lived branches. Worktrees are best for temporary parallel work—hotfixes, quick explorations, code review validation. For long-lived feature branches, stick to normal branch switching. Worktrees add cognitive load; use them purposefully.

Key takeaways

  • git worktree add creates a separate working directory linked to the same repository, letting you work on multiple branches simultaneously without stashing.
  • Worktrees share the object database and refs but maintain independent working directories and staging areas, saving disk space while keeping work isolated.
  • Use worktrees to reduce context-switching friction when handling urgent issues, parallel testing, or pair programming.
  • Always use git worktree remove to clean up, not manual folder deletion, to keep Git's metadata consistent.
  • Worktrees prevent checking out the same branch in multiple worktrees simultaneously—Git enforces this to avoid conflicts.
  • List worktrees with git worktree list and repair broken ones with git worktree repair and git worktree prune.
  • Document worktree usage with your team to avoid confusion and keep conventions clear.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles