Git merge时使用--no-ff参数

article/2025/7/10 1:52:59

/1、Git:Git-merge的–ff和–no-ff。

前言
Git merge最容易糊涂的地方就是这个--ff参数和--no-ff 参数,通过本文,把这个整理清楚。

其实官网讲的非常清楚,不过可能因为是英文的,所以大家阅读起来会有一些障碍。(PS:其实还是应该逐步逐步提高自己阅读英文文档的能力,想达到一个更高的高度,是需要客服自己本身很多的弱点的)

实例
假设合并前的分支是这样,这个一个非常常见的场景,如果不明白,可以参考另外一篇文章Git Flow工作流:

这里写图片描述

这是一个很常见的用例,功能开发分支是iss53,在开发新功能,master分支是线上分支,出现了问题,开辟了hotfix分支进行修复,修复完成,进行合并,需要把hotfix合并回master。

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

步骤如下:

切换回master分支。
将hotfix分支合并会master分支。
然后看到了Fast-forward 的字样,这个词组的意思就是快进,播放电影的时候,可以注意一下,快进按钮上面就是这个词组。
那么实际变成了什么样呢?

这里写图片描述

仅仅是master指针指向了这个提交C4。这样是一种比较快的合并方式,轻量级,简单。
这个时候,我们往往会删掉hotfix分支,因为它的历史作用已经结束,这个时候,我们的iss53这个功能又向前开发,进行了一次提交,到了C5,那么变成了这样:

这里写图片描述

然后,我们要把iss53 这个分支合并回master,就变成了这样:

这个时候生成了一个新的commit号,这种提交就不是fast-forward(这个时候也无法生成fast-forward提交,因为要将两个版本的内容进行合并,只有在没有需要合并内容的时候,会有这个fast-forward 方式的提交)。
如果我们对第一次合并,使用了--no-ff参数,那么也会产生这样的结果,生成一个新的提交,实际上等于是对C4 进行一次复制,创建一个新的commit,这就是--no-ff的作用。
 

 

2、在很多介绍GItFlow工作流的文章里面,都会推荐在合并分支的时候加上--no-ff参数, 而我们在合并的时候,有时git也会提示 使用了 fast-forward, 这里我将介绍一下merge的三种状态及 git mergegit merge --no-ff 的区别

Git merge的时候,有几种合并方式可以选择

--ff
When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit. This is the default behavior.--no-ff
Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag.--squash
--no-squash
Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the HEAD, or record $GIT_DIR/MERGE_HEAD (to cause the next git commit command to create a merge commit). This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).With --no-squash perform the merge and commit the result. This option can be used to override --squash.

而我们平常什么都不加的时候,则使用默认的 --ff , 即 fast-forward 方式

看过官方注释后,我们用一张图来简单描画一下相应的行为

 

image.png

 

fast-forward

Git 合并两个分支时,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,叫做“快进”(fast-forward)不过这种情况如果删除分支,则会丢失merge分支信息。

–squash

把一些不必要commit进行压缩,比如说,你的feature在开发的时候写的commit很乱,那么我们合并的时候不希望把这些历史commit带过来,于是使用–squash进行合并,此时文件已经同合并后一样了,但不移动HEAD,不提交。需要进行一次额外的commit来“总结”一下,然后完成最终的合并。

–no-ff

关闭fast-forward模式,在提交的时候,会创建一个merge的commit信息,然后合并的和master分支
merge的不同行为,向后看,其实最终都会将代码合并到master分支,而区别仅仅只是分支上的简洁清晰的问题,然后,向前看,也就是我们使用reset 的时候,就会发现,不同的行为就带来了不同的影响

 

https://github-1253518569.cos.ap-shanghai.myqcloud.com/2018-09-18_201744.png

 

上图是使用 merge --no-ff的时候的效果,此时git reset HEAD^ --hard 的时候,整个分支会回退到 dev2-commit-2

 

dev3-commit-1

 

上图是使用 fast-forward 模式的时候,即 git merge ,这时候 git reset HEAD^ --hard,整个分支会回退到 dev1-commit-3

通常我们把 master 作为主分支,上面存放的都是比较稳定的代码,提交频率也很低,而 develop 是用来开发特性的,上面会存在许多零碎的提交,快进式合并会把 develop 的提交历史混入到 master 中,搅乱 master 的提交历史。所以如果你根本不在意提交历史,也不爱管 master 干不干净,那么 –no-ff 其实没什么用。不过,如果某一次 master 出现了问题,你需要回退到上个版本的时候,比如上例,你就会发现退一个版本到了 commint-3,而不是想要的 commit-2,因为 feature 的历史合并进了 master 里。这也就是很多人都会推荐 –no-ff 的原因了吧

3、

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

