图解 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 ...
随机推荐
- Life In Changsha College- 第四次冲刺
第四次冲刺任务 整体功能实现. 用户故事 用户打开“生活在长大”的界面,选择登录 已注册过则输入用户名和密码直接登录 未注册用户则可选择注册功能,注册成功后登录 登录成功则弹出提示框 进行留言 系统结 ...
- CentOS 安装 git2.x.x 版本
方法一 源码方式安装 第一步:卸载旧的git版本. $ yum remove git 第二步:下载git $ wget --no-check-certificate https://www.kerne ...
- 逃离CSDN
2012年2月18日,从CSDN搬家到这里.对于搬家的理由,总觉得该说点什么.我是在2012年1月29日又开始写博客的,在此之前我的CSDN博客闲置了10个月.从1月29日开始,不到1个月的时间建立了 ...
- Blender如何设置中文界面
废话不多说,上图 bingo!!
- Java实现第九届蓝桥杯方格计数
方格计数 题目描述 如图p1.png所示,在二维平面上有无数个1x1的小方格. 我们以某个小方格的一个顶点为圆心画一个半径为1000的圆. 你能计算出这个圆里有多少个完整的小方格吗? 注意:需要提交的 ...
- PAT 挖掘机技术哪家强
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 105 的正整数 N,即参赛人数.随后 N ...
- iOS-PCH File的快速导入方法和使用
PCH的文件的用途: 在实际的项目开发中,如果很多地方都在使用某个类的头文件,很多地方都在使用同一个”宏”的时候:很多地方用到了NSLog()函数, 在app发布的时候,想清除掉时,此时就需 ...
- Servlet中的请求转发
请求转发时,传递到下一个servlet的request和response可能内存地址不同,但是里面包含的内容是相同的 // servlet1 RequestDispatcher dispatcher ...
- AsyncTask源码解读
AsyncTask源码解读 一.基本使用 protected void onPreExecute() protected abstract Result doInBackground(Params.. ...
- 为什么阿里巴巴Java开发手册中不允许魔法值出现在代码中?
在阅读<阿里巴巴Java开发手册>时,发现有一条关于关于常量定义的规约,具体内容如下: 图中的反例是将数据缓存起来,并使用魔法值加链路 id 组成 key,这就可能会出现其他开发人员在复制 ...