我们改名的原因是历史都是线性的。但是,如果我们将提交压缩为一个,那么是否只合并然后忽略任何分支就无关紧要吗?
我正在与一位同事讨论如果历史是线性的,并且如果一个开发人员有7次提交,而7次提交中有1次提交引入了错误,那么我们可以执行二进制搜索,我们可以使用自动二进制搜索准确地找到它是哪个提交(和自动测试)。但是他说,如果某些中间提交实际上还不好,那可能会破坏构建或破坏测试。然后他提到了能够将所有提交压缩为一个并重新设置基准,这样就不会遇到捕获尚未准备好的提交的问题。
[如果我们真的可以使用二进制搜索来查找哪个提交引入了一个新的错误,那很好,我们不必担心历史记录的提交数量是原来的7倍,因为当时间为O(log n)时,这不是问题n增加了7倍-仅意味着再进行3次构建和测试。但是,实际上我们是否使用自动构建和自动测试来进行二进制搜索以发现新的错误?似乎确实很耗时。
如果我们只是合并然后完全忽略任何分支,那与壁球和变基不一样吗?当我们忽略任何分支(只是一条直线)时,与仅将所有提交压缩为一个并重新设置基准相比,具有一个额外的合并提交具有相同的形状。
[您要提出的问题实际上是合并营和重组营之间的长期辩论。在我看来,这里的理想答案是倾向于使用重基础,但要始终确保所推送的每个提交都具有完整的功能(即所有单元测试和集成测试都通过了)。
从发现错误的角度来看,无论使用合并还是变基类型的工作流都没有多大区别。无论哪种情况,自引入错误提交以来,很可能已经进行了许多提交。在任何一种工作流程中,您都可以通过提交一个或多个提交来解决问题,从而修复该错误。正如您已经正确指出的那样,rebase的优点是可以使用git bisect
来深入了解引入该错误的确切提交。在合并工作流的情况下,git bisect
仍会告诉您哪个提交引入了该错误。但是,在这种情况下,您可能会失去很多分辨率。您可能会有一个较大的合并提交,而不是具有较小的更改集的较小的功能提交,而该合并提交是由包含许多提交的功能分支生成的。因此,在合并提交引起问题时,要立即准确地找出what可能会比较困难。
我更喜欢尽可能地使用变基工作流程,因为它可以清晰地记录构建功能所采取的确切步骤。
如果您的工作流程是压缩一次提交然后重新设置基准,那么最好也合并一下,以便保留分辨率。使用“第一个父母”视图(这是您所谓的“忽略任何分支”的正式名称),每个合并提交之间的差异应与压榨/变基历史记录相同。如果您的工作流程在功能分支合并到母版(或开发)中后将其删除,则保留开发人员从其功能分支的首选提交历史记录特别有价值。当然,您不需要额外的提交,但是有时能够遵循开发过程的思路是很好的。
通常,错误更可能是在损坏的代码行而不是commit处发现的,因此,除非自动执行,否则我不会仅出于发现错误的目的而考虑其他提交。 。如果您打算通过签出并构建特定的提交来自动化git bisect(或其他二进制搜索),则从最简单到最难自动化的排名是:最好是不压扁的基线,合并将是第二好的,而压扁/重新基线将是最佳最糟糕的情况(因为每个提交都包含许多更改,而无法解析为单个提交)。请注意,您仍然可以使用merge自动实现单个提交的隔离,除了它更复杂之外,因为您导航第一个父对象,直到找到中断的合并提交,然后向下跟踪第二个父对象,直到找到特定的损坏的提交为止。 >
我个人更喜欢合并,而不是合并,但略有不同。合并的一个缺点(尽管很少见)是在功能分支中可能没有错误,实际上是合并提交引入了该错误,即使合并发生时也没有冲突。为了避免这种情况,我建议我的团队始终首先将其功能分支重新建立到目标上,然后再与--no-ff合并以强制执行合并提交。 (有时称为半线性合并。)
如果您压缩提交,则无论您重新设置基础还是合并都无关紧要。它们将产生相同的树,因为更改将相同。如果您使用功能全面的Git服务器(例如GitHub),则会发现squash工作流称为“ squash and merge”,但行为是相同的。