分支合併的方法有兩種:merge 和 rebase
本篇先講解使用 merge
來合併分支的觀念。
情境|想要使用 A 分支來合併 B 分支
步驟|
先切換到 A 分支(顯示當前位於 A 分支上)
使用 git merge
指令
$ git merge B分支 # 合併 B 分支
🛠 實際操作
建立新的分支,並 Commit 兩次。
$ git branch one # 新增一個 one 分支
$ git checkout one # 切換到 one 分支
// 重複動作提交第二次
$ touch hello.html # 新增一個檔案
$ git add . # 加至暫存區
$ git commit -m"訊息記錄" # 提交到儲存庫
任務:想要使用 master
分支來合併 one
分支
因目前在 one 分支上,因此先切回到 master 分支上。
$ git checkout master # 切換到 master 分支
執行合併分支 git merge
指令( master
合併 one
分支)
$ git merge one # 合併 one 分支
查看檔案列表,確認先前新增的檔案內容是否有在內
$ ls -al # 查看檔案列表
master 分支上有 hello.html 與 hello2.html 檔案了~
因為 master 將 one 分支合併,所以 one 分支上的 commit 內容在 master 分支上也有一份了。
什麼是快轉模式呢?這是 git 在合併分支時的預設模式。
假設今天的 master 分支與 one 分支關係長這樣:
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 版本。
這時候兩個分支的關係圖會如以下圖表示:
假使今天的情況是 master 分支出去 one 分支與 two 分支:
又切回 master
分支,並新增 two
分支後提交兩個新版本。
現在三個分支的關係如下圖:
one
分支與two
分支是從master
分支出去的,並且都比master
分支多了新的兩個版本。one
分支與two
分支類似兄弟的概念。
master 分支想將兩個分支都合併,因為 one 分支與 two 分支都是從 master 分支出去的,所以 master 有的檔案內容 one 跟 two 都有,因此 master 要將與其中一隻分支合併時,也是直接使用 fast-forward 模式 進行合併,簡單來說可以想像是 master 分支可以將兩個分支都直接收割了。
假設是 master 分支合併 two 分支:
緊接上面的狀況,如果是要使用 one
合併 two
分支,或是 two
分支來合併 one
分支呢?
雖然 one
跟 two
都是從同一個 Commit 出來的,有相同來源,但是兩個分支有自己新增的版本,各自出家。此時如果要合併的話,Git 的方法是:
再額外產生一個 Commit 來指向兩個分支的最後 Commit,而執行合併的分支往前到最新的 Commit 中。
🛠 實際操作
假設如果是要用 two 分支來合併 one 分支的話, Commit 指向跟分支的關係會變成如下:
//當前在 two 分支上
$ git merge one # two 分支合併 one 分支
⚠️ 這時候可能會出現 Vim 編輯器,會提示說要請你輸入文字紀錄 Commit 的文字訊息
👉 因此要確定在「Insert」模式下,可以按下 i
、a
、o
其中一按鍵進入 Insert 模式,之後便可輸入文字訊息。
👉 過後需要在 「Nomal」 模式下才能存擋、離開。
Insert 模式與 Nomal 模式切換方式:按下
ESC
按鍵或是Ctrl+[
⚠️ 在 「Nomal」 模式下,按下 :w
可進行存擋;按下 :q
會關閉檔案,而 :wq
則是存擋完成後關閉檔案。
合併後的分支與 Commit 之間的狀況會是:使用 git log
指令查看
會新增額外的 Commit 來合併兩個分支
使用
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 的指標。