Why Stash-and-Checkout Churn Drives You Mad
With a single working dir, you stash to switch branches and stash-pop to come back; after a few rounds it blurs — pop conflicts, the "which branch does this belong to" mystery, and a forgotten stash losing half a day.
git worktree lets one repository host several physically separate working directories at once, each bound to its own branch. Edit feature-A in dir A and bugfix-B in dir B, no interference, no stash.
The precondition: branches must not share local files that collide at runtime (node_modules, .env). Install dependencies once and share or externalize them, so you are not reinstalling in every worktree.
# Create an extra worktree bound to a new branch from the repo root
git worktree add ../feature-a -b feature-a
# Create another worktree tracking an existing branch
git worktree add ../hotfix -b hotfix origin/main
git worktree list
# /repo 12ab main
# /repo/../feature-a 34cd feature-a
# /repo/../hotfix 56ef hotfixCreate a Worktree per Task: One Clean Dir, One Clear History
The core habit: one in-flight task (feature, bug, experiment) maps to one worktree and one dedicated branch. Name the dir after the ticket, e.g. ../feat/pricing-table, ../fix/timezone.
This model frees you from remembering which branch you are on — wherever you stand tells you. It also lets you spin up several branches off the same base for comparison: open A and B from origin/main in own dirs, commit and test each, never overlapping.
Committing, testing, and linting happen independently in each worktree, so parallelizing with CI is natural: each dir runs its own server and tests, no port or file-lock fights.
base="origin/main"
git worktree add ../feat/pricing-table -b feat/pricing-table "$base"
git worktree add ../fix/timezone -b fix/timezone "$base"
# Develop independently
# (cd ../feat/pricing-table && pnpm install && pnpm dev)
# (cd ../fix/timezone && pnpm install && pnpm test)
git worktree listMistake: Forgetting a Branch Can Only Have One Worktree
A branch usually has exactly one worktree. Trying to check out main in a second directory fails with "already checked out at". That is a guard, not a bug; the message tells you which directory holds it.
If you really need it, check out detached in the second one with git checkout --detach, but not for normal work.
To clean up, git worktree remove <path> (older Git may need git worktree prune to clear stale registrations) removes it from both Git and disk at once.
# Wrong: two directories for the same branch
git worktree add ../dup main
# fatal: 'main' is already checked out at '<other-dir>'
# Correct cleanup
git worktree remove ../dup
# Or remove only the registration (if you deleted the dir by hand)
git worktree prune
git worktree listVerify the Worktrees Are Clean and Point Around Correctly
Before removing, confirm the worktree holds no uncommitted changes. git worktree list --porcelain gives scriptable path and branch for reading.
When running in parallel, never guess the branch: explicitly cd into the target directory so scripts act on the right worktree.
Wrap-up habit: delete the worktree after its branch is merged and pushed, keep list lean, and do not let merged branches hoard disk in stray directories.
# List all worktrees from a script (--porcelain output is easy to parse)
git worktree list --porcelain
# worktree /repo
# branch refs/heads/main
# worktree /repo/../feat/a
# branch refs/heads/feat/a
# Remove the directory for a finished branch
git worktree remove ../feat/a
git worktree prune
git worktree list