Day21|【Git】合并分支 git merge 指令 、快转模式Fast Forward 、救回被砍掉的未合并分支方法

分支合并的方法有两种:mergerebase

本篇先讲解使用 merge 来合并分支的观念。


合并分支基本概念

情境|想要使用 A 分支来合并 B 分支

步骤|

  1. 先切换到 A 分支(显示当前位於 A 分支上)

  2. 使用 git merge 指令

    $ git merge B分支 # 合并 B 分支
    

🛠 实际操作

  1. 建立新的分支,并 Commit 两次。

    $ git branch one # 新增一个 one 分支
    $ git checkout one # 切换到 one 分支
    
    // 重复动作提交第二次
    $ touch hello.html # 新增一个档案
    $ git add . # 加至暂存区
    $ git commit -m"讯息记录" # 提交到储存库
    
    

    https://ithelp.ithome.com.tw/upload/images/20211005/20141010SqEtFnZ6RR.png

  2. 任务:想要使用 master 分支来合并 one 分支

    1. 因目前在 one 分支上,因此先切回到 master 分支上。

      https://ithelp.ithome.com.tw/upload/images/20211005/20141010NixajBrzEk.png

      $ git checkout master # 切换到 master 分支
      

      https://ithelp.ithome.com.tw/upload/images/20211005/20141010oka2t65re7.png

    2. 执行合并分支 git merge 指令( master 合并 one 分支)

      $ git merge one # 合并 one 分支
      

      https://ithelp.ithome.com.tw/upload/images/20211005/20141010nYqx0sbSXA.png

    3. 查看档案列表,确认先前新增的档案内容是否有在内

      $ ls -al # 查看档案列表
      

      https://ithelp.ithome.com.tw/upload/images/20211005/20141010WxVvtf0lkx.png

      master 分支上有 hello.html 与 hello2.html 档案了~

      因为 master 将 one 分支合并,所以 one 分支上的 commit 内容在 master 分支上也有一份了。


快转模式 (Fast Forward)

什麽是快转模式呢?这是 git 在合并分支时的预设模式。

假设今天的 master 分支与 one 分支关系长这样:

https://ithelp.ithome.com.tw/upload/images/20211005/201410103cBtjrfIP3.png

https://ithelp.ithome.com.tw/upload/images/20211005/20141010jQtldlNT4y.png

one 分支与 master 分支为同个版本,也就是说他们有相同的档案与内容。

但是现在 one 分支新增 2 个版本,也就是领先 master 分支 2 个 Commit 版本。

当 master 要合并 one 分支时,master 分支与 one 分支的差异仅仅在於 one 分支多了 2 个 Commit 版本,其余档案内容都相同。

因为 master 分支与 one 分支都是同个 commit 分支出去的,所以当 master 分支合并 one 分支後,可以说是 master 合并自己以後的版本。这时 git 就会使用预设的 fast-forward 模式 来将 master 分支往後 2 个版本到 one 分支最新的 Commit 版本。

这时候两个分支的关系图会如以下图表示:

https://ithelp.ithome.com.tw/upload/images/20211005/20141010jmApNAWviy.png

假使今天的情况是 master 分支出去 one 分支与 two 分支:

又切回 master 分支,并新增 two 分支後提交两个新版本。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010c20C9aDS15.png

https://ithelp.ithome.com.tw/upload/images/20211005/20141010pYnDeE75p9.png

现在三个分支的关系如下图:

https://ithelp.ithome.com.tw/upload/images/20211005/20141010kS33v5shOT.png

one 分支与two 分支是从 master 分支出去的,并且都比 master 分支多了新的两个版本。one 分支与two 分支类似兄弟的概念。

master 分支想将两个分支都合并,因为 one 分支与 two 分支都是从 master 分支出去的,所以 master 有的档案内容 one 跟 two 都有,因此 master 要将与其中一只分支合并时,也是直接使用 fast-forward 模式 进行合并,简单来说可以想像是 master 分支可以将两个分支都直接收割了。

假设是 master 分支合并 two 分支:

https://ithelp.ithome.com.tw/upload/images/20211005/20141010uHYXShMmer.png


紧接上面的状况,如果是要使用 one 合并 two 分支,或是 two 分支来合并 one 分支呢?

虽然 onetwo 都是从同一个 Commit 出来的,有相同来源,但是两个分支有自己新增的版本,各自出家。此时如果要合并的话,Git 的方法是:

额外产生一个 Commit 来指向两个分支的最後 Commit,而执行合并的分支往前到最新的 Commit 中。

🛠 实际操作