下面我们实战一下--no-ff方式的git merge

Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (master)
$ git checkout -b dev
Switched to a new branch 'dev'Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (dev)
$ ls
abc.txt  dd  ddd.txt  READMYFILEAdministrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (dev)
$ vi abc.txtAdministrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (dev)
$ git add abc.txt
warning: LF will be replaced by CRLF in abc.txt.
The file will have its original line endings in your working directory.Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (dev)
$ git commit -m 'add merge'
[dev 4fe2eaf] add merge1 file changed, 1 insertion(+)Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (dev)
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (master)
$ git merge --no-ff -m 'merge with no-ff' dev
Merge made by the 'recursive' strategy.abc.txt | 1 +1 file changed, 1 insertion(+)Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (master)
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.(use "git push" to publish your local commits)
nothing to commit, working tree cleanAdministrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (master)
$ git log --graph --pretty=oneline --abbrev-commit
*   0b655f8 (HEAD -> master) merge with no-ff
|\
| * 4fe2eaf (dev) add merge
|/
*   d2ac9a9 (origin/master, origin/HEAD) merge
|\
| * 62feb86 feature
* | a1d0ee6 master
|/
*   2360738 conflict fixed
|\
| * 22f91d7 READ
* | 4518e6a by master
|/
*   c01f0f2 Merge branch 'master' of github.com:ZhuBaker/learngit
|\
| * 6af3724 abc
| * ed9c88d dddd
| * 0fefcee dd
| *   1c508f7 Merge branch 'master' of github.com:ZhuBaker/learngit
| |\
| | * 78b85de abc
| * 7e13181 abc
:Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (master)
$ git branch -d dev
Deleted branch dev (was 4fe2eaf).Administrator@EZ-20170513RQHH MINGW32 /d/workspace/learngit/learn2 (master)
$ git log --graph --pretty=oneline --abbrev-commit
*   0b655f8 (HEAD -> master) merge with no-ff
|\
| * 4fe2eaf add merge
|/
*   d2ac9a9 (origin/master, origin/HEAD) merge
|\
| * 62feb86 feature
* | a1d0ee6 master
|/
*   2360738 conflict fixed
|\
| * 22f91d7 READ
* | 4518e6a by master
|/
*   c01f0f2 Merge branch 'master' of github.com:ZhuBaker/learngit
|\
| * 6af3724 abc
| * ed9c88d dddd
| * 0fefcee dd
| *   1c508f7 Merge branch 'master' of github.com:ZhuBaker/learngit
| |\
| | * 78b85de abc
| * 7e13181 abc
:

分支策略

在实际开发中,我们应该按照几个基本原则进行分支管理:

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

所以,团队合作的分支看起来就像这样:

git-br-policy

小结

Git分支十分强大,在团队开发中应该充分应用。

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。



 


http://chatgpt.dhexx.cn/article/Bgcyudwm.shtml

相关文章

如何清除弹窗FF新推荐

前言:一个星期日的下午,我打算过肥宅的生活,吃的东西已经就位,当我打开电脑后跳出了这个玩意,瞬间好心情全无。身为程序员,感觉受到了侮辱。 一 Adobe Flash简介 查看任务管理器查看详细信息如下&#xf…

ff新推荐弹窗怎么彻底删除---解决方案

根源:几乎所有的电脑中都会安装Flash Player,而FF新推荐弹窗就是Flash Player的,那么Win7、Win10系统FF新推荐怎么卸载? 方法一:直接删除FF新推荐 1、如果FF新推荐弹出之后,先不要关闭掉,使用键…

彻底关闭弹出广告“FF新推荐”

很多小伙伴们都发现,近一段时间,自己的电脑中时常会弹出一个叫“FF新推荐”的广告弹窗,扰民不说显示的内容也很猥亵。一检查发现居然是Flash中国官方干的,安装了flash播放器后就弹出广告。就像下面这样的: 1. FF新推荐…

Java课程设计

学生考勤管理系统 文章目录 学生考勤管理系统一、 前言1、设计背景2、系统设计的目的及意义3、 调查用户需求 二、 系统简介三、 功能介绍1、服务器启动2、登陆3、学生端4、 老师端 四、 系统调试实现1、老师端2、学生端 五、 总结 一、 前言 1、设计背景 随着社会的发展&…

软件测试学习路线

软件测试学习路线图 随着互联网IT产业的蓬勃发展,软件测试的行业也日趋火热,更多人的转向了软件测试行业,当然更多的问题也亟待解决,比如软件测试自学教程视频内容?软件测试视频教程?软件测试培训入门教程?软件测试培训学习思路?鉴此千锋教育不惜教育成本,全面推出软…

学习Altium Designer软件总结

