Git合并与变基 - 解决冲突

7

这段内容有点长,但我认为它可能是一个有趣的问题。

尽管很多人不情愿,但我们公司最近才开始使用git,在小项目中有些人成功地开始使用它,现在我们实际上在更相关的项目中使用它。

我总是试图在合并之前进行rebase,但最近我们发现了这种方法的一个问题。

想象一下你有一个文件F,你有以下git历史记录:

(master)       F -- F''1
                \
(feature)        \- F'1 -- ... -- F'X

现在,如果您对功能分支进行了变基,并且在解决第一个冲突时,您实际上保留了来自F''1和F'1的更改,则必须手动解决文件F的X个冲突,因为git无法自动解决它们。相反,如果您只是进行了合并(而没有变基),则只需解决一个(“大”)冲突。这让我质疑变基的实际价值,因为这可能是非常繁琐的工作。
我是否遗漏了什么或者这就是事实?如果您在一个文件上有30个提交,您将不得不逐个查看每个提交并手动解决任何冲突。是否有更合适的方法来处理这种情况?
如果我解释得不太清楚,很抱歉,但您可以尝试在虚拟存储库中重复我提到的步骤,我认为您会明白我的困扰。

1
接受 torek 的答案怎么样? - Mr_and_Mrs_D
1个回答

9
您是正确的:您必须保持重新解决冲突,通常是相同的方式。
然而,有一个自动化开关可以做到这一点,称为git rerere。这三个re代表重用记录的解决方案
它的工作方式是每次遇到冲突时,当您使用git add解决版本时,git会将原始冲突(减去行号)和解决方案保存在某些文件中(实际上只是存储在存储库内部的blob对象)。然后,在宣布冲突之前,合并代码会检查原始冲突是否已与解决方案相关联。如果是,则用该解决方案替换冲突区域。
由于在记录冲突之前削减了行号,因此通常情况下可以处理经常发生的冲突。(当周围的上下文发生变化时,它会失败,因为这会更改冲突/解决方案对的哈希ID。)
它有一点危险,因为有时看起来相同但在文件中远离的冲突并不是真正相同的冲突(这往往发生在模板代码中)。由于记录了每个冲突和解决方案,因此您可能会积累很多解决方案并获得虚假的匹配。Git尝试通过在60天内过期记录的解决方案(和仅在15天内未解决的冲突)来处理此问题。
您必须在创建第一个冲突之前启用rerere,并在使用git add解决方案时保持其启用。这有点烦人,因为通常情况下,您(我)会发现我可能早应该启用rerere,现在为时已晚。我一直想编写一个脚本,重复以前已经解决过的合并或rebase,使用现有的解决方案,输入到rerere-replay中以启动rerere引擎。(这个脚本的明显名称是git-rererere... :-) )

我已经处理过这个问题很多次了,我总是采用以下方法。假设我的分支中有30个提交,一旦我的拉取请求被审核并且可以使用,最后一步就是与主分支进行rebase操作。首先,我将我的特性分支的30个提交压缩成一个单独的提交,然后以这种方式与主分支进行rebase操作,这样我就不必一遍又一遍地解决所有冲突。 - Muhammad Shoaib
在创建第一个冲突之前,您必须启用rerere...为什么不使用git config --global rerere.enabled true - Mr_and_Mrs_D
1
@MuhammadShoaib:所以你实际上摧毁了所有的历史记录,太棒了。 - Mr_and_Mrs_D
@Mr_and_Mrs_D:您确实可以始终将rerere.enabled设置为true。不过我从来没有那么勇敢过。 - torek

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