Git 基本命令 merge 和 rebase,你真的了解吗?

前言

Git 中的分支合并是一个常见的使用场景。

  • 仓库的 bugfix 分支修复完 bug 之后,要回合到主干分支,这时候两个分支需要合并;
  • 远端仓库的分支 A 有其他小伙伴合入了代码,这时候,你需要和远端仓库的分支 A 进行合并;

以上只是列举了分支合并的一些常见场景,关于 mergerebase 命令你足够了解吗?

HEAD 的理解

在介绍本文的主要内容之前,我们先理解一下 HEAD

HEAD 指向当前所在的分支,类似一个活动的指针,表示一个「引用」。例如当前在 develop 分支,HEAD 内容就是 ref: refs/heads/develop

HEAD 既可以指向「当前分支」的最新 commit,也可以指向历史中的某一次 commit (「分离头指针」的情况)。归根结底,HEAD 指向的就是某个提交点。

当我们做分支切换时,HEAD 会跟着切换到对应分支。

fast-forward 与 --no-ff 的区别

假如有一个场景:有两个分支,master 分支和 feature 分支。现在,feautre 分支需要合并回 master 分支。

fast-forward 合并方式是条件允许的情况,通过将 master 分支的 HEAD 位置移动到 feature 分支的最新提交点上,这样就实现了快速合并。这种情况,是不会新生成 commit 的。

--no-ff 的方式进行合并,master 分支就会新生成一次提交记录。

如果条件满足时,merge 默认采用的 fast-forward 方式进行合并,除非你显示的加上 --no-ff 选项;而条件不满足时,merge 也是无法使用 fast-forward 合并成功的!

merge 操作

上面用图解的方式介绍了 fast-forward--no-ff 的区别。下面,结合实际的代码仓进行合并操作,举几个栗子理解一下。

git merge 操作是区分上下文的。当前分支始终是目标分支,其他一个或多个分支始终合并到当前分支。这个注意点记住了,方便记忆!所以,当需要将某个分支合并到目标分支时,需要先切到目标分支上。

fast-forward 合并

刚刚一直在强调条件允许的时候,fast-forward 才能合并成功。条件指的是什么呢?

其实指的是源分支和目标分支之间没有分叉(单词 diverge),这种情况才可以进行快速合并。如果是下图中的场景,无法通过 HEAD 的快速移动实现分支的合并!

下面进行一个不分叉的场景的示例:

现在需要将 feature 分支合入到 master 分支,默认使用 fast-forward 方式:

  1. # 切到目标分支
  2. git checkout master
  3. git merge feature

命令行里显示了 Fast-forward 的提示:

看一眼 master 分支合入的前后对比(注意 HEAD 的位置):

no-ff 合并

不分叉的场景是否可以强制采用 --no-ff 方式合并呢?可以!

  1. # master 回到合入前的状态
  2. git reset --hard d2fa1ae
  3. git merge feature --no-ff

这次命令行没有 Fast-forward 的提示了。

看一眼 master 分支图:

这个图和上面讲解 no-ff 命令时的示意图一致,果然会有新 commit 生成。

分叉场景的合并

上面的图展示了我们经常遇到的一个场景,特性分支创建之后,源分支也会有新的提交。这就是形成分叉了。

这时候如果我们进行合并呢?

  1. git merge feautre

可以看到,虽然默认会尝试 fast-forward 的方式进行合并,但是因为分叉了,所以此时会采用 no-ff 的方式进行合并!有新的 commit 生成了!

fast-forward 方式对应的合并参数是 --ff

我们试试这个参数 --ff-only,顾名思义,就是强制只使用 ff 方式进行合并:

  1. # 回到合并前
  2. git reset --hard 3793081
  3. git merge feature --ff-only

经过测试,当分叉时,因为无法使用 ff 方式合并,即使你强制指定使用该方式合并也不行,会提示终止!

附上 Git 官方文档中的解释,方便理解:

  1. With --ff, when possible resolve the merge as a fast-forward (only update the branch pointer to match the merged branch; do not create a merge commit). When not possible (when the merged-in history is not a descendant of the current history), create a merge commit.

rebase 操作

