Git-fast-forward快转模式

前一篇介绍的Git-如何解决合併冲突,说明了在合併过程中可能遇到的冲突。
成功合併之后也有可能遇到另一个情况,「fast-forward(快转模式)」。

何谓快转模式

这是上一篇成功合併的线图。
http://img2.58codes.com/2024/20112573RrS34ZgA8e.png

把feature分支删除,并且在master分支上,再重建一个feature分支。
http://img2.58codes.com/2024/20112573Yu7zmUWJR0.png

此时,feature分支与master分支,都是同一个版本。
http://img2.58codes.com/2024/20112573n2nFpuAKxV.png

在feature分支:
执行cat,查看a.txt的内容。
将内容改成123。
执行git diff查看修改前后的差异。
http://img2.58codes.com/2024/20112573XFHRegQM1m.png

commit新版本
http://img2.58codes.com/2024/201125734ihqgf09RS.png

feature分支比master分支领先一个版本。
http://img2.58codes.com/2024/20112573jc5vGgfKrn.png

为了让fast-forward(快转模式)更明显,再新增2个档案。

这样一来,feature分支会比master分支领先3个版本。
http://img2.58codes.com/2024/20112573iznsm7EBKW.png

在master分支合併feature分支。
http://img2.58codes.com/2024/201125730mqKQOrEOX.png
这时会发现,一个讯息:Fast-forward
表示这次的合併,採用了fast-forward(快转模式)。
那fast-forward(快转模式)究竟是什么情况?

查看log
http://img2.58codes.com/2024/20112573aEZYOZPIvz.png
目前,master分支跟feature分支位于同一个版本,这是可以预期的情况,毕竟是master分支合併feature分支。

来看看线图。
http://img2.58codes.com/2024/20112573JROtkM13Jz.png
重点来了,跟上一张线图比较后,会发现master分支从(Merge branch 'feature')版本直接跳到跟feature分支同一个版本(add c.txt)。
线图并无分岔,而是一条线直接跳上去(黑色)。
这种线图没有分岔,而直接跳到最新版的情况,就是fast-forward(快转模式)

分析fast-forward

一开始,feature分支与master分支,是同一个版本。
意味着,它们拥有相同的档案与内容。
http://img2.58codes.com/2024/20112573n2nFpuAKxV.png

然后,feature分支commit了3个新版本。
也就是领先master分支3个版本。
http://img2.58codes.com/2024/20112573iznsm7EBKW.png

当master分支要合併feature分支时。
它们之间的差异,就只是feature分支比master分支多3个commit而已,其他都是一模一样。
换句话说,master分支有的feature分支都有。
毕竟它们都是从同一个commit分出去的。

master分支合併feature分支,就等同于合併自己以后的版本。
此时,git就会启用fast-forward,master分支一口气跳了3个版本,
到feature分支最新的commit(add c.txt)。
http://img2.58codes.com/2024/20112573JROtkM13Jz.png

关闭fast-forward

表面上看来,fast-forward合併,并没有任何问题,结果也都成功合併。
但请仔细思考,分支的意义是什么?

在软体开发过程中,会有一条主要分支,其他分支,不管它的任务是什么,最后,都会併入主要分支。
master分支是主要分支,而feature分支是开发中的分支,master分支直接跳到feature分支的最新commit,是有点奇怪。
这边要强调,以git的观点,fast-forward没有不好,我们是以软体开发的观点来讨论这个问题。

解决方式就是将fast-forward合併关闭,让master分支与feature分支的合併,看起来就像是开发中的分支(feature)併入主要分支(master)。

执行git reset --hard ORIG_HEAD,回复合併之前的版本。
http://img2.58codes.com/2024/20112573jQnLxgweF6.png

master分支回到原本的版本。
http://img2.58codes.com/2024/20112573QJAZ7Ak4tJ.png

再次合併,这次关闭fast-forward。
指令 --no-ff,关闭fast-forward。
执行git merge feature --no-ff。
http://img2.58codes.com/2024/20112573PBepUDJe2n.png
这次合併讯息,没有Fast-forward字样。

