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.
# 在仓库根目录下新建一个绑定分支的额外工作树
git worktree add ../feature-a -b feature-a
# 再建一个跟踪已有分支的 worktree
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"
# 各自独立开发
# (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.
# 错误示范:同一分支开两个目录
git worktree add ../dup main
# fatal: 'main' is already checked out at '<other-dir>'
# 正确清理
git worktree remove ../dup
# 或只移除注册信息(目录你手动删过)
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.
# 脚本化查看所有 worktree(--porcelain 输出易解析)
git worktree list --porcelain
# worktree /repo
# branch refs/heads/main
# worktree /repo/../feat/a
# branch refs/heads/feat/a
# 回收完的分支对应目录
git worktree remove ../feat/a
git worktree prune
git worktree list