merge 和 rebase 有什么区别?
阅读官方 Git 手册,它指出 “rebase 在另一个基础分支上重新应用提交”,而 “merge 将两个或多个开发历史连接在一起”。换句话说,merge 和 rebase 之间的主要区别在于,merge 保留发生的历史,rebase 重写它。
让我们用一个并排的例子来说明这些陈述的背景!
如上图所示,merge 操作通过创建一个新的单一合并提交 (C7) 将分支交织在一起,从而导致菱形非线性历史 - 基本上保留了发生的历史。通过将此结果与 rebase 操作的结果进行比较,我们看到没有创建合并提交,而是两个提交 C5 和 C6 只是被倒带并直接重新应用C4 的顶部,保持历史线性。
如果我们进一步检查这两个重新应用的提交,我们可以看到哈希值发生了变化,这表明 rebase 确实重写了历史记录。
值得注意
每当你rebase 一个分支时,新的提交总是会生成,即使内容可能仍然相同!也就是说,如果没有其他指针(分支/标签)引用它们,任何以前的提交最终都会(垃圾回收后)从历史记录中删除。
权力越大责任越大
我们已经看到 rebase 如何重写历史,而 merge 保留它。但这在更广泛的意义上意味着什么?这两种操作会带来哪些可能性和潜在的弊端?
冲突的更改
例如,假设您在尝试整合更改时遇到了一些令人讨厌的冲突。在合并场景中,您只需要直接在 C7 提交中解决冲突一次。另一方面,使用 rebase 时,您可能不得不在每次提交(C5 和 C6)中解决类似的冲突,因为它们被重新应用。
已发布的分支
另一个与 rebase 相关的潜在问题发生在您正在 rebase 的分支已经远程发布,并且其他人已经基于它进行了工作。然后,您的重新定位分支可能会给所有相关方造成严重的混乱和头痛,因为 Git 会告诉您您的分支同时领先和落后。如果发生这种情况,使用 rebase 标志 (git pull --rebase) 拉取远程更改通常可以解决问题。
此外,每当您对已发布的分支进行变基时,无论其他人是否基于其工作,您仍然需要强制推送它以获取远程服务器的更新 — 完全覆盖现有的远程引用.
数据丢失(对您有利)
最后,由于 rebase 会重写历史,而 merge 会保留它,因此在 rebase 时实际上可能会丢失数据。当重新应用新的提交时,旧的提交(最终在垃圾回收后)被删除。实际上,正是这一特性使 rebase 如此强大——它允许您在公开之前整理您的开发历史!
结论
虽然从潜在数据丢失的角度来看,merge 可以安全使用,并且使用起来感觉更直接。以下是一些可以帮助您避免与rebase 相关的最常见问题的提示。
- 不要对已远程发布的分支进行变基...
- ……除非你知道你是唯一一个在做这件事的人(并且感到安全的力量推动)
- 在变基之前,从您要变基的分支的顶端创建一个备份分支,因为它可以让您轻松比较结果(一旦完成)并在必要时跳回变基前的状态。
来源:以上摘录摘自这篇关于该主题的完整帖子:Differences Between Git Merge and Rebase — and Why You Should Care