Git rebase冲突优化

mwkjh3gx  于 2023-09-29  发布在  Git
关注(0)|答案(2)|浏览(114)

假设我从main创建了一个分支F1。这个F1分支有20个提交。现在我想将这个分支的基重定到main上,以便从main中获取更改

git checkout F1
git rebase -i main

然而,我知道几乎所有在F1上的提交都修改了一个在main上也被修改过的文件。因此,在几乎所有的20个提交中,我将不得不解决冲突。
在commit 1/20中修复冲突似乎是浪费时间,只是为了在2/20和3/20中也发生冲突等等。
我是否应该从F1的第一次提交(1/20)开始变基,并将所有20次提交压缩为1次?然后将其转换为main
例如:

git checkout F1
git rebase -i HEAD~19 (add -squash to the last 19 commits)
git push -f

然后

git checkout F1
git rebase -i main
gkl3eglg

gkl3eglg1#

我们对这个问题有一些很好的评论,我将把它们记下来,并在这里总结成一个总的答案。
我是不是应该...将所有20个提交压缩为1...然后在main上进行rebase?
正如NoDataFound在评论中提到的:
我会说这取决于这些承诺在历史上的重要性!

如果你愿意...

正如Axnyff提到的:
我通常先做squash,然后再做rebase,但是如果你有有意义的提交,你就不应该这样做。
如果你打算最终把20个提交压缩成更少的“好”提交,那么是的,绝对要先压缩,然后再变基。如果你可能不打算压扁它们,但如果你这样做,它并不困扰你,那么同样,你不妨先压扁。请注意,如果你使用的是一个Pull Request工具来跟踪PR中分支的历史,那么考虑在rebase之前创建PR,然后在rebase之后强制推送你的分支,这样20个提交仍然可以在PR的历史中找到。这是在PR工具中保存历史记录的一种方法,即使您在repo本身中没有历史记录。我有时会这样做,当我怀疑在未来的某一天,我可能希望看到更多的个人提交的粒度,也许是为了确定为什么做出某些更改背后的原因,这可能是更大的压缩提交中更难确定的。即使在repo中没有单独的提交,也可以很容易地返回并查看PR以查看原始的提交列表,您可以再次调查甚至在本地 checkout 。

如果你不想被压扁

如果你的提交足够重要,需要保留,即使线性历史很好,有时候拥有线性历史的好处会被实现它的痛苦所超过。这可能是您决定接受合并提交的情况之一。正如Tim Biegeleisen所指出的:
事实上,解决这个问题的简单方法是使用git merge。合并将产生一个事件,其中所有冲突都是一次性的。
这是目前为止最简单的解决方案,即使在严格的变基工作流中,偶尔引入main的合并提交也不会引起太多的担忧。

如果你不想压缩,不能有一个合并提交...

如果你想保留完整的历史记录,但又不想合并提交,那么你就必须处理冲突。有一些选项可以帮助使该过程更有效。LeGEC的评论:
git rerere可以帮助:git config --global rerere.enabled true。有关详细说明,请参见git help rererethe git book
另一种选择是尝试使用-X选项来解决冲突。这将试图通过支持“我们的”或“他们的”来解决冲突。**注意:**当换基时,“我们的”和“他们的”的含义与合并时的含义相反。如果你将main合并到F1中,那么你将检出F1,正如预期的那样,“我们的”是F1,“他们的”是main。然而,当将F1 * 转换为 * main时,在转换期间main是“我们的”,而F1是“他们的”。例如,如果你希望通过在main上保留对F1上的20个提交中的所有冲突的更改来解决冲突,你可以用途:

git rebase main F1 -Xours

注意,当重定基时,您还将看到术语“incoming”和“current”,它们类似于“theirs”和“ours”。More info here.

vzgqcmou

vzgqcmou2#

我现在想将这个分支的基重定到main上,以从main中获取更改
注意,git rebase -i main命令不会这样做!您要查找的语法是

git rebase main F1     # Rebase F1 on top of main (independent on what the current branch is).

我强烈建议你在做rebase的时候,保留你原来的20个提交。
是的,理论上有20个冲突点,然而真正重要的一点是较小的提交首先不太可能产生冲突!
如果你有像“移除未使用的导入”和“重构:提取方法foo”,则导入提交不太可能在其自身上产生冲突,与当其与可能还添加附加导入的一些其他代码组合时相比,具有更少的行被改变,使得许多导入行被一次改变。
对于重构的情况,假设你得到了一个冲突,因为你提取到foo的代码已经在main上被修改了,那么解决这个冲突是微不足道的,因为你只是从main的版本中复制了所有相关的行,并替换了F1为这个重构提交所做的贡献。如果您在提交中将提取与对foo函数内的代码的附加修改结合在一起,那么解决这个问题并不容易。
因此,通过保持小的提交,你可以减少冲突的可能性,但如果你得到了,有补救措施来减轻解决的负担。例如,您可以use KDiff3来解决冲突,只要它们不更改同一行,它通常会自动解决相邻行上的更改。
甚至对于相同的行修改,KDiff 3也是一个成熟的3路合并程序,与不使用适当的3路合并工具相比,它使解决冲突成为一种上级的体验。
在提交1/20中修复冲突似乎是浪费时间
你在担心一个我认为很大程度上是想象出来的问题。在所有的提交中,没有冲突会反复出现(如果有什么东西会反复出现不止一次,那么就像前面提到的那样,有一个rerere(我没有使用它的经验))。我再次强调,较小的提交是避免冲突的最佳工具,保持所有原始提交是一条正确的道路。

相关问题