广西●河池学院 广西高校重点实验室培训基地 系统控制与信息处理重点实验室 本篇博客来自河池学院: 智控无人机小组 写作时间:2020.08.22 学习Altium Designer软件总结 因学习了AD,在此总结一下步骤和我遇到的问题以及的解决方法。 (1…

软件开发专业主要有哪些课程?

软件开发专业主要有哪些课程? 1、WEB分为前端开发和后端开发,前端开发需要学CSS3、JavaScript、Html5,后端开发开发需要学PHP、Python、Java。 2、移动端开发需要学OC或者Swift。 3、嵌入式开发需要学C语言、计算机基础知识等。 软件分为系统…

专业工具软件课程学习心得

专业工具软件课程学习心得 部分资源链接: 1 http://download.csdn.net/detail/zhangrelay/9799032 2 http://download.csdn.net/detail/zhangrelay/9799055 3 http://pan.baidu.com/s/1hs1IRMO 密码: kqiz …… 课程学习需要结合其他理论课程&am…

云原生学习的最佳路径

前言 运维这个课程是一个入行门槛低,精通比较难的岗位。 之所以比较难精通,是因为学的比较杂。更重要的是很多种知识并没有一个很好的连贯性。 比如你学zabbix和学docker,就是在学两个东西。 在或者你学nginx和学mysql,这也是两…

课程设计 英语学习助手

课程设计–英语学习助手 1.具体实现的功能模块 试设计一个英语学习助手,下列各项为对该系统数据库的基本要求。 (1)实现英语单词的录入、修改、删除等基本操作; (2)实现常用英语单词例句的录入、修改、删除…

电子科技大学软件工程大一到大三课程

大三下 实习6个月 大三上 大二下 大二上 大一下 大一上

计算机软件要学哪些课程,计算机软件专业主要学习哪些课程?

当前很多中专、大专类职业院校都开设了计算机软件专业。很多同学在选择该专业时,想知道这个专业有哪些课程,这些课程学习难度如何等问题。下面成都职业学校的老师就给大家解答。 首先看主要课程:中专类学习开设的主要课程有:动画设…

NB-IoT 的低功耗分析,我们是怎么做的

人与人之间的通讯规模已近天花板,物与物(IoT)的则刚刚进入增长快车道。随着可穿戴、车联网、智能手表等新兴市场的开启,工业4.0、智慧城市、智慧农业等理念照进现实,万物互联的时代正加速到来。预计未来全球物联网连接…

NB-IOT实验练习2——STM32基础实验

STM32基础实验 上一节介绍了江苏学蠡信息科技有限公司的无线传感器网络实验平台关于NB-IOT实验所需要的各项硬件以及所需要的软件组成部分,这一章,主要是使用STM32F103单片机的基础实验进行介绍和演示。 1. 使用STM32CubeMX创建工程 STM32的开发目前一…

涂鸦NBIOT OpenCPU开发快速入门(一)

今天我作为涂鸦的固件开发者的身份为大家详细讲解NB模组在涂鸦平台的快速对接。基于涂鸦完善的蜂窝通讯机制,使用涂鸦的OpenCPU SDK,可以实现真正的产品级对接!用户只需要关注业务实现,无需过度关注底层基线逻辑以及物联网通讯流程…

nb-iot_IoT项目:Arduino使用Parse.com的Temboo向Android发送推送通知

nb-iot 这篇文章介绍了如何创建一个IoT项目,该项目使用Arduino通过Temboo和Parse.com将推送消息发送到Android智能手机。 例如,我们将构建一个基于Arduino和Android的警报系统,这是一个有趣的物联网(IoT)示例,该项目的目的是使用连…

NBIOT连接阿里云控制台(MQTT连接阿里云控制台)

首先使用MQTT工具连接阿里云平台进行测试之后再使用NBIOT连接控制台,这里主要讲解MQTT连接阿里云的步骤 1、注册或登录阿里云账号 自行前往阿里云官网注册 2、进入物联网界面 首先点击阿里云旁边1位置的选项进入如下界面,找到物联网IOt里面的物联网平…

NB-IoT 接入 5G 核心网丨边缘计算阅读周

#边缘计算阅读周# 读书的人,有梦可做。 边缘计算社区联合6大出版社邀您一起阅读,一起做追梦人。 在近日结束的ITU-R WP5D#35会议上,3GPP技术正式被接受为ITU IMT-2020 5G技术标准。 此次通过的3GPP技术包含中国提交的3GPP NR NB-IoT RIT&am…

NB-IOT开发实战

一,初识NB-IOT 1,NB-IOT介绍 NB ----Narrow BandIOT —Internet of thingsNB-IOT —窄带物联网 2,物联网发展 广/深覆盖:比GPRS覆盖增强20dB 低功耗:基于AA电池,使用寿命可超过10年 低成本:…

SIM7020X NB-IOT HAT 通过MQTT连接EMQ物联网平台

序言: MQTT是基于二进制消息的发布/订阅编程模式的消息协议;由于规范很简单,非常适合需要低功耗和网络带宽有限的IoT场景,比如:智能家居、智慧城市和医疗医护;深受广大童鞋的青睐和喜爱。下面我们以SIM7020…