起因
经常遇到这场景:
- 当前 feature 分支开发到一半
- 紧急 hotfix 需要在 main 改一行
- 又要 review 同事的 PR 在 third-branch
老办法:git stash + git checkout main + 改 + commit + checkout feature +
stash pop。每次切换几分钟(编辑器要重 index、deps 不一样还要重装、
本地服务要重启)。
git worktree 解决:一个仓库,多个工作目录,分别 checkout 不同分支。
基本用法
cd ~/projects/myapp # 主 worktree(main 分支)
# 创建新 worktree 在 ../myapp-hotfix,checkout hotfix-x 分支
git worktree add ../myapp-hotfix -b hotfix-x
# 创建在 ../myapp-review,checkout 现有 PR 分支
git worktree add ../myapp-review feature/pr-42
# 列出所有
git worktree list
# /home/u/projects/myapp abcd1234 [main]
# /home/u/projects/myapp-hotfix ef567890 [hotfix-x]
# /home/u/projects/myapp-review 12345abc [feature/pr-42]
# 完成后删
git worktree remove ../myapp-hotfix
每个 worktree 是独立目录:自己的 working tree、index、stash、
hooks 状态。但共享 .git/(共享对象库、refs、config)。
磁盘只增加 working tree 文件大小,不重复存历史。
我的目录约定
~/projects/myapp/ # 主 worktree(main)
~/projects/myapp-wt/ # 所有附加 worktree 都进这里
├── feature-search/
├── hotfix-401/
└── review-bob-pr/
-wt/ 在 .gitignore 里加(实际上 git 不会管它),也加到编辑器的
排除列表,避免 indexing 重复。
效果
切换分支从"清理 + checkout + 重装 deps + 重启服务" → "cd 到另一个目录"。
- 编辑器在每个目录独立打开
- 每个 worktree 跑自己的 dev server(端口不同)
- venv / node_modules 独立(cargo / go 缓存可以共享)
实测:从 hotfix 切回主 feature 从平均 5 分钟 → 5 秒。一周省 1 小时。
自动化
每次 review 同事 PR 都建 worktree,写个 alias:
# ~/.zshrc
function wt-pr() {
local pr=$1
gh pr checkout $pr # 拉到本地分支
local branch=$(git branch --show-current)
cd ..
git -C myapp worktree add "myapp-pr-$pr" "$branch"
cd "myapp-pr-$pr"
}
wt-pr 42 → 自动 fetch + 建 worktree + cd 过去。
venv / node_modules 怎么办
每个 worktree 独立装:
cd ../myapp-hotfix
uv sync # 装到本地 .venv/
pnpm install # 装到本地 node_modules/
uv / pnpm 用 hard link / 全局 cache → 实际硬盘开销小。
n × 同 deps 不会真的 n 倍磁盘。
共享 hooks
.git/hooks/ 是共享的(git 内部目录共用)。
每个 worktree 都跑同样的 pre-commit。一般是好事。
个别 worktree 想跳过 hook → --no-verify。
配 IDE
VS Code:每个 worktree 当成独立 workspace 打开。
WebStorm / IntelliJ:同样。
Cursor:可以在多个窗口打开不同 worktree 同时操作。
.vscode/settings.json 通过 git ignore 的方式各自配置。
与 stash / checkout 对比
| 场景 | stash + checkout | worktree |
|---|---|---|
| 切换速度 | 慢(要重 index / restart) | 快(cd 即可) |
| 心智模型 | 一个目录多状态 | 多目录多状态(更直觉) |
| 编辑器 indexing | 重做 | 不需要 |
| 磁盘 | 少 | 多 working tree(但对象库共享) |
| 临时草稿 | stash 容易丢 | 文件实存 |
90% 场景 worktree 胜。
与 git clone 对比
git clone 多次克隆同 repo:
- 优点:完全独立,无干扰
- 缺点:每个独立
.git/(重复存对象库,几百 MB → 几 GB)+
不同 clone 之间分支不互通
worktree 共享 .git/,省空间 + 一处 fetch 全部能看到新 remote refs。
main worktree 不能删
git worktree remove . # error: cannot remove main working tree
主 worktree 是创建仓库时所在的目录。要换主 worktree 要 git worktree
move(少用)。
踩过的坑
-
同分支不能两个 worktree checkout:保险机制防止冲突。
要看同一分支就建一个 detached HEAD worktree:
git worktree add ../tmp HEAD。 -
worktree 删除后 git 不会清理元数据:
git worktree prune。
或者用remove命令而不是手动rm -rf。 -
submodule + worktree:早期 git submodule 在多 worktree
不太稳定。git 2.40+ 改善很多但仍偶有奇怪行为。 -
CI 不支持 worktree:CI clone 出来是单 worktree。worktree
是本地开发优化,不影响 CI。 -
跨平台 path 差异:worktree path 存在
.git/worktrees/*/gitdir
绝对路径。把仓库目录改名 / 移动 → worktree 失效。
用git worktree repair修。
登录后参与评论。