rebase 命令是一个经常听到,但是大多数人掌握又不太好的一个命令。rebase 合并往往又被称为 「变基」,我称为 「基化」

图解 Git 基本命令 merge 和 rebase的更多相关文章

  1. Git Step by Step – (8) Git的merge和rebase

    前面一篇文章中提到了"git pull"等价于"git fetch"加上"git merge",然后还提到了pull命令支持rebase模式 ...

  2. git之merge和rebase的区别

    merge合并 # merge操作 第一步: # 先创建一个目录,在主分支提交3个txt文件 [root@luchuangao]# mkdir oldboy [root@luchuangao]# gi ...

  3. 关于Git的merge和rebase命令解析

    git rebase是对提交执行变基的操作.即可以实现将指定范围的提交"嫁接"到另外一个提交智商. 其常用的命令格式有: 用法1:git rebase --onto <new ...

  4. Git分支merge和rebase的区别

    Git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 原理 如下: 假设你现在基于远程分支&quo ...

  5. Merge和Rebase在Git中的区别

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

  6. git中的merge与rebase

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

  7. git merge与rebase

    参考这篇文章 Git 之 merge 与 rebase 的区别  文章2 另外,使 rebase出现冲突后,先修改冲突,然后git add 某文件(我使用add  .经常有问题),然后git reba ...

  8. git代码合并:Merge、Rebase的选择

    代码合并:Merge.Rebase的选择 Zhongyi Tong edited this page on Dec 7, 2015 · 3 revisions Pages 19 Home 2.1 快速 ...

  9. [git]merge和rebase的区别

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

随机推荐

  1. Android调试非常有用的命令集1_adb&aapt&git&repo&scp&while

    Linux部分场景非常有用的命令集_1_持续更新 这里面也包含了对于开发调试有用的命令,也可以看看. 这里不做详细说明或截图,仅作为记录和简单说明.注:可能只针对某一命令部分功能,不包含整个功能,若要 ...

  2. [JavaWeb基础] 015.Struts2 表单验证框架

    在web开发的过程中,我们经常要用到一些填写表单的操作,我们一般都要在提交表单信息的时候对表单的内容进行验证,struts2给我们提供了简单的实现接口,让我们可以很容易的对表单进行验证.下面讲解下最传 ...

  3. equals()方法练习

    1: package com.aff.equals; public class TestOrder { public static void main(String[] args) { Order o ...

  4. Rocket - tilelink - CrossingHelper

    https://mp.weixin.qq.com/s/y432EkLcBvVn2u_U3tPWeA   简单介绍CrossingHelper的实现.   ​​   1. 基本介绍   为节点生成一个跨 ...

  5. Java实现洛谷 P1873 砍树(StreamTokenizer+IO+二分)

    P1873 砍树 输入输出样例 输入 5 20 4 42 40 26 46 输出 36 PS: get新知识,以前只知道STringTokenizer并没有了解过StreamTokenizer,这次才 ...

  6. Java实现 蓝桥杯VIP 算法训练 连续正整数的和

    问题描述 78这个数可以表示为连续正整数的和,1+2+3-+12,18+19+20+21,25+26+27. 输入一个正整数 n(<=10000) 输出 m 行(n有m种表示法),每行是两个正整 ...

  7. 解Bug之路-记一次存储故障的排查过程

    解Bug之路-记一次存储故障的排查过程 高可用真是一丝细节都不得马虎.平时跑的好好的系统,在相应硬件出现故障时就会引发出潜在的Bug.偏偏这些故障在应用层的表现稀奇古怪,很难让人联想到是硬件出了问题, ...

  8. 【JAVA习题三十】求0—7所能组成的奇数个数

    package erase; public class 求0到7所能组成的奇数个数 { public static void main(String[] args) { /* * 求0—7所能组成的奇 ...

  9. mysql基础-数据库表简单查询-记录(五)

    0x01 MySQL的查询操作 单表查询:简单查询                 多表查询:连续查询                联合查询 选择和投影 投影:挑选要符合的字段     select ...

  10. Grafana邮箱告警

    1.grafana-server 配置 smtp 服务器 vim /etc/grafana/grafana.ini #修改一下内容 ################################## ...