更聪明的rebase避免多余的工作?

时间:2012-05-15 13:16:48

标签: git git-rebase git-diff

我遇到长期重组的一个问题是必须解决多余的冲突。假设我有一个带有一系列提交的分支,它们一直在修改一个函数,最后的提交完全删除了这个函数。

当我rebase master时,Git天真地依次应用每个提交。这意味着我需要使用master的提示解决每个提交 - 尽管最终这些工作都被浪费了。

处理这种情况的好方法是什么?也许我应该为整个分支生成一个补丁,并将其应用于master?如果是这样,有什么方法可以保留一些历史记录吗?思想,建议等。

4 个答案:

答案 0 :(得分:10)

您希望使用git rerere结合使用rerere-train.sh从历史提交中教授rerere数据库(您可能已在/usr/share/doc/git/contrib/rerere-train.sh处获得)。这允许git自动使用从历史记录中学习的合并冲突解决方案。

警告:你基本上是通过盲目地使用历史字符串替换来修复冲突的合并,让git重写源代码。您应该在rebase之后查看所有冲突的合并。我发现gitk可以正常工作(它只显示冲突解决方案作为合并补丁)。我只有rerere的好经验,你可能没那么幸运。基本上,如果您的历史记录确实包含损坏的合并(即,技术上不正确的合并然后在以下提交中修复),您不希望使用历史记录中的rerere,除非您想要同样破坏合并自动完成。

长话短说,你就跑了

git config --global rerere.enabled 1
bash /usr/share/doc/git/contrib/rerere-train.sh --all

然后是你真正想做的变种,它应该神奇地起作用。

在全球范围内启用rerere后,您将来不再需要了解历史记录。只有在启用rerere之前已经完成冲突解决后才能使用rerere才需要学习功能。

PS。我找到了另一个问题的类似答案:https://stackoverflow.com/a/4155237/334451

答案 1 :(得分:7)

您可以使用git rerere功能。

您必须使用git config --global rerere.enabled 1启用它,之后,您解决的每个冲突都会被存储以供以后使用,并且在相同的上下文中重新应用解析。

您可以使用git rerere diff检查存储的分辨率。

请查看此tutorial以获取更多信息。

答案 2 :(得分:4)

为什么不在初始交互式rebase中将squash冗余补丁放在一起(首先重新排序它们以便它们在一起),以便清除序列中的“修改然后删除”方面。在这个阶段你可以选择提交中的帅哥(例如使用git gui)。这将为您提供更好的序列,以便最终获得最终清洁。

答案 3 :(得分:2)

(这是我的第二个问题答案。在二读时我认为最初的问题可能与我最初的理解有点不同。)

我理解这个问题,因为你有master的开发分支并行。通常这种分支样式称为特征分支,我绝对鼓励使用它们。

应始终尝试保持功能分支清洁。在实践中,您需要一个功能分支,如果您从未犯过任何错误,那么该功能分支将提交您已经完成的功能。对我来说,这意味着承诺了很多,后来git rebase -i来修复错误,当我后来了解这些错误时。

当您的功能分支准备好时,它应该看起来像

  1. 添加API以执行操作X
  2. 修复角落案例Z的现有API Y
  3. 使用X和Y添加功能B(在Z情况下也适用!)
  4. 改进功能B:做神奇的东西E
  5. 而不是

    1. WIP
    2. WIP2
    3. 添加API
    4. 移动API以执行X
    5. 添加功能B
    6. 第二个想法,重命名X
    7. 的参数
    8. 修复功能B
    9. 修复APi for X
    10. 修复角落案例Z
    11. 修复API Y的角落案例Z
    12. 做神奇的东西E
    13. 提交缺少文件
    14. 如果您然后将功能分支重新绑定到最新的master分支,则更改很高,只有提交Fix existing API Y for corner case Z可能会导致冲突。如果该提交是修改现有 API的最小更改,那么修复冲突应该很容易。此外,只有当其他一些提交修改了您的最小更改所触及的行时,才会产生冲突。

      如果你做功能分支和rebase功能分支而不是合并(我的首选样式是rebase,以便快进是可能的,然后做git checkout master && git merge --no-ff feature-branch-x并记录合并提交中的整个事情 - 这允许保持完整的分支历史,并允许GUI工具在需要时轻松浏览功能)在将这些分支重新定位到master之前,您肯定希望keep your feature branches clean。不仅你的rebase会更容易,但从长远来看,历史是可读的。

      所以在上面的例子中,可以rebase -i <old-enough-sha1>,重新提交的顺序为3 + 4 + 6 + 8,10,1 + 2 + 5 + 7 + 9,11 + 12 {{1}壁球。 Git也允许拆分和编辑现有的提交,但通常更容易保持提交非常小,然后再压缩其中一些。请注意,在此示例中,即使原始提交号10在最初的第一次提交之前结束。这是正常的,反映了您的实施并不完美的现实。但是,这不需要存储在版本历史中。

      在您的情况下,听起来您有一个功能分支,其中多个提交添加和删除相同的东西。将这些提交压缩为单个提交(可能最终没有变化,这是可以的)。仅在功能分支看起来干净时才将功能分支重新定位到主分支。绝对要学会使用+或其他一些工具来轻松提交更改而不是文件。每次提交都应该是一个改变,修改一个理智的东西集合。如果添加新功能X,则相同的提交不得修复现有功能Y或添加有关Z的缺少文档。即使对同一文件进行了这些更改也是如此。对我来说,这就是Linus Torvalds在说“files do not matter”时的意思。