git rebase和git merge设计的初衷是解决相同的一件事, 即把一个分支合并到另外一个分支--只是他们两个处理的方式非常不一样.

当你在一个特定的分支开发新功能, 团队的其它成员在master分支工作提交了新的commit. 这个项目的历史就会分叉.

现在假设master中的这个新的commit和你在其它分支中开发的新功能相关, 你想在你的feature分支中包含这个commit, 你有两种选择:merge和rebase.

merge

最简单的办法就是merge master分支到你的feature分支, 使用如下代码:

git checkout feature
git merge master

你还可以把这两句命令压缩成一行:

git merge master feature

这会在feature分支创建一个"merge commit",现在你的分支的结构如下:

merge比较好, 因为他是一个无损坏的操作. 存在的分支不会发生什么改变. 这避免了使用rebase时候的许多陷阱.

当feature分支想要和上游的commit一起工作的时候使用merge你的分支会多出一个"merge commit".

rebase

你可以使用rebase将master的修改合并到feature:

git checkout feature
git rebase master

会把整个feature分支的commit放到mager分支之后, rebase不会创建一个"merge commit", rebase会为你分支的每个commit创建一个新的commit.

使用rebase主要的一个好处是你的项目历史比较干净. 首先, rebase不再有merge commit. 第二, 从上图来看使用rebase项目的历史不会分叉.

交互式rebase

通常用来在merge一个feature分支到master之前来整理历史.

要开始一个交互式的rebase, 只需要传递-i标记给 git rebase 命令:

git checkout feature
git rebase -i master

运行后会打开一个文本编辑器列出所有要move的commit:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

这个列表展现了rebase运行后你的branch是怎么样的. 通过修改pick命令或者对这些行纪录进行重新的排序, 你可以决定哪种分支历史是你想要的. 例如, 如果第二个commit只是修复了第一个commit的一些小问题, 你可以使用fixup命令把这两个commit压缩成一个commit:

pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

当你保存并关闭这个文本编辑器, Git会按照你的结构执行rebase, 运行后项目历史如下:

消除"merge commit"这种不重要的commit, 能让你的feature历史更易懂一些. 这是git merge所不能的.

rebase的黄金法则

一旦你明白了rebase是怎么回事, 剩下最重要的事情就是搞懂什么情况下不要使用rebase. 其中一条黄金法则是永远不在在一个公共的分支中使用rebase.

想象一下如果你rebase master到feature分支:

  

rebase会将master的commit移动到feature分支的前面去. 这个问题只发生在你的本地仓储. 其它的开发这还是在开始的master中工作.因为rebase后移动的commit实际上是新的commit, Git会认为你的master分支历史和其它人的master分支分叉了.

如果想要同步这两个master分支, 只有merge他们了, 结果是将有一个额外的merge commit还有两组包含同样修改的commit.

在运行git rebase之前, 你应该问问自己"其他人能看到这个分支吗, 这个分支对团队其他人可见吗?" 如果对其它开发者可见, 你应该要非常谨慎多想想是否有一个不会破坏结构的方法(例如git revert).

Force push

如果你尝试把rebase后的master push到远程仓储, Git会阻止你的push, 因为和远程仓储的master分支有冲突. 这个时候你可以使用force push来强制push:

git push --force

这会用你的仓储的master完全覆盖远程仓储的master. 因此你这样做的时候要非常小心, 这会给团队的其它成员带来极大的困扰.

工作流演示

local cleanup

周期性的执行交互式的rebase, 可以让你的feature分支的每一个commit更加聚合、更加有意义.

当调用git rebase的时候, new base可以有两个选择: 一个是feature的父分支(例如 master), 另一个是你feature分支中的之前的commit. 后者当你需要fix最近的commits的时候非常管用. 下面的命令会运行一个对最近3个commit的一个交互式rebase.

git checkout feature
git rebase -i HEAD~3

指定HEAD~3做为新的base, 不会移动分支--只是交互的重写最近的3个commit. 注意了上游的修改不会放到你的feature分支来.

如果你想重写整个feature, 可以使用git merge-base命令来查找feature分支最初的base. 下面的命令会返回最初base的commit ID, 可以把他传给git rebase:

git merge-base feature master

  

