Git rerere:让重复冲突只解决一次

摘要

长期分支反复合并或变基时,相同冲突可能被多次触发。Git rerere 能记录人工解决结果,在冲突再次出现时自动复用,减少重复操作,同时保留人工检查与回退空间。

问题背景

在短生命周期分支里,一次合并通常只需要解决一次冲突。

但真实项目经常不是这样。一个功能分支可能持续数周,中间要反复同步主分支;一个补丁系列也可能在评审期间多次执行 rebase。只要双方持续修改相同区域,同一组冲突就会重复出现。

常见过程大致是:

text 复制代码
第一次 rebase:解决冲突,继续提交
主分支更新后再次 rebase:重新解决相似冲突
调整提交历史后再次 rebase:第三次处理同一组冲突

最让人浪费时间的不是冲突本身,而是开发者明明已经做过判断,Git 却不知道上一次是怎么解决的。

我最后采用的方案是启用 rerere,让 Git 记录冲突前后的内容,在相同冲突再次出现时复用之前的人工处理结果。

rerere 解决了什么问题

rerere 是 reuse recorded resolution 的缩写,可以理解为"复用已记录的冲突解决方案"。

第一次遇到冲突时,仍然需要开发者手动判断并修改文件。文件解决并加入暂存区后,Git 会记录这次处理结果。

之后如果出现相同的冲突形态,Git 会尝试把之前的结果重新应用到工作区。

它并不会替开发者理解业务,也不是一个通用的自动合并算法。它只是把已经做过的人工判断保存下来,避免重复劳动。

Git 官方文档对它的典型场景描述得很明确:长期存在的主题分支需要反复合并或变基时,开发者可能多次解决同样的冲突,而 rerere 可以记录并复用第一次的人工解决结果。

启用 rerere

可以只在当前仓库启用:

bash 复制代码
git config rerere.enabled true

也可以全局启用:

bash 复制代码
git config --global rerere.enabled true

检查当前配置:

bash 复制代码
git config --get rerere.enabled

返回 true 就说明已经开启。

如果希望 Git 在复用解决结果后自动把文件加入暂存区,还可以启用:

bash 复制代码
git config --global rerere.autoupdate true

我更倾向于一开始只开启 rerere.enabled,暂时不启用 rerere.autoupdate。这样 Git 可以帮忙恢复内容,但文件是否进入暂存区仍由开发者确认,第一次使用时更容易理解真实行为。

第一次冲突仍然需要手动处理

假设当前功能分支需要变基到主分支:

bash 复制代码
git switch feature/order-flow
git fetch origin
git rebase origin/main

Git 报告冲突后,先检查状态:

bash 复制代码
git status

再打开冲突文件,处理这些标记:

text 复制代码
<<<<<<< HEAD
主分支内容
=======
功能分支内容
>>>>>>> feature/order-flow

修改完成后加入暂存区并继续:

bash 复制代码
git add src/order/service.ts
git rebase --continue

启用 rerere 后,Git 会在这个过程中记录冲突内容和最终解决结果。第一次操作看起来和普通冲突处理没有明显区别,真正的差异会在下一次相同冲突出现时体现。

再次遇到冲突时会发生什么

当分支之后再次 rebase,并出现同样的冲突,Git 会尝试恢复上一次的结果。

终端通常会出现类似提示:

text 复制代码
Resolved 'src/order/service.ts' using previous resolution.

这时不要直接认为任务已经完成,先检查工作区:

bash 复制代码
git status
git diff

确认内容正确后再继续:

bash 复制代码
git add src/order/service.ts
git rebase --continue

如果启用了 rerere.autoupdate,Git 可能已经把复用成功的文件加入暂存区。此时应该同时检查普通 diff 和暂存区 diff:

bash 复制代码
git diff
git diff --cached

rerere 最有价值的地方不是让开发者跳过检查,而是把"重新手写同一个结果"变成"检查上一次结果是否仍然适用"。

几个有用的 rerere 命令

查看当前有哪些文件正在使用 rerere:

bash 复制代码
git rerere status

查看 rerere 记录的解决差异:

bash 复制代码
git rerere diff

查看仍未解决的路径:

bash 复制代码
git rerere remaining

如果发现某个路径记录了错误的处理结果,可以让 Git 忘记它:

bash 复制代码
git rerere forget src/order/service.ts

