简体中文 ▾ 主题 ▾ 最新版本 ▾ 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 <pathspec>

重置 rerere 为 <pathspec> 中当前冲突记录的冲突解决。

diff

显示当前解决状态的 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

标记为 * 的提交修改了同一文件中的同一区域;您需要解决标记为 + 的提交创建时的冲突。然后,您可以测试结果,以确保您的工作仍在最新的主分支上正常运行。

在此测试合并之后,有两种方法可以继续在主题分支上进行工作。最简单的方法是基于测试合并提交 + 继续开发,当您的主题分支工作最终准备好时,将主题分支合并到主分支,以及/或请求上游合并您的分支。然而,届时,主分支或上游可能已经自 + 测试合并以来有所前进,在这种情况下,最终的提交图谱将如下所示。

	$ 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 rebase 将运行 git rerere 来帮助您解决此冲突。

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

GIT

Git[1] 套件的一部分