Git
Git Worktrees Explained
One repo. Multiple branches. Checked out simultaneously.
The Problem
Why worktrees exist
Without worktrees
Working on feature-auth…
Urgent bug comes in
git stash
git checkout fix/bug
Fix the bug, commit, push
git checkout feature-auth
git stash pop
Lost context. Where was I?
With worktrees
Terminal 1
~/app-feature-auth/
Working…
Still working…
Never interrupted
Terminal 2
~/app-fix-bug/
Fix bug
Commit & push
Done
Architecture
How worktrees connect to your repo
my-project/
main
Main worktree (original clone)
points to
my-project-auth/
feature-auth
Linked worktree
.git
← tiny file, not a directory
points to
my-project-pay/
feature-payments
Linked worktree
.git
← tiny file, not a directory
Boundaries
What's shared vs. what's isolated
Workflow
Step-by-step lifecycle
1
Create worktrees
# From your main repo
git worktree add ../app-feature -b feature-auth
git worktree add ../app-bugfix -b fix/crash
2
Set up each environment
# Copy env, install deps
cd ../app-feature
cp ../my-app/.env .env
npm install # or go mod download, etc.
3
Work in parallel
Open separate terminals. Run Claude Code, your editor, or dev servers independently in each worktree. They won't interfere.
# Terminal 1 # Terminal 2
cd ../app-feature cd ../app-bugfix
claude claude
4
Push & create PRs
git add . && git commit -m "feat: auth flow"
git push origin feature-auth
gh pr create
5
Clean up after merge
# Back in main repo
cd ~/projects/my-app
git pull
git worktree remove ../app-feature
git branch -d feature-auth
Reference
Command cheatsheet
Create
git worktree add <path> -b <branch>
New worktree + new branch
git worktree add <path> <branch>
New worktree from existing branch
git worktree add <path> -b <br> origin/main
New branch from a specific start point
Manage
git worktree list
Show all worktrees and their branches
git worktree remove <path>
Delete a worktree (must be clean)
git worktree remove --force <path>
Force delete (discard changes)
Maintain
git worktree prune
Clean up stale references
git worktree move <old> <new>
Move worktree to new location
git worktree lock <path>
Prevent accidental pruning
Sync
git fetch origin
Fetch latest from remote
git rebase origin/main
Rebase worktree branch onto main
git worktree list | grep <branch>
Check if a branch is in use
Automation
Shell helper functions
Drop these into your
~/.zshrc to create and remove worktrees with a single command. They wrap the manual steps from the Workflow tab into reusable functions.
wt-add
Create a worktree as a sibling directory with a new branch.
# Usage: wt-add feature-auth wt-add() { local branch="$1" if [[ -z "$branch" ]]; then echo "Usage: wt-add <branch-name>" >&2 return 1 fi # Get repo root name for the sibling path local repo repo="$(basename "$(git rev-parse --show-toplevel)")" local target="../${repo}-${branch}" git worktree add "$target" -b "$branch" \ && cd "$target" \ && echo "Worktree ready → $target" }
wt-rm
Remove a worktree and delete its branch.
# Usage: wt-rm feature-auth wt-rm() { local branch="$1" if [[ -z "$branch" ]]; then echo "Usage: wt-rm <branch-name>" >&2 return 1 fi # Resolve the worktree path from branch name local repo repo="$(basename "$(git rev-parse --show-toplevel)")" local target="../${repo}-${branch}" # Return to main worktree if inside the one being removed if [[ "$(pwd)" == "$(cd "$target" && pwd)" ]]; then cd "$(git rev-parse --show-toplevel)" fi git worktree remove "$target" || return 1 if git branch -d "$branch" 2>/dev/null; then echo "Removed worktree + branch: $branch" else echo "Worktree removed. Branch '$branch' has unmerged commits." echo " Force delete: git branch -D $branch" fi }
How it works:
wt-add feature-auth creates ../my-project-feature-auth/ as a sibling of your repo and checks out a new branch. wt-rm feature-auth removes the worktree and deletes the local branch. If the branch has unmerged commits, it tells you how to force-delete.
Constraints
Rules to remember
One branch per worktree. Can't have the same branch checked out in two places.
Keep worktrees as siblings. Don't nest them inside each other or inside the main repo.
Dependencies aren't shared. Run install commands in each new worktree.
.env files are untracked. Copy them manually or script the setup.
Main worktree is special. You can't remove the original clone directory.
Stashes are global. They live in the shared .git and are visible everywhere.
Related Topics
Developer Tools
Terminal (macOS)
Terminal emulators, shells, and config files — how they connect and which file to edit when.
Google Cloud Platform
GCP IAM
Identity & Access Management — principals, roles, hierarchy, service accounts, and policy evaluation in one mental model.
Kubernetes
Helm Charts
Chart structure, templating engine, release lifecycle, and everything you need to package Kubernetes applications.