然后重新手动解决这次冲突并加入暂存区,Git 会记录新的结果。

清除当前冲突会话的 rerere 元数据可以使用:

bash 复制代码
git rerere clear

这几个命令里,我最常用的是 statusdiffforget。前两个用于确认复用内容,后一个用于纠正错误记录。

一个更适合 rerere 的工作流

rerere 在频繁 rebase 的功能分支里尤其合适。

例如一个分支需要持续跟随主分支:

bash 复制代码
git switch feature/order-flow
git fetch origin
git rebase origin/main

第一次遇到冲突:

text 复制代码
手动理解双方改动
完成业务层面的合并
运行测试
继续 rebase

之后再次遇到相同冲突:

text 复制代码
让 rerere 应用历史结果
检查 diff
运行测试
继续 rebase

真正节省的是第二次以及之后的重复处理成本。

如果冲突只会出现一次,rerere 的收益并不明显;如果同一分支会持续同步主线,它的价值会随着重复次数增加。

为什么不能完全相信自动复用

相同的文本冲突不一定代表相同的业务语义。

例如第一次冲突时,保留旧字段是正确的;两周后主分支已经重构了接口结构,即使 Git 识别出相同冲突,上一次的结果也可能不再适用。

因此每次复用后至少要做三类检查:

text 复制代码
检查 diff 是否符合当前需求
运行受影响模块的测试
确认没有残留冲突标记

可以搜索冲突标记:

bash 复制代码
git grep -n -e '<<<<<<<' -e '=======' -e '>>>>>>>'

如果项目支持定向测试,优先运行受影响模块,而不是只确认代码能够提交:

bash 复制代码
npm test -- order

或者:

bash 复制代码
./gradlew test

rerere 降低的是重复编辑成本,不应该降低验证标准。

适合使用的场景

rerere 比较适合这些工作流:

  • 长期存在的功能分支持续同步主分支
  • 大型重构期间反复执行 rebase
  • 补丁系列根据评审意见多次重排提交
  • 多个发布分支反复吸收同一批修复
  • 合并结果需要先验证,再撤销并等待正式合入

它不太适合被包装成"所有冲突自动解决工具"。如果团队很少遇到重复冲突,或者每次冲突的业务上下文差异很大,收益会比较有限。

常见误区

误区一:启用后第一次冲突也会自动解决

不会。rerere 必须先看到一次人工解决结果,之后才能尝试复用。

误区二:出现 Resolved 提示就可以直接提交

不建议。复用结果仍然要经过 diff 和测试检查,尤其是在主分支持续演进时。

误区三:记录错误后只能关闭 rerere

不需要。可以使用 git rerere forget <path> 删除指定路径的错误记录,再重新解决。

误区四:rerere 记录会自动分享给团队

默认不会。相关记录保存在本地仓库的 Git 元数据中。它首先是个人工作流优化,不是团队冲突规则库。

最后总结

重复冲突最浪费时间的地方,是开发者已经做过一次正确判断,却不得不再次手动输入同样的结果。

rerere 的思路很克制:第一次仍由人解决,Git 只负责记录;之后出现相同冲突时,Git 复用历史结果,人再负责检查。

对长期分支和频繁 rebase 的项目来说,这比单纯加快冲突编辑更可靠。它不会消除冲突,但能把重复劳动压缩成一次可审查的复用过程。

参考资料:Git rerere 官方文档

相关推荐
嘻嘻仙人4 天前
Ubuntu中 git上传自己的项目和二次上传一般流程
git·github
Patrick_Wilson4 天前
Squash Merge 的血缘陷阱:为什么删掉的代码又活了过来
前端·git·程序员
沉浸学习的匿名网友4 天前
什么是 .gitignore?为什么每个 Git 项目几乎都离不开它?
前端·git
深海鱼在掘金5 天前
Git 完全指南 —— 第3章:理解工作区、暂存区、版本库三个核心
git
江华森5 天前
Git 基础筑基:从原理到团队协作的全栈实战
git
JakeJiang5 天前
Git 必备命令指南:从日常高频到项目开发实战
git
叫我少年6 天前
Windows 中安装 git
git
深海鱼在掘金11 天前
Git 完全指南 —— 第1章:Git 概览与版本控制演进
git
noravinsc12 天前
关于Git Flow
git