安卓开发笔记首页投稿(暂停使用,暂停投稿)Git

闲谈 git merge 与 git rebase 的区别

2016-04-27  本文已影响9219人  不在服务区

前言

相信大部分使用 Git 的朋友都会遇见相同的疑问,并且也从网上搜索了不少资料。那么,为什么我还要写这篇文章呢?因为我想尝试从自己的角度解释这个问题,如果能给到大家灵光一闪的感悟,便善莫大焉啦。估计点进来的朋友也对 merge 和 rebase 有了一定了解,所以我也就不浪费篇幅再去详细介绍 merge 和 rebase,让我们直入主题吧。

merge 与 rebase 的区别

merge

现在假设我们有一个主分支 master 及一个开发分支 deve,仓库历史就像这样:

初始仓库历史
现在如果在 master 分支上 git merge deve:Git 会自动根据两个分支的共同祖先即 e381a81 这个 commit 和两个分支的最新提交即 8ab7cff696398a 进行一个三方合并,然后将合并中修改的内容生成一个新的 commit,即下图的 78941cb
merge 合并图

rebase

rebase 是什么情况呢?还是一个初始的仓库历史图:

rebase初始仓库历史
如果是在 master 分支上 git rebase deve:Git 会从两个分支的共同祖先 3311ba0 开始提取 master 分支(当前所在分支)上的修改,即 85841bea016f64e53ec51,再将 master 分支指向 deve 的最新提交(目标分支)即 35b6708 处,然后将刚刚提取的修改依次应用到这个最新提交后面。操作会舍弃 master 分支上提取的 commit,同时不会像 merge 一样生成一个合并修改内容的 commit,相当于把 master 分支(当前所在分支)上的修改在 deve 分支(目标分支)上原样复制了一遍,操作完成后的版本历史就像这样:
rebase 合并图
可以看见 master 分支从 deve 分支最新提交 35b6708 开始依次提交了自己的三个 commit(由于是提取修改后重新依次提交,故 commit 的 hash 码与上面的85841bea016f64e53ec51 不同)

rebase -i

rebase 操作加上 -i 选项可以更直观的看见被提取的 commit 信息。
仍然在 master 分支上 rebase deve 分支,不过这次要加上 -i 选项,即 git rebase -i deve,然后我们可以得到这样一个文本信息框

rebase -i信息

冲突处理策略的不同

merge --no-ffmerge --ff-only 的区别

上面对 merge 的讲述都是基于其默认操作即 --no-ffgit merge xxx = git merge --no-ff xxx)的说明,但是 merge 还有一种常用的选项 --ff-only,那么这两种有什么区别呢?
--no-ff 是 merge 的默认操作,三方合并并提交修改;而 --ff-only 会判断当前分支可否根据目标分支快速合并,就像下面这样

快速合并
此时 deve 分支就可与 master 分支快速合并。
在 deve 分支上 git merge --ff-only master,便得到合并完成后的版本历史图
快速合并完成
可以发现 --ff-only 生成的历史记录和 rebase 十分相似,但是本质上 --ff-only 仍然是合并操作,但 rebase 并没有做合并,仅仅是提取修改到目标分支后面。

总结:选择 merge 还是 rebase?

最后:一些注意点

参考:

上一篇下一篇

猜你喜欢

热点阅读