[译]merge vs rebase的更多相关文章

  1. [git]merge和rebase的区别

    前言 我从用git就一直用rebase,但是新的公司需要用merge命令,我不是很明白,所以查了一些资料,总结了下面的内容,如果有什么不妥的地方,还望指正,我一定虚心学习. merge和rebase ...

  2. git两种合并方法 比较merge和rebase

    18:01 2015/11/18git两种合并方法 比较merge和rebase其实很简单,就是合并后每个commit提交的id记录的顺序而已注意:重要的是如果公司用了grrit,grrit不允许用m ...

  3. git merge 和 rebase 区别

    git pull  超级不推荐使用git pull 有坑,谨慎使用,pull底层是merge git pull 是 git fetch + git merge FETCH_HEAD 的缩写.所以,默认 ...

  4. Merge和Rebase在Git中的区别

    git命令Merge和Rebase的区别 git merge 会生成一个新得合并节点,而rebase不会 比如: D---E test / A---B---C---F master 使用merge合并 ...

  5. git merge,rebase和*(no branch)

    上一篇:http://blog.csdn.net/xiaoputao0903/article/details/23933589,说了git的分支,相关的使用方法没说到可是仅仅要google就能搜出一大 ...

  6. Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase

    上篇博客聊了<git分支管理之rebase 以及 cherry-pick相关操作>本篇博客我们就以Learning Git中的关卡进行展开.下方列举了LearningGit中的 merge ...

  7. git中的merge与rebase

    之前一直对git的merge与rebase很困惑,而且一般也只使用merge而不是使用rebase.今天受高人指点理清了两者的区别. 首先对于两者而言,他们的结果是一样的,差异在于合并的方式(产生的结 ...

  8. git merge 与 rebase

    git merge git rebase merge V.S. rebase 参考材料 写在开始: 对merge和rebase的用法总有疑惑,好像两个都能完成"获取别的branch的comm ...

  9. merge和rebase的区别

    前言 我从用git就一直用rebase,但是新的公司需要用merge命令,我不是很明白,所以查了一些资料,总结了下面的内容,如果有什么不妥的地方,还望指正,我一定虚心学习. merge和rebase ...

随机推荐

  1. WSTMall网站系统最新官方版

    WSTMall V1.0是在thinkphp 的经典版本3.2.2基础上进行优化开发的, TP 3.2.2不是thinkphp的一个最新的版本,却是thinkphp最金典的一个版本,正所谓站在巨人的肩 ...

  2. QT210 android2.3 和android4.0 烧写编译日记

    QT210下载烧录编译android2.3过程 工作环境:ubuntu12.04.5 | QT210开发板光盘 | QT210开发板 android2.3编译环境:gcc version 4.4.7  ...

  3. 基于GPUImage的多滤镜rtmp直播推流

    之前做过开源videocore的推流改进:1)加入了美颜滤镜; 2) 加入了librtmp替换原来过于简单的rtmpclient: 后来听朋友说,在videocore上面进行opengl修改,加入新的 ...

  4. phpqrcode 生成二维码

    这个项目需要根据信息来自动生成二维码,到网上搜了下,发现php有生成二维码的类库phpqrcode,所以打算就用这个来生成二维码 从官网下载类库源码http://sourceforge.net/pro ...

  5. 2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结

    成绩:满分300,我得了200, 1:90//前两个题目都是模拟,没用到什么其他算法,第一题有可能少考虑了一点细节 2:100 3:10//感觉是个DP,但是毫无思路,只打了个普通背包,10分而已. ...

  6. 俄罗斯方块(Win32实现,Codeblocks+GCC编译)

    缘起: 在玩Codeblocks自带的俄罗斯方块时觉得不错,然而有时间限制.所以想自己再写一个. 程序效果: 主要内容: 程序中有一个board数组,其中有要显示的部分,也有不显示的部分,不显示的部分 ...

  7. Android 从网络中获取数据时 产生部分数据乱码的解决

    产生部分数据乱码的解决 标签: android部分中文乱码 2014-04-12 23:24 12366人阅读 评论(10) 收藏 举报 分类: [Android 基础](15) 版权声明:本文为博主 ...

  8. php结合redis实现高并发下的抢购、秒杀功能

    抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题,已经很容易想到用缓存 ...

  9. Log4j简单学习笔记

    log4j结构图: 结构图展现出了log4j的主结构.logger:表示记录器,即数据来源:appender:输出源,即输出方式(如:控制台.文件...)layout:输出布局 Logger机滤器:常 ...

  10. 调用webapi 错误:使用 HTTP 谓词 POST 向虚拟目录发送了一个请求,而默认文档是不支持 GET 或 HEAD 以外的 HTTP 谓词的静态文件。的解决方案

    第一次调用webapi出错如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http:// ...