图解 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 ...
随机推荐
- 基于 kubeadm 搭建高可用的kubernetes 1.18.2 (k8s)集群 三 集群可用性测试
1. 创建nginx ds # 写入配置 $ cat > nginx-ds.yml <<EOF apiVersion: v1 kind: Service metadata: name ...
- [PHP学习教程 - 系统]004.通过ini_set()来设置系统属性(ini_set Method)
PHP原意:ini_set — 为一个系统配置项设置值 基本信息: string ini_set ( string $varname , string $newvalue). (说明:设置指定配置选项 ...
- Redis 入门到分布式 (六)常见的持久化开发运维问题
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.常见问题目录 fork操作 进程外开销 AOF追加阻塞 单机多实例部署 二. fork 1.Fork ...
- OkHttp,一次无奈的使用
一次使用OKHTTP的心痛历程 最近由于一些不得已的原因,接触到了OKHttp,说起来也挺Dan疼的,之前同事将生产附件上传地址配置成了测试地址,还好数量不多,没有造成太大的影响,况且的是这位同事又离 ...
- Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
输入一个百分制的成绩t后,按下式输出它的等级.等级为:90100为A,8089为B,7079为C,6069为D,0~59为E. 样例输入 98 样例输出 A import java.util.Scan ...
- java实现最大五个数
** 最大5个数** [12,127,85,66,27,34,15,344,156,344,29,47,....] 这是某设备测量到的工程数据. 因工程要求,需要找出最大的5个值. 一般的想法是对它排 ...
- java实现第六届蓝桥杯垒骰子
垒骰子 题目描述 赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体. 经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥! 我们先来规范一下骰 ...
- TZOJ 公交车
描述 公交车在一条笔直的道路(道路宽度忽略,设为X轴)上行驶,按顺序路上有若干个站点(X坐标值),crq的家也在道路旁某个位置h(X坐标值),现在crq想知道哪个站点下车离家最近. 输入 输入数据的第 ...
- C#基础篇——委托
前言 在本章中,主要是借机这个C#基础篇的系列整理过去的学习笔记.归纳总结并更加理解透彻. 在.Net开发中,我们经常会遇到并使用过委托,如果能灵活的掌握并加以使用会使你在编程中游刃有余,然后对于很多 ...
- Kubernetes内部域名解析的那些事儿
前言 在kubernets环境中,服务发现大都是基于内部域名的方式.那么就涉及到内部域名的解析.从1.11版本开始,kubeadm已经使用第三方的CoreDNS替换官方的kubedns作为集群内部域名 ...