什么是git-rerere,它是如何工作的?

50

据我理解,rerere 对于通过保存冲突解决信息实现项目同步非常有用,但我不太清楚如何使用和配置它。

我想为我的持续集成 (CI) 环境进行配置。这样做是否推荐?

请不要将此问题标记为重复另一个问题:Are there any downsides to enabling git rerere?。因为我的疑问与“启用 rerere 是否有任何缺点?可能会引起什么潜在问题,这些问题本来不会发生?”无关。


1
可能是启用git rerere有什么缺点吗?的重复。 - mkrieger1
3个回答

79

git rerere是什么?

正如文档所述,rerere代表着reuse recorded resolution。

不过这并没有真正解释清楚它是什么。值得指出的是,git rerere本身——这个命令——你并不需要运行它。它只有六个子命令:clearforgetdiffstatusremaininggc。这些命令都不会记录或重用解决方案——事实上,git rerere cleargit rerere forget <path>只是丢弃一些已经记录的解决方案。而gc命令也类似,但是是针对旧的解决方案。

大部分工作都发生在rerere.enabled的设置上(这使得Git在适当的时候为您运行git rerere,无需使用子命令)。您可以自己运行没有子命令的git rerere,但这并没有真正重要,因为Git会自己运行。

git config rerere.enabled true

一旦您设置了rerere.enabled,当Git进行合并——任何合并,包括来自git amgit rebasegit cherry-pick等操作,并非仅限于git merge——并遇到冲突时,Git将:

  1. 记录(合并动词触发它们后)冲突的diff hunks;
  2. 等待您手动解决它们;
  3. 记录(在git commit时)你解决冲突的过程。

这里缺少一步,所以它从2开始编号。第一步是:

  1. 检查这些冲突是否存在先前记录的解决方案:如果存在,则使用它们自动解决这些冲突。

如果记录的解决方案完全解决了冲突,则步骤2-4变得多余。Git可能仍然会运行它们所有(我不确定它是否这样做)来更新记录解决方案的时间戳。

摘要

一旦设置了rerere.enabled,合并本身就会创建冲突,并且(因为它自动运行没有参数的git rerere)记录它们,然后尝试重用任何现有的记录解决方案。提交本身记录了最终的解决方案(因为Git会自动再次运行git rerere)。所以这一切都是自动完成的——您只需要通过运行自己的git diff命令确保您之前复用的解决方案是正确的。如果不正确,只需像往常一样修复文件,然后添加和提交即可,Git将用新的解决方案替换记录的解决方案。

请注意,您仍然必须执行git addgit commit!您应该始终检查合并结果(或运行测试)——尽管无论您的rerere.enabled设置如何,您都应该这样做。

正如VonC在评论中指出的,如果您有之前未记录的现有合并冲突解决方案,您可以“训练”rerere数据库以采用这些解决方案。 Git源代码中提供了一个贡献脚本来执行此操作;该脚本也可在线获取。


10
当你设置rerere.enabled时,是的,但是不要忘记你可以训练rerere在尚未启用它时解决过的过去冲突。可以手动训练(https://dev59.com/nW855IYBdhLWcg3wxHYq#4155237),也可以通过`contrib/rerere-train.sh`脚本进行训练(https://dev59.com/y2ox5IYBdhLWcg3wWzJ7#45664714)。 - VonC
1
啊哈,train脚本是我一直想要的。 - torek
1
我似乎无法使rerere train脚本正常工作。它一直要求我输入我的PIN来签署我认为在存储库中每个提交。这并不可行。我也不明白为什么它需要这样做,因为提交应该不会在这里更改。 - Martijn Otto
1
@MartijnOtto,火车脚本会重新执行每个合并操作,提交(然后丢弃)结果。如果您已将Git设置为要求在每次提交时使用GPG签名,则必须对所有这些新的合并提交进行签名。该脚本可以在进行此训练时禁用签名。您可以将其作为修复提交到Git邮件列表或脚本作者。 - torek
1
@zaabson:不是的:初始输入需要被记录下来,这发生在git merge停止并出现冲突的时候。你可以中止合并(git merge --abort),然后重新开始;现在启用了rerere新的合并将停在相同的冲突处,并记录它们。如果你已经做了很多工作来解决它们,在git merge --abort之前,你可能想要保存这些工作。当然,我还应该补充一点,也许只运行没有参数的git rerere就足够了。我还没有测试过! - torek
显示剩余2条评论

9

在CI环境中启用rerere是没有意义的,因为首先您的CI环境不应该解决合并冲突。您为什么认为您需要它呢?


1
我似乎无法正确使用rerere train脚本。它一直要求我输入个人识别码,以签署我认为存储库中每个提交的内容。在git 2.38(2022年第3季度)中,它应该要求你输入更少的内容。"rerere-train"脚本(在contrib/中)用于重建一次性合并,现已修复此问题,支持commit.gpgSign
查看 commit cc391fc (2022年7月20日)由 Celeste Liu(CoelacanthusHex 提交。
(由Junio C Hamano -- gitster --合并于commit f0f9a03,2022年8月1日)

contrib/rerere-train:避免在训练中无用的 GPG 签名

签署者:Celeste Liu

用户可能已配置 "git merge"(man),以始终要求对生成的提交进行 GPG 签名。
我们不是在运行 "git merge" 以重新创建合并提交,而仅仅是为了重放合并冲突,并且我们将立即丢弃生成的提交;签署它们没有任何意义。

使用 "--no-gpg-sign" 选项从命令行覆盖强制无用签名的配置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接