Git
英语 ▾ 主题 ▾ 最新版本 ▾ git-rerere 最后更新于 2.39.0

名称

git-rerere - 重用记录的冲突合并解决方案

概要

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

描述

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

此命令通过在初始手动合并时记录冲突的自动合并结果和相应的手动解决结果,并将先前记录的手动解决应用到其相应的自动合并结果,来帮助开发人员完成此过程。

注意
你需要设置配置变量 rerere.enabled 才能启用此命令。

命令

通常,git rerere 在没有参数或用户干预的情况下运行。但是,它有一些命令允许它与其工作状态交互。

清除

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

忘记 <路径规范>

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

差异

显示解决的当前状态的差异。它对于跟踪用户解决冲突期间发生的更改非常有用。附加参数直接传递到 PATH 中安装的系统 diff 命令。

状态

打印具有冲突的路径,rerere 将记录这些冲突的合并解决。

剩余

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

垃圾回收

修剪很久以前的冲突合并记录。默认情况下,未解决的冲突超过 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

标记为 * 的提交触碰了同一文件中的同一区域;你需要在创建标记为 + 的提交时解决冲突。然后你可以测试结果,以确保你的正在进行的工作仍然与最新的主分支兼容。

在进行此测试合并后,有两种方法可以继续在主题分支上工作。最简单的方法是在测试合并提交 + 之上构建,当你的主题分支工作最终准备好时,将主题分支拉取到主分支,或者要求上游从你那里拉取。但是,到那时,主分支或上游可能已经比测试合并 + 更先进,在这种情况下,最终的提交图将如下所示

	$ 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^ ;# rewind the test merge
	$ ... 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

当你的主题分支最终准备好并合并到主分支时,这只会留下一个合并提交。这将需要你解决由标记为 * 的提交引入的冲突。但是,这通常与你在创建你删除的测试合并时所解决的冲突相同。git rerere 帮助你使用之前手动解决的信息来解决此最终冲突合并。

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

下次,在看到相同的冲突自动合并后,运行 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 rerere 将由 git rebase 运行,以帮助你解决此冲突。

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

GIT

git[1] 套件的一部分

scroll-to-top