Git

名称

git-rerere - 重复使用已记录的冲突合并解决方法

概述

git rerere [clear|forget <pathspec>|diff|remaining|status|gc]

描述

在采用相对较长的特性分支的工作流程中,开发人员有时需要反复解决相同的冲突,直到特性分支完成(要么合并到 “发布” 分支,要么发送到上游并被接受)。

在此过程中,该命令通过记录冲突的自动合并结果和初始手动合并的相应手工解析结果,并将先前记录的手工解析结果应用于相应的自动合并结果,来帮助开发人员。

Note
您需要设置配置变量 rerere.enabled 才能启用该命令。

命令

通常,git rerere 的运行不需要参数或用户干预。 不过,它有几条命令允许它与工作状态交互。

clear(清除)

如果要中止合并解析,重置 rerere 使用的元数据。 调用 git am [--skip|--abort]git rebase [--skip|--abort] 会自动调用此命令。

forget <路径规范>

重置 rerere 在 <路径规范> 中记录的当前冲突的冲突决议。

diff

显示当前冲突解决状态的差异。 这对于跟踪用户在解决冲突时发生了哪些变化非常有用。 附加参数会直接传递给安装在 PATH 中的系统 diff 命令。

status

打印有冲突的路径,rerere 将记录其合并解决方案。

remaining

打印 rerere 尚未自动解决冲突的路径。 这包括 rerere 无法跟踪其解决的路径,如冲突的子模块。

gc

修剪很久以前发生的冲突合并记录。 默认情况下,超过 15 天的未解决冲突和超过 60 天的已解决冲突会被剪除。 这些默认值分别由 gc.rerereUnresolvedgc.rerereResolved 配置变量控制。

讨论

当你的特性分支修改了主分支(或上游分支)从特性分支分叉出来后接触过的重叠区域时,你可能想用最新的主分支进行测试,甚至在特性分支准备好推送到上游之前:

              o---*---o topic
             /
    o---o---o---*---o---o master

要进行这样的测试,需要以某种方式合并主分支和特性分支。 一种方法是将主分支拉入特性分支:

	$ git switch topic
	$ git merge master

              o---*---o---+ topic
             /           /
    o---o---o---*---o---o master

标有 * 的提交涉及同一文件中的同一区域;您需要在创建标有 + 的提交时解决冲突。 然后,您就可以测试结果,以确保您正在进行的工作仍能与最新的 master 中的内容一起运行。

测试合并后,有两种方法可以继续主题工作。 最简单的方法是建立在测试合并提交 + 之上,当你在特性分支中的工作最终准备就绪时,将特性分支拉入主分支,和/或请求上游从你那里拉取。 不过,到那时,主分支或上游分支可能已经在测试合并 + 后提前了,在这种情况下,最终的提交图会是这样的:

	$ git switch topic
	$ git merge master
	$ ... work on both topic and master branches
	$ git switch master
	$ git merge topic

              o---*---o---+---o---o topic
             /           /         \
    o---o---o---*---o---o---o---o---+ master

然而,当你的特性分支寿命很长时,你的特性分支上就会有很多这样的 “从主分支合并” 提交,这将不必要地扰乱开发历史。 Linux 内核邮件列表的读者可能还记得,当一个子系统维护者要求从一个充满 “无用合并” 的分支中拉取代码时,Linus 抱怨过这种过于频繁的测试合并。

作为一种替代方法,为了使主题分支不受测试合并的影响,可以删除测试合并,并在测试合并之前继续在提示之上构建:

	$ git switch topic
	$ git merge master
	$ git reset --hard HEAD^ ;# 倒带测试合并
	$ ... 同时在 topic 分支和 master 分支工作
	$ git switch master
	$ git merge topic

              o---*---o-------o---o topic
             /                     \
    o---o---o---*---o---o---o---o---+ master

这样,当你的特性分支最终准备就绪并合并到主分支时,就只剩下一个合并提交了。 这次合并需要解决标有 * 的提交所带来的冲突。 然而,这个冲突往往就是你在创建测试合并时解决的冲突。 git rerere 可以帮助你使用之前手工解决的信息来解决最终的冲突合并。

在自动合成冲突后立即运行 git rerere 命令,会记录下冲突的工作树文件,并在其中加上通常的冲突标记`<<<<<<<=======` 和 >>>>>>>。 稍后,当你解决完冲突后,再次运行 git rerere 就会记录下这些文件已解决的状态。 假设你在创建将 master 合并到主题分支的测试时做了这个操作。

下一次,在看到相同的自动生成器冲突后,运行 git rerere 将在之前的自动生成器冲突、之前的手动解决和当前的自动生成器冲突之间执行一次三向合并。 如果这次三方合并解决得很干净,结果就会写入工作区的文件中,因此你就不必再手动解决了。 请注意,git rerere 不会影响索引文件,因此您仍需要使用 git diff(或 git diff -c)和 git add 进行最后的正确性检查。

为了方便起见,git merge 会在自动合并失败退出时自动调用 git rerere,如果是新的冲突,git rerere 会记录手工解析,如果不是,则重用之前的手工解析。 在提交合并结果时,git commit 也会调用 git rerere 。 这意味着,除了启用 rerere.enabled 配置变量外,你无需做任何特别的事情。

在我们的示例中,当你进行测试合并时,手动解决方法会被记录下来,只要记录下来的解决方法仍然适用,就会在稍后与更新的主分支和主题分支进行实际合并时重复使用。

git rerere 记录的信息也会在运行 git rebase 时使用。 将测试合并后,继续在主题分支上进行开发:

              o---*---o-------o---o topic
             /
    o---o---o---*---o---o---o---o   master

	$ git rebase master topic

				  o---*---o-------o---o topic
				 /
    o---o---o---*---o---o---o---o   master

您可以运行 git rebase master topic,在您的主题准备好被发送到上游之前更新自己。 这将导致退回到三方合并,而且会和之前的测试合并产生冲突。 ' git rebase' 会运行 git rerere 来帮你解决这个冲突。

[注意] git rerere 依靠文件中的冲突标记来检测冲突。 如果文件中已经包含了与冲突标记相同的行,git rerere 可能无法记录冲突解决。 要解决这个问题,可以使用 gitattributes[5] 中的 conflict-marker-size 设置。

GIT

属于 git[1] 文档

scroll-to-top