git merge 与 git rebase
- git merge
- git rebase
- merge V.S. rebase
- 参考材料
写在开始:
对merge和rebase的用法总有疑惑,好像两个都能完成“获取别的branch的commits到我的branch上”,那二者的区别又是什么。通过一些文章和实验,整理如下,参考资料附后。
1.git merge
来看两种场景中merge的不同方式。
- 场景一:切出特性分支后,develop分支上没有新的提交。

fast-forward,若无分歧,会直接移动文件指针。看不出特性分支的起始点。
no-fast-forward(--no-ff),保留提交链的完整性。
squash,压缩不必要的commit;无法看出feature分支合到develop;feature,develop保持相对独立。
- 场景二:切出特性分支后,develop分支上提交了C6,C7。

develop分支上提交了C6,C7,无法fast forward。
three way merge,
- 找到develop分支的最新节点C7;
- 找到feature分支的最新节点C5;
- 找到develop分支和feature分支的共同祖先节点C3;
- 对C3,C5,C7进行三方合并,生成最新的C8。
2.git rebase
变基/衍合,从旧的base变基到新的base,在新base的基础上重现另一个分支的修改过程,版本树像两个链条串在一起变成一个链条,以达到线性的效果。
rebase,对指定的base本身并没有什么影响;只是重写base之后的commit历史。

来看几个场景:
- 在继续开发的过程中和主分支develop同步
从develop上拉出分支做一些开发工作,在这个过程中develop分支可能继续往前走了,那我们需要经常和develop保持下同步(可能是别人提交了公用的模块,或者修复了对大家都有影响的bug)。之前我会通过pull操作来达到这一目的,但pull往往内置了merge(pull的效果看起来就像fetch+merge,想想提到过的“merge应该反映业务层面的合并,而非技术行为”,并且此时merge会产生一些杂乱的历史记录)。
这就相当于我们本地的开发工作(一系列的commits)是在旧的base上展开的,应该使用rebase操作,将本地的开发工作变基到develop的最新节点上。
git pull --rebase

