闲谈 git merge 与 git rebase 的区别

前言

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

merge 与 rebase 的区别

merge

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

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

rebase

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

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

可以看见 master 分支从 deve 分支最新提交 35b6708 开始依次提交了自己的三个 commit(由于是提取修改后重新依次提交,故 commit 的 hash 码与上面的85841bea016f64e53ec51 不同)

rebase -i

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

  • A 区域内的信息说明了这次 rebase 操作提取了哪些 commit 记录(f9a7673 与 edb2ba2),会连接到目标分支的哪个 commit (9c86a5c)后面。可以根据 B 区域中的命令说明修改 pick 为其他命令,对该次提取出来的 commit 做额外的操作
  • B 区域内说明了本次 rebase 操作可以选用的命令
  • 通过 :wq 保存退出后,就会按照刚刚在 A 区域内设定的命令处理 commit 并 rebase。

冲突处理策略的不同

  • merge 遇见冲突后会直接停止,等待手动解决冲突并重新提交 commit 后,才能再次 merge
  • rebase 遇见冲突后会暂停当前操作,开发者可以选择手动解决冲突,然后 git rebase --continue 继续,或者 --skip 跳过(注意此操作中当前分支的修改会直接覆盖目标分支的冲突部分),亦或者 --abort 直接停止该次 rebase 操作

merge --no-ff 与 merge --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?

  • merge 是一个合并操作,会将两个分支的修改合并在一起,默认操作的情况下会提交合并中修改的内容
  • merge 的提交历史忠实地记录了实际发生过什么,关注点在真实的提交历史上面
  • rebase 并没有进行合并操作,只是提取了当前分支的修改,将其复制在了目标分支的最新提交后面
  • rebase 的提交历史反映了项目过程中发生了什么,关注点在开发过程上面
  • merge 与 rebase 都是非常强大的分支整合命令,没有优劣之分,使用哪一个应由项目和团队的开发需求决定
  • merge 和 rebase 还有很多强大的选项,可以使用 git help <command> 查看

最后:一些注意点

  • 使用 merge 时应考虑是采用 --no-ff 默认操作,生成一个对回顾提交历史并不友好的合并记录,还是采用 --ff-only 方式
  • rebase 操作会丢弃当前分支已提交的 commit,故不要在已经 push 到远程,和其他人正在协作开发的分支上执行 rebase 操作
  • 与远程仓库同步时,使用 pull 命令默认进行了 git fetch + git merge --no-ff 两个操作,可以通过加上 --rebase 命令将 fetch 后的 merge 操作改为 rebase 操作,或者仅仅 ‘git fetch remoteName‘,然后才思考采取哪种整合策略 git merge(or rebase) origin/master
  • 开发与 commit 时注意自己此时在哪个分支上
  • 当有修改未 commit 时,不能进行 rebase 操作,此时可以考虑先用 git stash 命令暂存

参考:

时间: 2024-10-06 01:42:17

闲谈 git merge 与 git rebase 的区别的相关文章

git merge 及 git rebase的区别

Git上合并代码有git merge 及 git rebase 两种方式. 前置知识点 Master分支:首先,代码库应该有一个.且仅有一个主分支.所有提供给用户使用的正式版本,都在这个主分支上发布.这个分支被称为Master分支: Develop分支:主分支只用来分布重大版本,日常开发应该在另一条分支上完成.我们把开发用的分支,叫做Develop分支.这个分支可以用来生成代码的最新隔夜版本(nightly).如果想正式对外发布,就在Master分支上,对Develop分支进行"合并"

git merge vs git rebase

背景 开发过程,可能遇到这种情况 git merge效果 git checkout feature git merge master git rebase效果 git checkout feature git rebase master 参考 https://www.atlassian.com/git/tutorials/merging-vs-rebasing/conceptual-overview 版权声明:本文为博主原创文章,未经博主允许不得转载.

git第七节---git merge和git rebase

# git merge和git rebase 都可以进行分支合并 #git merge 合并后保留记录两个分支的记录 #git rebase合并后会展示成一个分支的记录,另一个分支的提交实际生成了一个副本 冲突解决 git merge在解决冲突后需要手动通过git add ,git commit 再生成一次提交 git rebase 在解决冲突后会自动生成一次提交 git merge 一次性会解决之前提交记录中的所有冲突 git rebase 一次只会解决一次提交上的冲突,如果多次提交都有冲突,

【译文】Git merge 和 Git rebase比较

[译文]Git merge 和 Git rebase比较 原创: 胡江华 胡同学和朋友们的成长日记 2017-03-22 git rebase 这个命令经常被人认为是一种Git巫术,初学者应该避而远之.但如果使用得当的话,它能给你的团队开发省去太多烦恼.在这篇文章中,我们会比较git rebase和类似的git merge命令,找到Git工作流中rebase的所有用法. 概述 你要知道的第一件事是,git rebase 和git merge 做的事其实是一样的.它们都被设计来将一个分支的更改并入

[git] git merge 和 git merge --no-ff

git merge 和 git merge --no-ff 根据这张图片可以看出 git merge –no-ff 可以保存你之前的分支历史.能够更好的查看 merge历史,以及branch 状态. git merge 则不会显示 feature,只保留单条分支记录 一时间没看明白: git merge效果: git merge –no-ff效果 附录: https://segmentfault.com/q/1010000002477106 sourcetree使用教程: http://blog

git各种命令 &amp; git merge和git rebase的区别

git merge 和 rebase的区别: http://blog.csdn.net/jollyjumper/article/details/24743751 对于两个分支而言,rebase和merge没有区别,但是rebase更干净,因为log hisitory是线性的,但commit不一定按日期先后排,而是local commit总在后面,merge之后history变得比较复杂,但是commit按日期排序,stackoverflow上有个图示很好: http://stackoverflo

git merge和git rebase的区别(转)

Description git rebase 和 git merge 一样都是用于从一个分支获取并且合并到当前分支,但是他们采取不同的工作方式,以下面的一个工作场景说明其区别 场景:  如图所示:你在一个feature分支进行新特性的开发,与此同时,master 分支的也有新的提交. 为了将master 上新的提交合并到你的feature分支上,你有两种选择:merging or rebasing merge 执行以下命令: git checkout feature git merge mast

git merge 与 git rebase的区别

前言 其实这个问题困扰我有一段时间,相信也有人和我一样有这个困扰,网上已有很多这种解释了,但是要么就是无图,要么就是解释的很乱,没太看懂,经过自己对git的使用,加上向同事请教,算是理解了这个问题,所以写下来分享一下,我尽量详细说明merge与rebase的区别 假设我们有如下图一所示仓库,该仓库有master和develop两个分支,且develop是在(3.added merge.txt file)commit处从master拉出来的分支.图一 merge 假设现在HEAD在(6.added

git merge 和 git rebase 小结(转)

git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 ----------------------------------- 他们的 原理 如下: 假设你现在基于远程分支"origin",创建一个叫"mywork"的分支. $ git checkout -b mywork origin 假设远程分支"origin"已经有了2个提交,如图 现在我们