git merge
和有什么区别git rebase
?
7 回答
假设最初有 3 个提交,A
, B
, C
:
然后开发人员 Dan 创建了 commit D
,开发人员 Ed 创建了 commit E
:
显然,这种冲突应该以某种方式解决。为此,有两种方法:
合并:
两者都提交D
和E
仍然在这里,但是我们创建了合并提交M
,它继承了D
和的更改E
。然而,这会产生钻石形状,许多人对此感到非常困惑。
重新定位:
我们创建 commit R
,其实际文件内容与M
上面的合并提交相同。但是,我们摆脱了 commit E
,就像它从未存在过一样(用点表示 - 消失线)。由于这种删除,E
应该是开发人员 Ed 本地的,并且不应该被推送到任何其他存储库。rebase 的优点是避免了菱形,并且历史保持良好的直线 - 大多数开发人员都喜欢这一点!
就我个人而言,我不觉得标准的图表技术很有帮助——箭头似乎总是指向错误的方向。(它们通常指向每个提交的“父”,最终会在时间上倒退,这很奇怪)。
用文字来解释:
- 当你将你的分支rebase到他们的分支上时,你告诉 Git 让它看起来好像你干净地检查了他们的分支,然后从那里开始做所有的工作。这样就形成了一个干净的、概念上简单的更改包,可供某人查看。当他们的分支上有新的更改时,您可以再次重复此过程,并且您将始终在其分支的“尖端”上得到一组干净的更改。
- 当您将他们的分支合并到您的分支中时,此时您将两个分支历史联系在一起。如果您稍后再进行更多更改,您将开始创建一个交错的历史线索:他们的一些更改,我的一些更改,他们的一些更改。有些人觉得这很混乱或不受欢迎。
由于我不明白的原因,Git 的 GUI 工具从未付出太多努力来更清晰地呈现合并历史,抽象出单个合并。所以如果你想要一个“干净的历史”,你需要使用 rebase。
我似乎记得曾经阅读过只使用 rebase 的程序员和其他从不使用 rebase 的程序员的博客文章。
例子
我将尝试用一个简单的例子来解释这一点。假设您项目中的其他人正在处理用户界面,而您正在编写文档。如果没有变基,你的历史可能看起来像:
Write tutorial
Merge remote-tracking branch 'origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md
也就是说,在文档提交中间进行合并和 UI 提交。
如果您将代码重新定位到 master 而不是合并它,它将如下所示:
Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger
您的所有提交都在顶部(最新),然后是master
分支的其余部分。
(免责声明:我是另一个答案中提到的“我讨厌 Git 的 10 件事”帖子的作者)
虽然接受和最受好评的答案很好,但我还发现尝试仅用文字解释差异很有用:
合并
- “好的,我们的存储库有两种不同的开发状态。让我们将它们合并在一起。两个父母,一个孩子。”</li>
变基
- “将主分支(无论其名称)的更改提供给我的功能分支。假装我的功能工作是在以后开始的,实际上是在主分支的当前状态下开始的。”</li>
- “重写我的更改历史以反映这一点。” (需要强制推送它们,因为通常版本控制就是不篡改给定的历史记录)
- “很可能——如果我所做的更改与我的工作无关——历史实际上不会有太大变化,如果我逐个查看我的提交差异(你可能还会想到‘补丁’)。”</li>
总结:如果可能,rebase 几乎总是更好。使重新集成到主分支更容易。
因为?➝ 您的功能工作可以呈现为一个相对于主分支的大“补丁文件”(又名 diff),而不必“解释”多个父级:至少两个,来自一个合并,但可能更多,如果有进行了几次合并。与合并不同,多个变基不会累加。(另一个大优点)
Git rebase 更接近于合并。变基的区别是:
- 本地提交会暂时从分支中删除。
- 运行 git pull
- 再次插入所有本地提交。
这意味着在所有远程提交之后,您的所有本地提交都将移到最后。如果你有合并冲突,你也必须解决它。
我发现一篇关于 git rebase vs merge的非常有趣的文章,想在这里分享
- 如果你想看到和它发生的完全一样的历史,你应该使用合并。Merge 保留历史,而 rebase 重写它。
- 合并为你的历史添加了一个新的提交
- 变基更好地简化复杂的历史,您可以通过交互式变基来更改提交历史。