iT邦幫忙

2021 iThome 鐵人賽

DAY 21
1
Modern Web

【Git】從零開始學習 Git - 30 天的學習筆記系列 第 21

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 的指標。


上一篇
Day20|【Git】介紹分支觀念與切換分支指令動作
下一篇
Day22|【Git】合併的另一個指令 - Rebase 與取消方式
系列文
【Git】從零開始學習 Git - 30 天的學習筆記30

尚未有邦友留言

立即登入留言