中文 (简体) ▾ 主题 ▾ 最新版本 ▾ git-rerere 上次更新于 2.39.0

名称

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

概要

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

描述

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

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

注意
你需要设置配置变量 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

对于此类测试,你需要以某种方式合并 master 和 topic。 一种方法是将 master 拉到 topic 分支中

	$ git switch topic
	$ git merge master

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

标有 * 的提交会触及同一文件中相同的区域; 创建标有 + 的提交时,你需要解决冲突。 然后,你可以测试结果以确保你的工作仍在与最新的 master 一起使用。

在此测试合并之后,有两种方法可以继续你在主题上的工作。 最简单的方法是建立在测试合并提交 + 之上,并且当你在主题分支中的工作最终准备就绪时,将主题分支拉入 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

然而,当你的主题分支存在很长时间时,你的主题分支最终会有许多这样的“从master合并”的提交,这会不必要地使开发历史变得混乱。Linux内核邮件列表的读者可能还记得,当一个子系统维护者要求从一个充满“无用合并”的分支拉取时,Linus抱怨过这种过于频繁的测试合并。

作为一种替代方法,为了使主题分支免受测试合并的影响,你可以删除测试合并,并继续建立在测试合并之前的 tip 之上

	$ 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

当你的主题分支最终准备就绪并合并到 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 配置变量)。

在我们的示例中,当你进行测试合并时,会记录手动解决方案,并且只要记录的解决方案仍然适用,它将在稍后使用更新的 master 和主题分支进行实际合并时重用。

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

              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