多智能体并行开发:用 Git rerere 一次冲突重复解决

git rerere 通过记录一次冲突解决,在多智能体并行开发中把重复冲突的手动处理从三次降到一次。
当 Claude Code 和 Codex 分别在独立分支修改同一文件时,同样的合并冲突会在试合并和正式落地、rebase 中反复出现。开启 `git config rerere.enabled true` 后,Git 会在自动合并失败时记录冲突的 preimage,在你手动解决并提交后保存 postimage,之后遇到完全相同的冲突块便自动重放。由于同一仓库的所有 worktree 共享 `.git` 目录,`rr-cache` 与配置是全局生效的,这正是多智能体并行场景中该功能从锦上添花变为基础设施的原因。但 rerere 只比较文本、只匹配相同冲突块,且不会自动暂存结果,因此每次重放后都应 `git diff` 检查并运行测试。
当 Claude Code 和 Codex 同时在两个分支上修改同一个文件时,合并冲突几乎不可避免。更糟的是,同样的冲突会在试合并阶段出现一次,在正式落地第一个智能体、rebase 第二个时再出现一次。Git 的 rerere 功能正是为此而生:记录一次冲突解决方式,之后自动重放。

问题场景:同一行代码,两次手动解决
假设你给 Claude Code 分配了登录模块的 bug,给 Codex 分配了认证逻辑的清理任务。两个智能体各自在独立分支上工作并完成修改。你先把两者合并到一个临时分支跑测试,src/login.js 中的 guard clause 发生冲突。你阅读两个版本,写下同时保留两处修复的那一行,测试通过。
随后你正式落地第一个智能体,将第二个 rebase 到 main。同一个文件、同一行、同样的冲突,你又手动解决了一遍。如果智能体在最终落地前再次触碰那个分支,你可能还得解决第三次。据 Git 官方文档(Pro Git 及 git-rerere 手册),git rerere 即 "reuse recorded resolution",专门解决这类重复冲突问题。
什么是 Git worktree
git worktree 允许从同一个仓库中检出多个工作树,每个工作树对应一个独立的分支,但共享底层的 .git 目录(包括对象数据库、引用、配置和 hooks)。这意味着你可以在 ../fix-login、../tidy-auth 等不同目录下同时拥有 hermes/fix-login 和 hermes/tidy-auth 两个分支的完整工作副本,而不需要反复 git checkout 来回切换。对并行运行的多个编码智能体来说,这一点至关重要:Claude Code 和 Codex 各自在一个独立的 worktree 中工作,互不干扰对方的暂存区和工作目录,但它们的提交都进入同一个仓库历史。也正因为 .git 共享,rerere 的 rr-cache 和 rerere.enabled 配置才能被所有 worktree 共用。
开启 rerere:一次配置,全程自动
设置只需要一条命令:
git config rerere.enabled true
Git 官方文档指出,当自动合并失败时 git merge 会自动运行 rerere,而 git commit 在提交合并结果时再次运行它。正常流程中你不需要手动调用。另外,如果仓库中已存在 rr-cache 目录,Git 也会默认开启该功能(见 Git 配置参考文档)。
实际操作演示如下:创建仓库和初始文件,为每个智能体创建独立分支和 worktree:
git worktree add -q -b hermes/fix-login ../fix-login
git worktree add -q -b hermes/tidy-auth ../tidy-auth
第一个智能体拒绝空密码,第二个智能体修剪用户名,两者修改同一行代码。在临时 worktree 中做试合并:
git worktree add -q -b try-both ../try-both main
cd ../try-both
git merge -q hermes/fix-login
git merge hermes/tidy-auth
第二次合并触发 CONFLICT (content),同时 Git 输出以 Recorded preimage for 开头的行。手动解决冲突后,在提交前可用两个子命令检查 rerere 将记住什么:
git rerere status # 将记录解决方式的路径
git rerere diff # 冲突版本与当前编辑的对比
提交时 Git 输出 Recorded resolution for。这个分支已经是两个智能体工作的合并结果,在此运行测试。
rr-cache 的结构与 preimage/image 概念
rerere 在 .git/rr-cache/ 下为每次冲突创建一个以冲突哈希命名的目录,其中包含三个关键文件:preimage(冲突发生前、带冲突标记的原始内容)、postimage(你手动解决后的内容)和 thisimage(本次遇到的冲突版本)。当 rerere 检测到新的冲突时,它会计算冲突块的规范化哈希——该哈希刻意剔除了行号和一些上下文无关信息,只基于冲突的“内容形状”——然后去 rr-cache 中查找匹配的目录。若命中,就把记录中的 postimage 直接写入工作文件;若未命中,则在解决并提交后把当前解决方案存为新的条目。理解这个机制就能明白文章强调的两个限制:为什么“只匹配完全相同的冲突块”(哈希必须一致),以及为什么“只比较文本”(哈希不编码语义)。
落地第一个智能体后,rebase 自动重放
试合并仅用于测试。正式落地时,将第一个智能体合并进 main,再从第二个智能体自己的 worktree 中 rebase:
cd ../rerere-demo
git merge -q hermes/fix-login
cd ../tidy-auth
git rebase main
rebase 遇到相同冲突,但这次 Git 输出 Resolved 'src/login.js' using previous resolution.,文件中已经是合并后的那一行。据 Pro Git 章节描述,正是这种流程:先手动解决一次合并,随后在 rebase 中由 rerere 自动填入解决结果。
需要注意 rerere 没有做什么。官方文档明确说它 "leaves the index file alone",路径仍被视为冲突状态,rebase 仍会暂停。你需要检查、暂存、继续:
git diff # 检查 rerere 写入的内容
git add src/login.js
GIT_EDITOR=true git rebase --continue
有一个 rerere.autoUpdate 设置可以自动暂存重放的文件,但它默认为 false。Git rebase 文档将 --no-rerere-autoupdate 描述为 "a good way to double-check what git-rerere did and catch potential mismerges"。面对两个智能体写的、并非你亲手输入的代码,这个额外检查值得多一次 git add。
当记录的解决方案是错的
rerere 会重放你记录的任何内容,包括错误。假设试合并时你保留了修剪后的用户名,却丢掉了密码检查,rerere 会在每次相同冲突出现时写回这个错误。
修复方法是在 rebase 暂停于冲突时,丢弃记录并重建冲突标记:
git rerere forget src/login.js
git checkout --conflict=merge src/login.js
**为什么 `git checkout --conflict=merge` 能恢复冲突**
发生冲突时,Git 会在索引中为每个冲突路径保存三个阶段的条目:stage 1 是共同祖先版本,stage 2 是当前分支版本,stage 3 是待合并分支版本。即使在解决冲突、写入合并内容之后,只要还没 `git add`,这三个阶段条目通常仍然存在。`git checkout --conflict=merge`(等价于 `--conflict=diff3` 之外的默认样式)会读取这些索引阶段,重新生成带 `<<<<<<<`、`=======`、`>>>>>>>` 标记的文件,把工作区恢复到冲突未解决的状态。这就是为什么在 rerere 重放了错误方案后,这条命令配合 `git rerere forget` 能让你“从头再来”:`forget` 清掉错误的记录,`checkout` 重建标记,你再手工写出正确的一行,随后 `git rerere` 会把新方案重新记录。
# 手动修复文件后:
git rerere
git add src/login.js
GIT_EDITOR=true git rebase --continue
forget 重置 rerere 为当前冲突记录的解决方式,git checkout --conflict=merge 重新生成带标记的冲突文件。
使用前需要了解几个限制:
- 只匹配完全相同的冲突块。如果智能体重写了那一行的版本,冲突是新的,需要再解决一次。
- 只比较文本。重放的解决方案对其他地方已变化的代码可能是错的,每次重放后都要运行测试。
git rerere gc会清理旧记录:未解决的 15 天后清理,已解决的 60 天后清理,由gc.rerereUnresolved和gc.rerereResolved配置。如果智能体分支存活更久,需要调高这些值。- 它通过冲突标记来识别冲突。文件中本来就包含类似
<<<<<<<的行会混淆它,官方文档指向conflict-marker-size属性作为解决方案。
多 worktree 环境下 rerere 的协同价值
在 Hermes IDE 这类并行运行 Claude Code、Codex 的桌面应用中,rerere 的优势更加明显。据 Git 仓库布局文档,同一仓库的所有 worktree 共享一个 .git 目录,而 rerere 存储记录的 rr-cache 被标记为共享目录,仓库配置也是共享的。
这意味着只需执行一次 git config rerere.enabled true,在一个任务 worktree 中解决的冲突即可在任何其他 worktree 中重放。演示中,你在 ../try-both 中记录解决方案,Git 在 ../tidy-auth 中重放了它。
整体流程与命令行一致:落地第一个任务(本地合并或等 PR 合并后拉取基础分支),使基础分支包含第一个智能体的改动;从第二个任务的 worktree 终端中将其分支 rebase 到该分支,rerere 自动填入已解决的代码行;审查文件、git add、运行 git rebase --continue,然后落地第二个任务。
如果选择让智能体执行 rebase 也一样,因为 rerere 的记录和配置都存在仓库中,智能体的 git rebase main 会像你手动执行时一样读取已记录的解决方案。
核心要点
两个智能体、两个分支是最简单的多智能体配置,却已经会产生重复冲突。git rerere 通过一次记录、自动重放,将手动解决冲突的次数从三次降到一次。在多 worktree 并行开发环境中,这个特性从"锦上添花"变成了"基础设施"。
相关推荐

JetBrains孵化ThinkRail:基于Pi的智能体IDE,规格驱动开发新体验
JetBrains Innovation Hub孵化的开源智能体IDE ThinkRail,基于Pi构建,支持规格驱动开发、Git worktree并行工作区与Monaco编辑器交互,完全免费。本文详解其安装、工作流与生态整合。

主流世界之外:被忽视地区的安全与隐私困境
人本安全研究长期集中于西方,导致安全方案在主流世界失效。研究者Collins Minando基于肯尼亚移动贷款应用、网吧认证困境及九国本地专家研究,揭示社会经济约束如何重塑隐私实践,并提出移动货币隐私重设计与PETs部署路径。

Claude被曝可在正常图片中隐藏秘密信息
Reddit帖子称Claude Fable 5.1能在正常图片中隐藏秘密信息,本文梳理事件背景、图片隐写技术原理及潜在安全风险,并给出从传闻走向验证的测试路径建议。