简体中文 ▾ 主题 ▾ 最新版本 ▾ 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 配置变量控制。

讨论

当您的主题分支修改了自其从 master 分支(或上游)派生以来,master 分支(或上游)已触及的重叠区域时,您可能希望用最新的 master 进行测试,即使您的主题分支尚未准备好推送到上游。

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

为了进行此类测试,您需要以某种方式合并 master 和主题分支。一种方法是将 master 拉取到主题分支中。

	$ 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 抱怨过这种过于频繁的测试合并。

作为替代方案,为了使主题分支不受测试合并的干扰,您可以放弃测试合并,并继续在测试合并之前的顶端之上构建。

	$ 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 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