- 重新拾起搁置的工作
很久之前可能启动一个并行工作(开发不着急上线的新特性或者优化一些功能),但一直没有时间处理所以就搁置了,现在又有时间重新拾起,然后就发现当时基于的base实在是太太太老了。现在肯定是希望基于最新的base展开工作,这样就可以从已解决的bugfix或已完成的新特性中中受益。
- 在push之前整理我的本地历史
git rebase -i <myBaseCommit>
这是一个使用更频繁的场景:并不是为了变基,而是清理本地的commit。很多情况我们都需要commit:
- 可能需要多个连续的commit才能完成一次bugfix;
- 切换分支需要保存本地修改(当然按理说这个时候应该使用stash或者idea提供的shelve了);
- 某些历史commit写错了msg(最近一次commit的msg可以通过 commit --amend 修改);
通过-i(--interactive,交互式的),我们可以干预rebase将要执行的脚本化过程,从而达到清理本地commit历史的目的。
熟练使用rebase,可以轻松的进行commit,只需要在最终push之前做一次清理,不必担心影响到公共仓库。
git fetch origin develop git rebase origin/develop ... do sth ... git push
- rebase的场景和用法还有待探索,慢慢更新了。
记住这个:
只能rebase私有分支,一旦发布到公共仓库,不要再rebase了。
3.merge V.S. rebase
什么时候用merge;基于上述不同的merge行为(fast-forward,--no-ff,squash),什么场景下用哪种merge:
merge执行一个合并,这个合并应该反应业务层面的合并,而非技术行为。我们希望在当前分支上往前走,这样它就包含了其他分支的工作。
所以问题的关键是:这个“其他分支”是什么样的分支?这个“其他分支”需要在历史图谱中展示么?
- 本地的、临时的分支,使用它仅仅是为了使master保持clean。
1.若拉出本地分支后,master往前走了,此时在本地分支:
git rebase -i master
将本地分支变基到最新的master节点(重新梳理本地历史提交信息比如合并成一个commit),好似本地分支就是在最新的master节点上做的开发工作,以保证合并到master后呈现线性增长。
2.在master上:
git merge (fast-forward)
最终以一个或几个commit展现在master上。
- 知名分支,团队明确定义的,可能是用来追踪bug/feature。
永远不要用rebase,而是用
git merge --no-ff
以保留清晰完整的历史图谱。
4.参考材料
GETTING SOLID AT GIT REBASE VS. MERGE
Git team workflows: merge or rebase?
A successful Git branching model
git merge 与 git rebase的更多相关文章
- Git merge 与 git rebase的区别
Git merge的用法: git merge Dev // Dev表示某分支,表示在当前分支合并Dev分支 git merge -m "Merge from Dev" Dev ...
- git merge与 git rebase区别及实例
接Git分支创建与合并,在分支合并时,有两种方式:git merge 和git rebase. git merge:将两个分支,合并提交为一个新提交,并且新提交有2个parent. git rebas ...
- git第七节---git merge和git rebase
# git merge和git rebase 都可以进行分支合并 #git merge 合并后保留记录两个分支的记录 #git rebase合并后会展示成一个分支的记录,另一个分支的提交实际生成了一个 ...
- git merge和git rebase的区别
git merge是用来合并两个分支的.# 将b分支合并到当前分支git merge b git cherry-pick可以选择某一个分支中的一个或几个commit(s)来进行操作.例如,假设我 们有 ...
- git merge和git rebase的区别和异同
1.git merge和git rebase作用差不多,都是将远程代码和本地代码合并 2.git merge和git rebase作用差不多,都是将远程代码和本地代码合并 3.git merge ...
- git merge 及 git rebase的区别
Git上合并代码有git merge 及 git rebase 两种方式. 前置知识点 Master分支:首先,代码库应该有一个.且仅有一个主分支.所有提供给用户使用的正式版本,都在这个主分支上发布. ...
- 【译文】Git merge 和 Git rebase比较
[译文]Git merge 和 Git rebase比较 原创: 胡江华 胡同学和朋友们的成长日记 2017-03-22 git rebase 这个命令经常被人认为是一种Git巫术,初学者应该避而远之 ...
- git merge 与 git rebase的区别?
一,git merge 与 git rebase的区别 1,git merge 例如: master分支合并dev分支,git将两个分支dev和master上的所有commit , 按照提交时间的先后 ...
- git pull、git fetch、git merge、git rebase的区别
一.git pull与git fetch区别 1.两者的区别 两者都是更新远程仓库代码到本地. git fetch相当于是从远程获取最新版本到本地,不会自动merge. 只是将远程仓库最新 ...
- git merge 和 git rebase 小结
Git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 ---------------------- ...
随机推荐
- 下载android4.4.2源码全过程(附已下载的源码)
今天在下载andriod源码,特来与大家分享一下我的经验.当然,网上教下载源码的教程较多,本文主要针对在GFW下下载源码出现的各种问题的解决方法. 1.首先安装下载客户端git , curl. 命令如 ...
- [GitHub]第四讲:合并分支
本地两个分支合并 先从最简单的一种情况着手.现在项目只有一个 master 分支,我来新建一个 idea 分支,实现自己的想法,commit 一下.那现在仓库内的情况就是这样的 这个是前面已经见过的情 ...
- Unity 简易的UI背景昼夜轮替效果
在UI背景上实现一个简易的有光影照射的昼夜轮替效果,往往比一个死板的UI背景看起来更加形象生动,比较传统的方式是多图轮流替换的序列帧动画,不过要达到整个UI背景大图的所有地方都产生光影效果,那么务必每 ...
- java同步synchronized
java同步synchronized volatile仅仅用来保证该变量对所有线程的可见性,但不保证原子性. 看下面的这段代码: /** * * @author InJavaWeTrust * */ ...
- 存储那些事儿(五):BTRFS文件系统之Btree结构详解
Btree数据结构可以说是BTRFS文件系统的基础.它提供了一个通用的方式去存储不同的数据类型.它仅仅存储3个数据类型:key, item和block header. btrfs_header的定义如 ...
- Linux之使用网络
Linux有好多命令可以让你方便的使用网络,常见的有ssh,rsync,wget,curl等等,但是telnet等方式并不适用于网络交互的使用,因为它会暴露你的用户名密码等.所以一般使用安全的命令来进 ...
- sql 如何应对子查询返回数据有多条 我就是要返回数据有多条
SELECT * FROM SUSE_DEV.PROJECT_LISTING INNER JOIN SUSE_DEV.PROJECT_AUCTION ON SUSE_DEV.PROJECT_LISTI ...
- ReactJs和React Native的那些事
介绍 1,React Js的目的 是为了使前端的V层更具组件化,能更好的复用,它能够使用简单的html标签创建更多的自定义组件标签,内部绑定事件,同时可以让你从操作dom中解脱出来,只需要操作数据就会 ...
- 【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析
. Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...
- 使用Android Support Design 控件TabLayout 方便快捷实现选项卡功能
1.概述 TabLayout是在2015年的google大会上,google发布了新的Android Support Design库的新组件之一,以此来全面支持Material Design 设计风格 ...