Git rebase commit replays vs merge commits:一个具体的例子

Git rebase commit replays vs merge commits: a concrete example

我对变基如何在 git 中工作有疑问,部分原因是每当我向其他开发者询问有关它的问题时,我都会变得模糊、抽象、高水平“架构师说" 这对我来说意义不大。

听起来好像在我的工作分支中的更改上从源分支一个接一个地(如此顺序地)重新设置“重播”提交的基础,是这种情况吗?因此,如果我有一个功能分支,比如说 feature/xyz-123 最初是从 develop 中删除的,然后我从 origin/develop 变基,那么它会重播对 develop 所做的所有提交因为我从它分支出来。此外,它会这样做,一次 develop 提交,直到所有更改都“重播”到我的功能分支中,是吗?

如果我上面说的有什么不正确或误导的地方,请先纠正我!但假设我或多或少是正确的,我看不出这与通过执行 git merge develop 合并来自 develop 的更改有何不同。难道这两种方法都不会导致从 develop 进入 feature/xyz-123 的所有最新更改吗?

我敢肯定情况并非如此,但我只是在这里没有看到森林。如果有人能给出一个具体的例子(可能有一些模拟提交和 git 命令行调用),我也许能够理解 rebase 与合并的工作方式的区别。提前致谢!

" 听起来好像变基“重播”提交,一个接一个(如此顺序地)从源分支到我的工作分支中的更改,是这种情况吗?

是。

" 此外,它会这样做,一次一个开发提交,直到所有更改都已“重播”到我的功能分支中,是吗? "

不,恰恰相反。 如果你在 origin/develop 上 rebase 你的分支,所有 你分支的提交 都将是在 origin/develop 之上重播,而不是相反。

最后,合并和变基方案之间的区别已在各处进行了详细描述,包括在本网站上,但从广义上讲,合并工作流会将合并提交添加到历史记录中。对于最后一部分,先看看 here

涵盖了很多内容,但让我再添加一些内容:

  • “重播”提交是 运行ning git cherry-pick 或做一些等效的事情。 git rebase 的某些版本字面意思是 运行 git cherry-pick,如果您想了解 rebase 的工作原理,那就是要考虑的具体部分。 (如果你想了解所有细节,“复制”提交的另一种主要方法是使用 git format-patchgit am:这会更快,因为它不能正确处理重命名。所以cherry-pick 方法通常更好。它直到最近才成为默认方法,但交互式变基和任何使用交互式机制的变基除外。)

  • 合并提交实际上不能被挑选,所以当使用 git rebase --rebase-merges 时,Git 不能那样做。相反,Git 将 重新执行 合并。也就是说,Git 在 rebase 操作开始时计算出哪些提交是普通的(单亲)提交,可以被挑选出来,哪些是与两个或更多父提交的合并。然后它在交互式变基脚本中——这种特殊类型的变基总是使用交互式机制——布置了交互式变基需要的特殊额外命令,以便再次 运行 git merge。您可以通过将 --interactive 添加到 rebase 命令来查看这些命令。编辑它们时要小心:它们必须 运行 以正确的顺序排列才能正常工作。

  • 如果您有 git rebase 需要“重放”的合并提交,并且您 使用 --rebase-mergesgit rebase 完全 删除 这些合并提交。结果是……往往不好。但是如果你做了一个你没有 mean 做的合并,并且想要做一个 rebase,它实际上 is 好:这去掉了最后的合并。

这个的 TL;DR 版本是:两者都很复杂。使用 git merge 通常会产生一 (1) 个新的 merge commit,它结合了工作。使用 git rebase 个副本,就像通过樱桃挑选一样,many 提交,并放弃旧的(和糟糕的?)提​​交新的和改进的副本。

当使用 git cherry-pick git merge 时,可能会发生合并冲突。 Git 2.33 可能会默认启用 git rerere,因此任何以前针对某些特定合并冲突的解决方案都将被自动拾取并重新使用。目前您必须手动启用它。 rerere 的工作方式有点复杂;值得通读 this blog entry.