git worktree:在同一个仓库同时开多个分支 work

起因

经常遇到这场景:

  • 当前 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(少用)。

踩过的坑

  1. 同分支不能两个 worktree checkout:保险机制防止冲突。
    要看同一分支就建一个 detached HEAD worktree:
    git worktree add ../tmp HEAD

  2. worktree 删除后 git 不会清理元数据git worktree prune
    或者用 remove 命令而不是手动 rm -rf

  3. submodule + worktree:早期 git submodule 在多 worktree
    不太稳定。git 2.40+ 改善很多但仍偶有奇怪行为。

  4. CI 不支持 worktree:CI clone 出来是单 worktree。worktree
    是本地开发优化,不影响 CI。

  5. 跨平台 path 差异:worktree path 存在 .git/worktrees/*/gitdir
    绝对路径。把仓库目录改名 / 移动 → worktree 失效。
    git worktree repair 修。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。