多个 AI 编码 Session 共用目录,为什么不同分支仍会冲突
两个 session 共用一个目录时,即使各自在不同 branch 上工作,也只能轮流 checkout;每次切换都会更新同一套工作文件。Worktree 用独立目录解决这个问题。
问题不在分支,而在共用目录
我经常同时开几个 Claude Code 或 Codex session。最开始,我让每个 session 使用不同 branch,却让它们共用同一个项目目录。结果还是不断冲突。
原因很简单:一个目录同一时间只能 checkout 一个 branch。Session A 要用 feature-a,Session B 要用 feature-b,它们就得在同一个目录里反复 git switch。每切一次 branch,Git 都会更新同一套工作文件。于是:
- A 正在改文件,B 的 checkout 可能因为未提交改动而失败;
- A 和 B 同时写同一个文件,会直接改到对方的工作;
- 一个 session 正在编译,另一个 session 切了 branch,构建过程就可能前后读到两套源码。
所以,branch 只能隔离提交历史,隔离不了磁盘上的文件。只建两个 branch、却让两个 session 共用一个目录,冲突仍然存在。
真正的解法是给每个 session 一套独立文件。Git worktree 正是为此而生:每个任务 checkout 到自己的目录,拥有自己的 HEAD、index 和工作文件,但仍共享同一个 Git 仓库。Session A 切 branch 或改文件,不会碰到 Session B 的目录。
不同 branch 还不够。只有把它们放进不同目录,多个 session 才能真正并行。
怎么配置
最省事的做法,是在任务开始时直接告诉 agent:「新建一个 worktree,在里面完成并验证,最后再合并回 main。」agent 可以代你执行 Git 命令,不需要你手动切 branch。
Claude Code
Claude Code 支持用 --worktree 启动独立工作目录;sub-agent 也可以使用 isolation: worktree。每个任务在自己的目录里完成,验证通过后再合并。
Codex
Codex App 已经内置 worktree。新建 chat 时选择 Worktree,Codex 会为这个 chat 建立独立目录;默认使用 detached HEAD,需要保留成果时再创建 branch。Codex 也支持在 Local 与 Worktree 之间 handoff,并负责处理切换所需的 Git 操作。官方说明见 Codex Worktrees。
如果你使用 CLI、脚本或其他 agent,也可以直接运行 git worktree add -b <branch> <目录> main。关键不在工具,而在一条固定规则:一个并行任务,对应一个独立目录。
让每个新 session 都遵守
只靠人或 agent「记得建 worktree」并不可靠。我们把规则写进了 hook:
- SessionStart:session 如果从共享的
main目录启动,先提醒它创建 worktree; - PreToolUse:目标文件位于共享
main目录时,直接阻止编辑; - 提交与合并闸门:只允许通过受控脚本把已经验证的 branch 合并回
main。
配套脚本负责创建和清理 worktree,还会链接本地环境文件、分配不同端口。这样隔离不再依赖自觉,而是默认工作方式。
Worktree 到底隔离了什么
所有 worktree 共用同一个 Git 对象库和分支记录,但每个 worktree 都有自己的 HEAD、index 和工作文件。可以把它理解成「一套 Git 历史,多个独立项目目录」。
| 状态 | 每个 worktree 独立 | 整个仓库共享 |
|---|---|---|
| HEAD、index、工作文件、进行中的 merge/rebase | ✓ | |
| commit 对象、branch、tag、stash | ✓ |
这就是 branch 和 worktree 的区别:branch 只是指向某个 commit 的引用;worktree 才是磁盘上的独立工作目录。两个 worktree 可以同时使用不同 branch,互不改写对方的文件;其中一个产生的新 commit,又能立即被另一个看到。
还有两点要记住:
- 同一个 branch 默认不能同时 checkout 到两个 worktree。Git 会直接拒绝,避免两个目录同时推进同一个 branch;
- stash 是共享的。在一个 worktree 里创建的 stash,其他 worktree 也能看到,使用时要写清楚说明。
Worktree 解决不了什么
- 它不能消除合并冲突。两个任务如果修改同一行,合并时仍然需要解决冲突。Worktree 只是把冲突留到明确的合并步骤,而不是让两个 session 在工作过程中互相改文件。
- 它会占用更多磁盘。每个 worktree 都有自己的源码、依赖和构建缓存。
node_modules、target之类的大目录会重复出现。 - 本地配置需要单独处理。被
.gitignore忽略的.env等文件不会自动出现,需要复制、链接,或用工具的 worktree 配置带过去。 - 用完要清理。合并后运行
git worktree remove;不要直接删除目录,否则 Git 可能留下失效记录。
我们现在的做法
- 共享目录只保留干净的
main,作为最终合并入口; - 每个 session 新建自己的 branch 和 worktree;
- 每个 worktree 使用独立端口和依赖目录,避免运行环境继续互相干扰;
- 改动在 worktree 内完成定向测试和审查,通过后才允许合并;
- 合并完成后删除 worktree,不让临时目录长期堆积。
一句话总结
多个 session 共用一个目录时,不同 branch 只会让它们不停 checkout;worktree 才能让每个 session 拥有自己的文件。
Branch 负责分开提交历史,worktree 负责分开工作现场。需要并行开发时,两者缺一不可。