确实执行分支合併的动作。
http://img2.58codes.com/2024/20112573hqoh60RCoC.png
由线图可以看出,master分支的确合併feature分支,并做了一次commit(Merge branch 'feature')。
合併之后,feature分支可以再继续开发,再继续併入master分支。

feature分支再新增档案。
http://img2.58codes.com/2024/20112573aAbyCckA08.png

再次併入master分支。
http://img2.58codes.com/2024/20112573AJwETCLlzd.png

这样的线图非常一目了然。

fast-forward的缺点

一般来说,我们不会在主要分支,执行开发、修复、测试这些操作,一定都是确认稳定后,再併入主要分支。
从线图上可以看出哪些分支做了哪些commit,再合併入主要分支。

master分支的黑正方,表示合併后的commit,黑圆点,表示自身的commit,
红圆点表示feature分支的commit,这样不是很清楚吗。
http://img2.58codes.com/2024/20112573HiG4q6ZB8H.png

但如果透过fast-forward合併的话,并不会产生合併的commit,且全部的commit都挤在同一条线上,包括master分支,如此一来,我们就很难判断分支commit的情况。
http://img2.58codes.com/2024/20112573JROtkM13Jz.png

那到底fast-forward适合用在什么情况呢?

适合fast-forward的情况

我们先在GitHub,新建一个repository,并上传本地专案。
详细步骤可以参考Git-上传档案至远端储存库

上传成功后可以发现,多了一个origin/master分支,代表远端储存库的master分支,
目前跟本地端的master分支指向同一个版本。
http://img2.58codes.com/2024/20112573uhomPYPa8K.png

查看前5笔的log
http://img2.58codes.com/2024/20112573fKJb1jQzyh.png

master分支(本地)与origin/master分支(远端),虽然是不同分支,但它们意义上是相同的,都是master。
所以它们应该要同步才对。

我们来模拟一个多人分工,大家都在origin/master分支开发的情境。
http://img2.58codes.com/2024/20112573M4VZmBBVDG.png

将专案clone下来,跟原本的範例不同位置。
模拟同事A的开发。
详细步骤可参考Git-git clone 的各种方式
http://img2.58codes.com/2024/2011257390mANCS3Y3.png

假设同事A修改b.txt后,push至远端储存库。
http://img2.58codes.com/2024/20112573JVRhpFJAAB.png

这时,远端的origin/master分支有16个commit。
http://img2.58codes.com/2024/20112573tYjuRGUMW6.png

而本地端的master分支有15个commit。
http://img2.58codes.com/2024/20112573DucoNa5pGx.png
所以远端的origin/master分支领先本地端的master分支一个版本。

必须得将远端的origin/master分支下载回来,才能更新版本状态。

执行git pull,可以下载更新。
但实际上git pull是由两个命令所组成的:git pull = git fetch + git merge。
也就是说,它会执行两个动作。
将变更的部分先下载回来(git fetch),再执行合併(git merge)。

执行git fetch
http://img2.58codes.com/2024/20112573wVeRrN0lq1.png

查看线图。
http://img2.58codes.com/2024/20112573VptbOdMmvf.png
origin/master分支领先master分支一个版本,这是由同事A所push上去的。

既然已经有新版本了,那就得将master分支合併origin/master分支,我们跟同事A的专案才能同步。

重点注意,这时要採用哪种合併呢?
刚刚我们将fast-forward关闭,是因为master分支与feature分支,意义上是属于不同的分支,才需要让线图分岔。
但目前的情况是,master分支与origin/master分支,意义上都是相同的分支,既然如此,那直接让master分支一直线上去,是比较合乎逻辑的。线图分岔,反而会觉得奇怪。

採用fast-forward合併。
http://img2.58codes.com/2024/20112573gxkc3wvNRe.png

让master分支直接跳到origin/master分支的版本。
http://img2.58codes.com/2024/20112573rZqvmH1Z1b.png

结论

使用fast-forward的情况:合併的分支,代表相同的意义。
关闭fast-forward的情况:合併的分支,代表不同的意义。

本文为观看网路教学的学习笔记。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章