青蛙小白
博客 / 2026/06

git worktree:同时在多个分支上工作

2026/06/17 · — 字 · 阅读约 — 分钟 ·
目录

AI 编程工具改变了写代码的节奏。以前一个人同时只能推进一条线,现在用 Claude Code 或者其他 AI agent 可以很自然地并发:一个任务交给 agent 跑着,自己再开一个 session 做另一件事。问题随之而来——两个任务如果在同一个工作目录里,文件系统是共享的,两个 agent 会互相踩脚。

这不是 AI 工具的问题,是 git 工作目录没有为"并发"设计。git worktree 才是。

事实上,Claude Code 官方文档里有一整页专门介绍 worktree 隔离:自定义 subagent 可以在 frontmatter 里写 isolation: worktree,每个子任务就会在自己的文件系统里工作,互不干扰。这个设计背后的 git 原语,就是本文要介绍的内容。

当然,worktree 不只是 AI agent 的基础设施。在没有 AI 的场景里,它也能让一类常见情况更顺滑:正在 feature 分支开发到一半,突然需要紧急修复线上 bug。用 stash 当然能解决,但 worktree 让你不必暂停手头的工作——hotfix 目录和 feature 目录同时都是活的,可以各自跑测试、开编辑器,互不干扰。

1. 核心概念

通常我们认为一个 git 仓库就是一个工作目录,配一套 .git 目录里的对象存储、索引(index)和 HEAD 引用。但这个绑定并非不可拆分。

git worktree 允许从同一个 .git 存储出发,创建多个独立的工作目录(linked worktrees)。每个工作目录有自己的 index 和 HEAD,因此可以各自检出不同的分支。它们共享提交历史和对象存储,但彼此的工作区完全独立,不会互相干扰。

第一次打开仓库的那个目录叫做 main worktree(主工作树)。之后用命令创建的每一个额外目录叫做 linked worktree(链接工作树)。两者在 git 操作层面是对等的——没有主从之分,只是一个有 .git 目录,另一个通过 .git 文件指向那个目录。

一个约束值得提前知道:同一个分支不能同时被两个 worktree 检出。这不是 bug,而是防止两个工作区同时修改同一分支造成冲突。如果需要在新 worktree 里基于某个分支工作,可以从它新建分支,或者用 --detach 以 detached HEAD 状态检出。

2. 基础用法

准备一个已有仓库,添加一个新的 worktree:

# 在 ../hotfix 目录创建新 worktree,基于 main 分支新建 hotfix/login
git worktree add ../hotfix -b hotfix/login main

这条命令做了三件事:在 ../hotfix 路径创建目录,新建 hotfix/login 分支,并检出到那个目录。

如果分支已经存在,直接指定就好:

git worktree add ../review feature/new-api

查看当前所有 worktree:

git worktree list

输出大概是这样:

/home/alice/projects/myapp          a3f1c28 [main]
/home/alice/projects/hotfix         a3f1c28 [hotfix/login]
/home/alice/projects/review         9e2b441 [feature/new-api]

修完 hotfix,不再需要那个 worktree 时:

git worktree remove ../hotfix

这个命令会删除那个目录,同时清理 .git 里的 worktree 记录。但它有保护措施:如果目录里有未提交的修改,它会拒绝删除(可以加 --force 强制)。

如果目录已经被手动删除,只是 .git 里的记录还在,用 prune 清理:

git worktree prune

3. 实际场景

线上紧急修复是最经典的使用场景。开发分支继续待着,新建 worktree 处理 hotfix,两边的文件系统完全分离,修完直接删 worktree,回去继续开发,什么都不用 stash。

# 开发分支工作中
cd ~/projects/myapp         # feature/payment 分支
vim src/payment.ts          # 修了一半

# 紧急 hotfix
git worktree add ~/projects/myapp-hotfix -b hotfix/crash main
cd ~/projects/myapp-hotfix
vim src/auth.ts             # 修完
git commit -m "fix: auth crash"
git push origin hotfix/crash
# 在 GitHub/GitLab 上提 PR 合并到 main,或直接合并:
# git switch main && git merge hotfix/crash && git push

# 如果 feature 分支也需要这个修复,cherry-pick 过来
cd ~/projects/myapp
git cherry-pick hotfix/crash

# 清理 worktree(分支已合并,可以一并删除)
git worktree remove ~/projects/myapp-hotfix
git branch -d hotfix/crash

同时跑多个命令也是常见场景。比如在 main 分支跑测试套件的同时,在 feature 分支继续开发,两个测试进程用的是不同的文件集,互不影响:

git worktree add /tmp/myapp-test main
cd /tmp/myapp-test && npm test &   # 后台跑 main 的测试
cd ~/projects/myapp                 # 继续写 feature

Code review 可以借助 worktree 避免污染自己的工作区。需要看一个同事的 PR 时:

git worktree add /tmp/review-pr42 origin/feature/their-branch
cd /tmp/review-pr42
# 看代码、跑一遍、测试
git worktree remove /tmp/review-pr42

4. 与 IDE 和工具的协作

worktree 在文件系统上是独立的目录,IDE 可以各自打开它们。VSCode 里可以同时打开两个窗口,一个指向主项目,一个指向 hotfix 目录,互不干扰。

如果配合 Zellij 或 tmux,可以给不同 worktree 分配不同的 session 或 tab,进一步减少来回切换的摩擦。比如主开发工作区一个 session,hotfix 工作区另一个 session,zellij attach hotfix 就能切过去。

一个小细节:linked worktree 的 .git 是一个文件(不是目录),内容类似 gitdir: /home/alice/projects/myapp/.git/worktrees/hotfix。这是 git 把多个工作区指回同一个对象存储的机制。知道这个可以避免误删那个 .git 文件。

CI/CD 流水线在某些场景里也会用 worktree。如果流水线需要同时构建两个分支,用 worktree 比克隆两次仓库快,因为对象不需要重新下载。

5. 常用命令速查

# 添加 worktree(新建分支)
git worktree add <path> -b <new-branch> <start-point>

# 添加 worktree(已有分支)
git worktree add <path> <existing-branch>

# 添加 worktree(detached HEAD)
git worktree add --detach <path> <commit>

# 列出所有 worktree
git worktree list
git worktree list --porcelain    # 机器可读格式

# 移动 worktree 到新路径
git worktree move <old-path> <new-path>

# 删除 worktree
git worktree remove <path>
git worktree remove --force <path>   # 强制,忽略未提交改动

# 清理失效记录
git worktree prune
git worktree prune --dry-run         # 预览,不实际删除

6. 总结

git worktree 把"分支"和"工作目录"的绑定关系解开了。这个解耦带来的直接变化是:多个任务可以在文件系统上同时存在,各自有独立的进程、编辑器和终端,而不是共用同一个工作目录、靠来回切换维持秩序。

最值得先试的场景是紧急 hotfix 和 PR review——一条命令创建,做完删掉,几乎没有心智负担。用熟了之后,worktree 会变成一个自然反应:需要隔离,就开一个目录。

参考资料

评论