假设如果是要用 two 分支来合并 one 分支的话, Commit 指向跟分支的关系会变成如下:

//当前在 two 分支上
$ git merge one # two 分支合并 one 分支

https://ithelp.ithome.com.tw/upload/images/20211005/20141010N42hBaFjqz.png

⚠️ 这时候可能会出现 Vim 编辑器,会提示说要请你输入文字纪录 Commit 的文字讯息

https://ithelp.ithome.com.tw/upload/images/20211005/20141010Fq6vcCQ0e2.png

👉 因此要确定在「Insert」模式下,可以按下 iao 其中一按键进入 Insert 模式,之後便可输入文字讯息。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010xyhM9XCYG8.png

https://ithelp.ithome.com.tw/upload/images/20211005/20141010spzRbXAqld.png

👉 过後需要在 「Nomal」 模式下才能存挡、离开。

Insert 模式与 Nomal 模式切换方式:按下 ESC 按键或是 Ctrl+[

⚠️ 在 「Nomal」 模式下,按下 :w 可进行存挡;按下 :q 会关闭档案,而 :wq 则是存挡完成後关闭档案。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010cKEK6d91JH.png

合并後的分支与 Commit 之间的状况会是:使用 git log 指令查看

会新增额外的 Commit 来合并两个分支

https://ithelp.ithome.com.tw/upload/images/20211005/20141010JqeYaP6yCK.png

https://ithelp.ithome.com.tw/upload/images/20211005/20141010yMhajXTQEq.png

使用 one 分支来合并 two 分支一样会产生新的 Commit ,但这个 Commit 值会因为计算结果而不同。


💬 我们可以思考【 A 合并 B 】与 【 B 合并 A 】有什麽不同呢?

其实就结果来看,谁合并谁是没有什麽差异的,但是过程中会有些差别。

不管是谁合并谁,每个分支上的 Commit 都是平等的,只是哪一个分支往前移动而已,而 Commit 本身的档案或内容并不会受影响。因此这里可以再次复习分支的观念:分支只是一个指标,即使删除或改名都不会影响已经存在的 Commit。


--no-ff 参数

预设的 fast-forward 模式 ,从 SourceTree 上来原来的新增的分支并不会特别表示,也可以称作是无线图,如果想要特别表示这里也有个其他分支(有线图),可以加上 --no-ff 参数即可。

$ git merge one --no-ff

如此一来就很像铁轨上又多出一条铁路出来,但都会抵达相同地点。

--no-ff 参数 - 不要使用快转模式合并。此时也会产生额外的 Commit 来指向前两个 Commit 喔!


救回被砍掉的未合并分支

有时候在我们还没合并分支前,可能会因为指令错误或是手残而不小心将新增的分支给砍掉了。如果想要把它救回来我们可以怎麽做呢?

方法|只要再制作分支将 Commit 内容接回来即可。

$ git branch 【新分支名称】 【Commit 的 SHA-1 值】

也许你会疑惑,为什麽我们明明已经砍掉分支,却还是可以找得到 Commit 的 SHA-1 值?这是因为一直强调的观念:分支只是一个指标。因此删掉分支,对 Git 来说只是一个指标没有了,但是 Commit 的内容依然存在,所以我们可以透过 Commit 的 SHA-1 值接回分支。

补充|如果忘记欲接回的 Commit 的 SHA-1 值,可以使用 git reflog 指令翻找。
Relog 预设会保留 30 天,如果是在时间范围内删除的都有机会查询到。


总结观念|

虽然我们说明上都是讲「合并分支」,实际上合并的应该是「分支指向的 Commit」。

👉 分支只是一个指向某个 Commit 的指标。


<<:  【Day 21】 实作 - 启用 AWS CloudFront 日志

>>:  ASP.NET MVC 从入门到放弃(Day30)-总结

转行的探索跟可以闪开的思考误区

早起运动30分钟Day1 今天一边运动,一边听《转行》这本书。里面提到几个我喜欢的观点。 “我们都以...

【踩坑】codepen没有出现fontawesome的icon!

有时候想要刻一些小物件,或是需要分享程序码给人以便请教问题 我都会使用codepen (真的是初学者...

[Day08] JavaScript - 回圈_part 2

forEach 来看看forEach在MDN的定义 Array.prototype.forEach(...

[Day28] Flutter with GetX Socket.io

Socket.io 注意server side需要使用3.0.3版本 否则flutter clien...

不用Recoil的话,如何自己制作一个 Custom hook 来共享全域变数?

需求 在早前几篇文章,我们介绍了 Recoil 这个 library 来在整个 App 分享全域变数...