图解 Git 基本命令 merge 和 rebase

Git 基本命令 merge 和 rebase,你真的了解吗?
前言
Git 中的分支合并是一个常见的使用场景。
- 仓库的 bugfix 分支修复完 bug 之后,要回合到主干分支,这时候两个分支需要合并;
- 远端仓库的分支 A 有其他小伙伴合入了代码,这时候,你需要和远端仓库的分支 A 进行合并;
以上只是列举了分支合并的一些常见场景,关于 merge 和 rebase 命令你足够了解吗?
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 方式:
# 切到目标分支
git checkout master
git merge feature
命令行里显示了 Fast-forward 的提示:

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


no-ff 合并
不分叉的场景是否可以强制采用 --no-ff 方式合并呢?可以!
# master 回到合入前的状态
git reset --hard d2fa1ae
git merge feature --no-ff

这次命令行没有 Fast-forward 的提示了。
看一眼 master 分支图:

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

上面的图展示了我们经常遇到的一个场景,特性分支创建之后,源分支也会有新的提交。这就是形成分叉了。
这时候如果我们进行合并呢?
git merge feautre

可以看到,虽然默认会尝试 fast-forward 的方式进行合并,但是因为分叉了,所以此时会采用 no-ff 的方式进行合并!有新的 commit 生成了!
fast-forward 方式对应的合并参数是
--ff
我们试试这个参数 --ff-only,顾名思义,就是强制只使用 ff 方式进行合并:
# 回到合并前
git reset --hard 3793081
git merge feature --ff-only

经过测试,当分叉时,因为无法使用 ff 方式合并,即使你强制指定使用该方式合并也不行,会提示终止!
附上 Git 官方文档中的解释,方便理解:
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的更多相关文章
- Git Step by Step – (8) Git的merge和rebase
前面一篇文章中提到了"git pull"等价于"git fetch"加上"git merge",然后还提到了pull命令支持rebase模式 ...
- git之merge和rebase的区别
merge合并 # merge操作 第一步: # 先创建一个目录,在主分支提交3个txt文件 [root@luchuangao]# mkdir oldboy [root@luchuangao]# gi ...
- 关于Git的merge和rebase命令解析
git rebase是对提交执行变基的操作.即可以实现将指定范围的提交"嫁接"到另外一个提交智商. 其常用的命令格式有: 用法1:git rebase --onto <new ...
- Git分支merge和rebase的区别
Git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 原理 如下: 假设你现在基于远程分支&quo ...
- Merge和Rebase在Git中的区别
git命令Merge和Rebase的区别 git merge 会生成一个新得合并节点,而rebase不会 比如: D---E test / A---B---C---F master 使用merge合并 ...
- git中的merge与rebase
之前一直对git的merge与rebase很困惑,而且一般也只使用merge而不是使用rebase.今天受高人指点理清了两者的区别. 首先对于两者而言,他们的结果是一样的,差异在于合并的方式(产生的结 ...
- git merge与rebase
参考这篇文章 Git 之 merge 与 rebase 的区别 文章2 另外,使 rebase出现冲突后,先修改冲突,然后git add 某文件(我使用add .经常有问题),然后git reba ...
- git代码合并:Merge、Rebase的选择
代码合并:Merge.Rebase的选择 Zhongyi Tong edited this page on Dec 7, 2015 · 3 revisions Pages 19 Home 2.1 快速 ...
- [git]merge和rebase的区别
前言 我从用git就一直用rebase,但是新的公司需要用merge命令,我不是很明白,所以查了一些资料,总结了下面的内容,如果有什么不妥的地方,还望指正,我一定虚心学习. merge和rebase ...
随机推荐
- [工具推荐]002.SoftOrbits Sketch Drawer使用教程
SoftOrbits Sketch Drawer是一款简单易用的照片素描化软件,内置多种预设方案以及丰富的自定义细节. 只需要一次轻轻的鼠标点击,就可以帮助你迅速的将家人的照片转换为黑白或者彩色的素描 ...
- 容器技术之Docker常用命令说明
前面我们聊了docker的基本概念.架构.镜像.网络.数据卷,回顾请参考https://www.cnblogs.com/qiuhom-1874/category/1766327.html:今天这篇博客 ...
- SpringBoot 2.x 版本以put方式提交表单不生效的问题详解
在使用SpringBoot 2.x版本时,原有springboot 1.x 版本的通过在表单中添加 input框隐藏域指定_method = put 的方式失效. 虽然浏览器传参的确是带上了这个参数, ...
- 使用RTL进行硬件模型编程的局限性
https://mp.weixin.qq.com/s/Nj_d3hwgNX4kWVtKsqMSWg 硬件模型编程,即Hardware Model Programming.在RTL抽象级别 ...
- Chisel3 - util - Mux
https://mp.weixin.qq.com/s/TK1mHqvDpG9fbLJyNxJp-Q Mux相关电路生成器. 参考链接: https://github.com/freechips ...
- Java实现 LeetCode 526 优美的排列(DFS)
526. 优美的排列 假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这 ...
- Java实现 LeetCode 33 搜索旋转排序数组
33. 搜索旋转排序数组 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值, ...
- python—面向对象设计
一:三大编程范式 1.面向过程编程 2.函数式编程 3.面向对象编程 (类:把一类事物的相同的特征和动作整合到一起就是类,类是一个抽象的概念) (对象:就是基于类而创建的一个具体的事物 [具体存在的] ...
- 循序渐进VUE+Element 前端应用开发(9)--- 界面语言国际化的处理
我们开发的系统,一般可以不用考虑语言国际化的问题,大多数系统一般是给本国人使用的,而且直接使用中文开发界面会更加迅速 一些,不过框架最好能够支持国际化的处理,以便在需要的时候,可以花点时间来实现多语言 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...