git:rebase的原理


前提:

  • 在最近的项目中,我碰到这样一个情况:第一版app上线之后,团队紧接着进行第二版本的开发,由于团队成员对git使用不熟悉,所以开发的每一次提交都是往远端master分支上提交。
  • 第一版本打包上线之后,我想让后续的开发中master分支保持代码高可用性,于是在远端建立新的分支second_version用于第二版本的开发,到时候再合并到master分支上,奈何有的团队成员不会提交远程其他分支,导致master被污染(如下图)

由于团队成员对git的熟练程度不同,有的使用可视化工具提交,有的使用命令行(比如我),当使用merge的时候会出现如上图所示的问题,点线图错综复杂,原因是在merge时会将本地的提交与拉取的提交融合成新的提交,也就是如图所示的Merge remote-tracking branch...,并且会将所有的提交显示在点线图上,十分混乱。但是使用rebase的时候,点线图则会很优雅:

点线图是一条直线。网上有很多关于rebase和merge的区别解释,以下分享的是我自己对rebase的观点,希望可以帮助大家理解。

rebase原理

首先大家在开发过程中肯定会经常碰到这样的情况:当你执行git push时出现错误信息:

这是因为跟你当前分支相关联的远端分支上已经有别人提交了新的代码,或者说你想push的commit的基点已经变更(后面会说明什么是基点)。

  • 问题引出:这里涉及到本地分支与远端分支关联的问题,使用git branch -vv查看关联关系:


    本地master默认与origin/master相关联,当你执行git pushgit push origin master时,其完整命令是git push origin master:master,前一个master是你本地的master,后一个master是远端master。所以如果没有特别指定,无论你在本地的哪个分支,git push命令都只会将你本地master分支上的代码进行提交。当你在本地新建其他分支git checkout -b test,默认是不会与远程分支相关联的。所以当你在该分支上进行git push时会有如下问题出现

    根据提示,使用git push --set-upstream origin test可以与远端分支test进行关联,这里的test要换成自己的分支名。

回到正题

rebase,故名思意re-base,重新定义基点,当你的代码push不上去的时候,你可以使用git pull -r或是git pull --rebase拉取并合并远端分支,然后执行git status查看是否出现冲突,以下是冲突情况:

红框字的翻译大致是:以'1f618a1'为基点重新定义分支master。1f618a1可以看作是每一次提交的唯一标识码。

我将以下图来讲述rebase的原理:

不同的字母分别代表不同的提交,图中从左到右分别以时间从小到大进行排列。每个commit都以前一个commit作为基点进行开发,例如D是以C为基点进行开发。当我开发完D后,准备push到远端master时,git会进行检查:远端master的最新节点是否是节点D的基点,即检查远端master的基点是否是节点C,如果是,则可以直接push,如果不是,也就是上图的情况:在你push之前远端master已经被他人提交了E和F节点,这时可以执行git pull -r

git会以F节点作为新的基点,与D节点的代码进行融合,如果此时出现冲突,那么你就会被移到临时解冲突的分支,需要人工解冲突,解完后执行git add -A保存操作,再执行git rebase --continue继续后续操作,你可能会遗漏某一处冲突,这个完全不同担心,git rebase --continue会帮你检查是否解决完成,如果没有完成则不会让你回到正常分支。

下图是冲突解决完且顺利执行git rebase --continue的情况:

可以看到,此时我再执行git push,就可以顺利将D节点提交到远端master上去了:

可以看到,远端master保持了一条直线,让人看起来非常舒服,这就是rebase的好处,而不像文章开头使用merge那样杂乱、让人迷惑。

