你让 Claude Code 跑「修 billing bug」,同时让 Codex 跑「重构 billing 结构」——同一时间、同一分支。两个都动了 src/billing.ts。现在 git status 显示文件冲突,两个 agent 都坚持自己的改动才是「对」的,而你的测试套件挂了,因为两边的测试各自假设了不同的文件状态。
最快的修法: 如果你正卡在 merge 中途,先跑 git merge --abort 回到干净状态,然后把两个 agent 都停掉。冲突由你自己来 resolve(或用 git mergetool)——绝不要 prompt 任何一个 agent「resolve this merge conflict」,因为没写另一边代码的那个 agent,根本无从恢复另一边的意图。然后防止复发:给每个 agent 一份不相交的文件 scope,并把每个 agent 放进各自的 git worktree。
结构性的根因是共享状态。两个 agent 读同一批文件、做出不同决定,产生的冲突两边都不该去 resolve。截至 2026 年 6 月,两大主流编码 agent 都正是为此把 worktree 隔离直接做进了自家工具里。在 OpenAI Codex app 里,你开 thread 时选 Worktree 模式(而非 Local / Cloud),它会在你选的分支上 checkout 一个隔离的 worktree;合并回去要你刻意操作——用它内置的 git 工具(commit / push / 开 PR)或 Hand off 按钮——它从不自动合并。Claude Code 给每个 session 提供了 --worktree 标志,并允许自定义 subagent 在 frontmatter 里带 isolation: worktree。下面这套修法,无论你用这些自动化还是手动搭 worktree 都适用。
你属于哪一类?
| 症状 | 可能原因 | 跳到 |
|---|---|---|
merge / rebase 后 git status 显示 both modified 文件 | 同分支上 scope 重叠 | 原因 1-2,Step 1-4 |
| 一个终端里的改动出现后又消失,同时另一个终端在写 | 两个 agent,一个 working tree | 原因 3,Step 4 |
| 长跑 agent 覆盖了你后来做的工作 | 后台 agent + 前台编辑 | 原因 4,Step 4 |
| 合并后的文件「干净」,但某个 task 的逻辑没了 | 某个 agent 猜着 resolve | 原因 5,Step 2 + 5 |
冲突只出现在 CLAUDE.md / package.json / lockfile | 共享配置,物理碰撞 | 原因 6,Step 6 |
常见原因
按命中率从高到低排列。
1. 并行跑之前没分 scope
你在同一分支上启动了两个 agent,task scope 重叠。各自读了共享文件的原始状态、按自己的解读去改,直到 merge 时你才发现重叠。
如何判断:两个近期 commit 或在跑的分支都动了同一批文件。跑一下 git diff --name-only --diff-filter=U——如果冲突列表同时落在两个 task 的描述里,那这个重叠是结构性的,不是运气不好。
2. Task 看着独立、其实有隐性耦合
「修 billing bug」和「重构 billing 结构」听起来不相交。其实并不是——两个都要动 billing.ts。所谓的独立只是名义上的。
如何判断:grep -rl "billing" src/ 列出一大堆共享文件。围绕同一个概念命名的 task 通常会重叠。
3. 两个 agent 共享同一个 working tree
同一个 repo、同一个分支、两个终端 session。第二个 agent 读到第一个 agent 干到一半的状态、被搞糊涂、然后把它覆盖掉。
如何判断:一个终端的改动在另一个终端写入时出现又消失。文件修改时间(ls -la --time-style=full-iso src/)在两个 session 之间交错出现。
4. 后台长跑 agent + 前台编辑
你给一个 Claude Code agent 派了一个长 task,然后自己开始手动编辑(或者又开了另一个 agent)。后台 agent 最终的写入和你新鲜的改动撞上了。一个长跑、或者看起来已经 stall 的 agent,仍可能在你转去做别的事情几分钟后,一次性 flush 一大批写入,盖到你期间动过的文件上。
如何判断:之前 stall 或长跑的 agent 在你已经转去做别的之后才完事。它的输出覆盖了你更新的工作。
5. 某个 agent 靠「猜」resolve 了冲突
真冲突发生后,你让其中一个 agent 去修。它挑了一个方向,但另一个 agent 的意图现在丢了——resolution 看着干净,可另一个 task 的逻辑已经没了。
如何判断:git log --oneline 里有一个在 agent 跑动期间生成的 “resolve conflict” commit。合并后的文件代表不了任何一支的完整意图,而另一个 task 的测试现在挂了。
6. 共享的 CLAUDE.md / 配置造成假阳性冲突
两个 agent 出于略有不同的原因,都更新了 CLAUDE.md、package.json 或某个 lockfile(package-lock.json、pnpm-lock.yaml)——意图不同,但只要改动的行物理上靠得太近、或者 lockfile 重新生成了,git 就没法自动 merge。
如何判断:冲突出在配置 / 文档 / lockfile 里,而不是代码里。每个 agent 的添加本身都是对的,只是物理上撞了。
最短修复路径
按收益从高到低排列。Step 1 止血,Step 4 防复发。
Step 1:停掉两个 agent,冻结 merge
先把 Claude Code 和 Codex(或者你那一对,不管是哪两个)都停掉。任一 agent 每多跑一步,冲突都会被进一步放大。
如果有一个 merge 或 rebase 正卡在中途、你想在做任何决定之前先回到干净状态,就 abort 掉它:
git merge --abort # 如果你正卡在 merge 中途
git rebase --abort # 如果你正卡在 rebase 中途
git merge --abort 会把 working tree 恢复到 merge 开始之前的精确状态,这样你就能重新 plan,而不是在一个坏掉的 merge 里硬改。冲突没解决之前,不要重启任何一个 agent。
Step 2:由人来 resolve 冲突
# 看清楚到底有哪些冲突
git status
git diff --name-only --diff-filter=U # 只看冲突文件
打开每一个冲突文件。git 用下面这些标记把两边标出来:
<<<<<<< HEAD
你当前分支的版本
=======
被合并进来的那一支的版本
>>>>>>> feature/refactor-billing
编辑文件,留下你想要的部分,然后删掉全部三行标记(<<<<<<<、=======、>>>>>>>)。想要一个引导式的三方对比视图,就跑 git mergetool,而不是手改原始标记。对每一处冲突,决定:
- 是不是有一个方向明显对?留下那个方向,弃掉另一个。
- 是不是两边都要?小心地手动合起来。
- 如果你判断不了,跑
git checkout --theirs <file>或--ours <file>重置那一个文件,或者整文件回退、重新 plan。
完成后:
git add <resolved-files>
git commit -m "resolve conflict between feature-billing and feature-refactor"
Step 3:为下一次并行跑 plan 不相交的 scope
Agent A 只动:src/billing/
Agent B 只动:src/auth/
如果任一 agent 需要动它 scope 之外的东西:
- 停下
- 等另一个 agent 完事
- 然后顺序进行
不相交的文件路径 = 不可能冲突。这要在开始之前就 plan 好。拿不准的时候,先 grep -rl "<共享概念>" src/ 确认两个 scope 真的不相交——名字会骗人。
Step 4:用 git worktree 隔离并行工作
worktree 是链接到同一个 repo 的第二份 checkout。每个 worktree 有自己的分支、自己的 index、自己在磁盘上的文件,但共享同一份 commit 历史。两个 agent 可以分别写进不同的 worktree,永远不会撞在一起。
# 主项目给一个 agent(假设已经 checkout 在 feature/billing 上)
cd ~/projects/myapp
# 给另一个 agent 在新分支上开一个独立 worktree
git worktree add -b feature/auth ../myapp-agent2
# 列出所有 worktree 确认一下
git worktree list
-b feature/auth 一步到位地创建分支并把它 checkout 进 ../myapp-agent2。把第二个 agent 指向那个目录。合并是一个刻意的步骤:
git checkout main
git merge feature/billing
git merge feature/auth
# 手动 resolve 任何剩余冲突(见 Step 2)
worktree 是一份全新的 checkout,所以像 .env 这种被 gitignore 的文件不会被复制进去。用 Claude Code 时,在 repo 根目录加一个 .worktreeinclude 文件(语法和 .gitignore 一样),列出要复制进每个新 worktree 的本地文件:
.env
.env.local
config/secrets.json
一个 worktree 用完后,清理掉它,免得过期的 checkout 越堆越多:
git worktree remove ../myapp-agent2
git worktree prune # 清掉已被删除 worktree 的残留登记
用内置工具(2026 年 6 月): 你不总是得手动搭这一套。
- Claude Code: 用
claude --worktree feature-auth(或-w)就能让任意 session 跑在自己的 worktree 里。默认它会在worktree-feature-auth分支上创建.claude/worktrees/feature-auth/;记得把.claude/worktrees/加进.gitignore。想让写代码的 subagent 自己隔离,就在 subagent 的 frontmatter 里加isolation: worktree——每个会拿到一个临时 worktree,当它没改动地完成时会被自动移除。worktree 默认从origin/HEAD(一份干净的 tree)分叉;如果你需要它们带上你正在进行中的 commit,就在 settings 里把worktree.baseRef设成"head"。 - Codex app: 开 thread 时选
Worktree模式,它会把那个 task 隔离到自己的 checkout 上,合并回去由你用它内置的 git 工具或Hand off刻意操作。 - Codex CLI: 截至 2026 年 6 月它还没有内置的
--worktree标志,所以用普通的git worktree add创建 worktree,并为每个 worktree 导出一个不同的CODEX_HOME(例如export CODEX_HOME=../myapp-agent2/.codex),让并行的 agent 不共享 session / 配置状态。
Step 5:永远不要让 agent 去 resolve 冲突
再有能力的 agent,在挑一个方向时也会丢掉另一边的意图。agent 看到的是代码,不是它当初为什么这么写。resolve 需要理解两边的意图——这是人做的事,agent 做不了。这也正是 Codex app 和大多数正经 worktree 工具都强制人工合并、而不是自动合并的原因。
不要 prompt 任何一个 agent:「resolve this merge conflict。」
改成:手动 resolve(Step 2),然后用现在已经干净的状态重新 prompt 每个 agent。
Step 6:共享配置文件,人工协调更新
CLAUDE.md、package.json、.eslintrc、lockfile——这些都是多个 agent 可能想动的文件。两种办法选一种:
- 禁止 agent 编辑它们(「
CLAUDE.md只允许人改」) - 或者协调时机——这些文件一次只让一个 agent 动
# CLAUDE.md
## Agent 不许并行修改的文件
- 本文件(CLAUDE.md)
- package.json(engines、scripts)和 lockfile
- .eslintrc、tsconfig.json
- migrations/
这些文件一次最多只允许一个 agent 动。
如何确认已经修好
git status报nothing to commit, working tree clean,且没有列出任何both modified路径。git diff --check没有任何输出——整个 tree 里没有残留的冲突标记。- 你的完整测试套件通过,包括两个 task 各自加的测试(猜出来的 resolution 通常会留下某一个 task 的测试是红的)。
git worktree list只显示你打算保留的那些 worktree。
预防建议
- 在跑并行 agent 之前先 plan 好不相交的文件 scope——重叠 = 注定冲突
- 任何并行 agent、或者并行加手动编辑,都走 git worktree(或者用 Codex / Claude Code subagent 里内置的 worktree 隔离)——独立的 working tree 不可能撞
- 禁止 agent 去 resolve merge 冲突;合并是一个刻意的人为步骤
- 共享配置文件(
CLAUDE.md、package.json、lockfile)一次只允许一个写者 - 顺序往往比并行更安全——只有在 scope 真的不重叠时才并行
- task 看着独立时,先
grep -rl找共享文件验证一下——名字会骗人
FAQ
既然代码是 Claude 或 Codex 写的,是不是干脆让它来 resolve 冲突? 不行。负责 resolve 的那个 agent 只能看到代码,看不到另一个 agent 改动背后的推理,所以它会悄悄丢掉某个 task 的意图。先手动 resolve,再把干净的状态交给每个 agent 继续。
git worktree 能彻底杜绝冲突吗? 它能在 agent 工作期间杜绝文件系统层面的碰撞——两个 agent 永远不会互相覆盖对方的文件。但当你把分支合并回来时,如果它们的 scope 重叠,你仍然可能遇到一个正常的 merge 冲突,这就是为什么即便用了 worktree,不相交的 scope(Step 3)依然重要。
我的 merge 卡到一半、看着一团糟——怎么从头来?
跑 git merge --abort(或 git rebase --abort)。它会把 working tree 恢复到 merge 之前的状态,两支上都不丢任何改动,这样你可以重新 plan 再试。
冲突只在 package-lock.json / pnpm-lock.yaml 里。要手改它吗?
不要。先 resolve package.json,删掉冲突的 lockfile,然后用 npm install / pnpm install 重新生成它,让它和合并后的 manifest 精确一致。
怎么检查没有冲突标记漏过去?
跑 git diff --check。它会在你 commit 之前标出任何残留的 <<<<<<<、======= 或 >>>>>>> 行以及空白错误。
现在 Claude Code 和 Codex 都有内置 worktree 了,我还需要手动跑 git worktree 命令吗?
做一次性的并行工作,不需要——claude --worktree <name> 和 Codex app 的 Worktree 模式会帮你处理创建和清理。当你需要 checkout 一个已存在的特定分支、把 worktree 放到 repo 之外、或者用 Codex CLI(截至 2026 年 6 月它还没有内置 worktree 标志)时,才手动用 git worktree add。
相关阅读
外部参考:git-worktree 文档、git-merge —abort、Claude Code worktrees、Codex app worktrees。
标签: #排查 #Claude Code #排查 #误改