DevOpsil
Git
85%

Git Worktrees For Managing Multiple Feature Branches Simultaneously

Aareez AsifAareez Asif4 min read

Git Worktrees: Manage Multiple Feature Branches Without the Switching Nightmare

Stop stashing. Stop context-switching. Git worktrees let you check out multiple branches simultaneously in separate directories — each with its own working tree, no conflicts.

The Core Concept

One repository, multiple working directories. Each worktree shares the same .git folder but has its own branch and working state.

# Your main repo lives here
~/projects/my-app/          # main branch

# Worktrees live alongside it
~/projects/my-app-feature-auth/     # feature/auth branch
~/projects/my-app-hotfix-prod/      # hotfix/prod-crash branch

Essential Commands

# Create a new worktree (branch must not exist yet)
git worktree add ../my-app-feature-auth -b feature/auth

# Create a worktree from an existing branch
git worktree add ../my-app-hotfix hotfix/prod-crash

# Create a worktree in detached HEAD state
git worktree add --detach ../my-app-review abc1234

# List all worktrees
git worktree list

# Remove a worktree (after you're done)
git worktree remove ../my-app-feature-auth

# Force remove if worktree has uncommitted changes
git worktree remove --force ../my-app-feature-auth

# Prune stale worktree references
git worktree prune

My Preferred Directory Layout

Keep worktrees organized by putting them in a sibling directory pattern:

~/projects/
├── my-app/              # main / primary worktree
├── my-app--auth/        # feature/auth
├── my-app--payments/    # feature/payments
└── my-app--hotfix/      # hotfix/critical-bug

The double-dash naming convention makes it obvious these are worktrees of the same repo at a glance.

Real Workflow Example

# You're deep in feature work on main worktree
# Prod alert fires — need a hotfix NOW

# Step 1: Spin up a hotfix worktree (don't touch your current work)
git worktree add ../my-app--hotfix -b hotfix/null-pointer-exception

# Step 2: Jump over, fix it, ship it
cd ../my-app--hotfix
# ... make your fix ...
git commit -am "fix: null pointer in payment processor"
git push origin hotfix/null-pointer-exception

# Step 3: Back to your feature — zero disruption
cd ../my-app
# Your changes are exactly where you left them

Worktree List Output

$ git worktree list
/home/user/projects/my-app           abc1234 [main]
/home/user/projects/my-app--auth     def5678 [feature/auth]
/home/user/projects/my-app--hotfix   ghi9012 [hotfix/null-pointer-exception]

Quick Reference Card

TaskCommand
New worktree + new branchgit worktree add ../path -b branch-name
New worktree + existing branchgit worktree add ../path branch-name
List all worktreesgit worktree list
Remove worktreegit worktree remove ../path
Force removegit worktree remove --force ../path
Clean stale refsgit worktree prune
Move a worktreegit worktree move ../old ../new
Lock a worktreegit worktree lock ../path

Gotchas to Know Before You Start

You can't check out the same branch in two worktrees. Git will refuse. One branch = one worktree at a time.

# This will FAIL if feature/auth is already checked out
git worktree add ../another-auth feature/auth
# fatal: 'feature/auth' is already checked out at '...'

.git is a file, not a directory, in linked worktrees.

$ cat ~/projects/my-app--auth/.git
gitdir: /home/user/projects/my-app/.git/worktrees/my-app--auth

Don't be surprised — this is normal and expected.

Node modules, build artifacts, and .env files don't transfer. Each worktree is a fresh working directory. You'll need to run npm install (or equivalent) in each new worktree.

# Quick setup script after creating a worktree
git worktree add ../my-app--feature-x -b feature/x && \
  cd ../my-app--feature-x && \
  cp ../my-app/.env . && \
  npm install

Bash/Zsh Aliases Worth Adding

# ~/.bashrc or ~/.zshrc

# Create worktree with automatic setup
gwt() {
  local branch=$1
  local path="../$(basename $(git rev-parse --show-toplevel))--${branch//\//-}"
  git worktree add "$path" -b "$branch"
  cd "$path"
}

# List worktrees (short)
alias gwtl='git worktree list'

# Remove current worktree (from inside it)
gwtrm() {
  local current=$(pwd)
  cd ..
  git worktree remove "$current"
}

When to Use Worktrees vs. Stash vs. Branches

SituationUse
Quick context switch, same daygit stash
Parallel long-running featuresWorktrees
Code review while mid-featureWorktrees
Hotfix while feature is in progressWorktrees
Running two versions simultaneouslyWorktrees

The Bottom Line

If you're still stashing work every time a Slack message says "can you review this PR real quick?" — you're leaving productivity on the table. Worktrees are underused and genuinely change how you work across multiple features.

Set one up in the next five minutes. You won't go back.

Share:

Was this article helpful?

Aareez Asif
Aareez Asif

Senior Kubernetes Architect

10+ years orchestrating containers in production. Battle-tested opinions on everything from pod scheduling to service mesh. I've seen clusters burn and helped rebuild them better.

Related Articles

GitQuick RefBeginnerNeeds Review

Git Commands: Cheat Sheet

Git commands cheat sheet for DevOps engineers — branching, rebasing, stashing, bisecting, cherry-picking, and recovery workflows with examples.

Sarah Chen·
3 min read

Discussion