git:rebase的原理的更多相关文章

  1. 使用git Rebase让历史变得清晰

    当多人协作开发一个分支时,历史记录通常如下方左图所示,比较凌乱.如果希望能像右图那样呈线性提交,就需要学习git rebase的用法. “Merge branch”提交的产生 我们的工作流程是:修改代 ...

  2. 你真的懂git rebase吗?

    前段时间由于某种原因,开始接手开发公司前端Vue搭建的项目 该前端项目采用的是基于git rebase的形式去合并代码,而我之前使用git一直都是采用merge的形式合并分支代码,对于rebase一概 ...

  3. Git应用详解第九讲:Git cherry-pick与Git rebase

    前言 前情提要:Git应用详解第八讲:Git标签.别名与Git gc 这一节主要介绍git cherry-pick与git rebase的原理及使用. 一.Git cherry-pick Git ch ...

  4. 聊下 git rebase -i

    在使用git作为源代码管理工具的时候,开发的时经常会面临一个常见的问题,多个commit 需要合并为一个完整的commit提交. 在一个基本的迭代周期里,你会有很多次commit,有跟配置文件相关的, ...

  5. [git]rebase和merge

    转自:http://blog.csdn.net/wh_19910525/article/details/7554489 Git merge是用来合并两个分支的. git merge b # 将b分支合 ...

  6. git merge 和 git rebase 小结

    Git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 ---------------------- ...

  7. Git merge 与 git rebase的区别

    Git merge的用法: git merge Dev // Dev表示某分支,表示在当前分支合并Dev分支 git merge -m  "Merge from Dev"  Dev ...

  8. git知识总结-2.git基本操作之原理说明

    0.前言 本文主要对git常用命令的工作原理做一个详细的说明,常用命令主要包括: 1.git add git add相关命令很简单,主要实现将工作区修改的内容提交到暂存区,交由git管理. 2. gi ...

  9. git rebase 的使用

    rebase 在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase. 在本节中我们将学习什么是“rebase”,怎样使用“rebase”,并将展示该操作的惊艳之处,以及指 ...

随机推荐

  1. H3C DCC的特点

  2. 如何学习Python的一些总结

    https://mp.weixin.qq.com/s/w0NoDiYfvtTy8N3BVoIVpw 为什么选择Python 经常会有同学问我为什么选择Python.我很喜欢这门语言,因为它的简洁灵活, ...

  3. Math.abs( x )

    Math.abs( x ) 下面是参数的详细信息: x : 一个数字 返回值: 返回一个数字的绝对值 <html> <head> <title>JavaScript ...

  4. jQuery中的siblings()的用法

    siblings  英文翻译    兄; 弟; 姐; 妹;   的意思 siblings()用于查找当前元素的同胞元素,就是拿到当前元素的兄弟节点(不包括自己). 给当前元素设置新的样式,并删除当前元 ...

  5. Python--day46--MySQL视图

    1,创建一个视图(给临时表起一个别名v1),视图也虚拟出来的,并非真正的物理表,不能直接往里面插数据.它的数据是动态的读出来的. create view v1 as select * from use ...

  6. 带你认识“货真价实”的P2P网贷风控

      文/杨帆 说起P2P,多数金融圈内人士已经并不陌生.国内现有近千家的P2P网贷平台,动辄打出高息诱人的收益率宣传口号以及眼花缭乱的安全承诺.但是在这些浮华表面的背后,关于P2P的风控很多人仍然是一 ...

  7. echarts实现多条可拖动节点的折现图

    这篇博文主要是利用echarts实现两条以及多条可拖动节点的曲线,demo脱胎于官方demo,在官方demo的基础上添加了另一条曲线.因为之前写过一篇在vue中使用echarts实现可拖动节点的折线图 ...

  8. Can you find it?——[二分查找]

    Description Give you three sequences of numbers A, B, C, then we give you a number X. Now you need t ...

  9. vue-learning:40 - Vuex - 第一篇:概念和基本使用

    vuex 第一篇 目录 vuex概念 state / mapState getter / mapGetter mutation / mapMutation action / mapAction mod ...

  10. Linux 内核pci添加一个驱动

    一个 PCI 驱动被添加到 PCI 核心, 当它调用 pci_register_driver 函数时. 这个函数 只初始化 struct device_driver 结构, 这个结构包含在 struc ...