如何自动解决git rebase“ git add”中的所有冲突。

时间:2019-11-05 21:45:12

标签: bash git rebase git-rebase git-add

我正在处理的项目是带有父子模块的Maven应用程序。对父模块的更改进入开发分支。每个子模块都有自己的分支,该分支从开发基础上重新继承以继承这些更改。

截至目前,我正在尝试设置一个变基脚本。为此,我试图找出一种自动解决所有冲突且不会中断的方法。作为测试的一部分,我将始终根据自己的更改来重新设置我从开发中获得的测试分支:

git ls-files -z *_child | xargs -0 git update-index --skip-worktree #I do not want the child module to be touched

git rebase -X theirs development

但是,重新定位过程仍然被冲突打断,通常是因为几个月前已解决的非常古老的提交。为了解决这个问题,我使用:

git add .
git rebase --continue

在我遇到另一个冲突之前,这一直有效。目前,我正在考虑使用git rerere来记录我采取的解决措施:

git config --local rerere.enabled true

但是,我仍在尝试弄清重新定基的实际工作方式。您对git rerere或其他一些git命令有任何建议来解决此问题吗?理想情况下,我想一并剔除git add .,并始终将默认冲突更改为“其”更改。

1 个答案:

答案 0 :(得分:1)

重要的注意事项:您的git update-index在这里不是很有用。如果基础合并操作需要触摸标记为--skip-worktree的文件,则Rebase将需要触摸它们。如果没有,它将不会碰到它们。标记文件可能会在执行自动选择操作时给您一个有用的错误(我尚未测试过,但您可以自己对其进行测试)。


重复进行基础git cherry-pick(有时是等效的)。每个小巧的选择都使用合并过程(我喜欢称谓 merge作为动词 merge ),并且您会看到,合并可能会有合并冲突。 git cherry-pick与普通合并不同的两种方式是:

  1. 合并基础只是被精心挑选的提交的父级。
  2. 最后要进行的提交是常规(非合并)提交。

启用rerere与在其他git merge上具有相同的效果,因为记录的分辨率的重用以相同的方式发生。这不会对您有帮助,因为您已经在使用-X theirs,因此可以避免rerere可以解决的那种冲突。

合并期间的冲突可能是由于我所说的高级操作,整个文件树上的冲突或低级合并工作引起的。我使用这两个短语来区分Git合并引擎中的两个不同的代码部分。合并实际上是通过运行两个git diff操作进行的:

git diff --find-renames <base> <tip1>
git diff --find-renames <base> <tip2>

这些差异位于git merge的内部,该差异具有内置的差异引擎,并且可以传递很难通过命令行实现的各种选项,但是原理是相同的:

  1. 重命名查找将查看添加和/或删除的文件,并尝试将左侧(合并基础侧)“已删除”文件与右侧“已添加”文件进行匹配。如果是这样,Git决定将该文件重新命名为

  2. 像这样匹配文件名会生成身份映射:名为 F B 的基本文件具有新名称​​ F L 位于左侧, F R 位于右侧。这三个名称可能相等,或者两个或三个名称可能不同,但是无论哪种方式,这都是“相同”的文件。它还使我们可以在任一侧添加和/或删除文件,并且可以在一侧或两侧修改或不修改的文件。

  3. 现在我们必须结合所有更改……但这首先发生在文件名和存在性级别:

    • 如果左侧删除文件 F d ,而右侧未更改文件,则可以。但是,如果左侧将其删除而右侧对其进行了修改,则我们将发生删除/修改冲突。 (如果右侧删除了它,而左侧修改了它,则我们有相同的冲突,相反)。

    • 如果左侧重命名文件而右侧删除文件(或两边互换),则我们会出现重命名/删除冲突

    • 如果双方从头开始添加新文件但名称相同,则我们会发生添加/添加冲突

    • 如果双方都重命名了基本文件 F B ,但重命名为两个不同的名称* F L F < sub> R ,我们有一个重命名/重命名冲突


    Git单独解决了这些冲突。这些是高级冲突。

    已经解决(或未解决)任何高级树操作,现在我们遇到了以下情况:同一文件已从基础转移到两个分支提示中,其中“同一个文件”按上述方式进行了重命名,但已被两个文件修改双方。 Git现在从名为ll-merge.c的单独文件中运行代码:低级合并代码。

    LLMerge允许用户定义合并驱动程序。使用这些文件时,整个操作取决于合并驱动程序,合并驱动程序仅获取所有三个输入文件的数据(基本,左/ HEAD和右/它们的)。使用内置的合并驱动程序时,可以使用-X扩展选项自动解决冲突 -X theirs选择右侧更改,放弃左侧更改侧(base-vs-HEAD)更改。 -X ours选择左侧更改。没有这些选项,当更改重叠或邻接时,Git只会声明冲突。

由于您正在使用-X theirs并发生冲突,因此我们可以得出结论,您肯定会遇到高级冲突。 Git的rerere代码不会记录,也不能重复使用这些分辨率。

要在合并由于冲突而停止后发现它们,可以使用git status或使用git ls-files --stage检查索引/暂存区。不幸的是,Git在记录实际发生的高级别冲突方面做得很差(大多数情况下不存在)。它打印冲突,因此,如果您捕获了输出,则可以对其进行解析;或者,您可以运行自己的git diff --find-renames --name-status命令来查看合并所看到的内容。

在合并的一般情况下,git diff --find-renames存在问题,因为git merge可能会建立一个临时提交,其中包含Git所说的虚拟合并基础。但是,对于Cherry-pick,合并基础只是当时选择的提交的父级,因此使用此方法可能是可靠的。您将不得不以任何一种方式编写代码。

相关问题