--- title: 實戰Git-Merge tags: git --- # 實戰Git-Merge [TOC] --- ### 分支合併 可以安裝[Sourcetree](https://www.sourcetreeapp.com)以便日後好了解分支。 #### Fast-forward 在開始之前先按照以下步驟依序執行 1. 創建一個新的資料夾 2. 切換到該資料夾並透過命令列進行初始化`git init` 3. 在該資料夾建立一個test.txt的文字檔內容隨意 4. 將該檔案add & commit ![](https://i.imgur.com/uxpHGdp.png) 在master分支中透過`git checkout -b bugfix`建立一個新的bugfix分支。 ![](https://i.imgur.com/g7VZxI9.png) 在bugfix分支中建立一個新文件test2.txt將其add & commit。 ![](https://i.imgur.com/rBTpo4q.png) 我們可以從log中看到新的分支超前於master ![](https://i.imgur.com/XLgjt1r.png) 接下來切換到master分支並透過`merge`指令將bugfix合併進來。 ```bash= git checkout master git merge bugfix ``` ![](https://i.imgur.com/AdnWsqI.png) 在merge前master指向73f04d0,merge後指向了c657ca5,且在merge後會在.git中多一個ORIG_HEAD(HEAD之前的狀態)。 因為merge為比較危險的操作,因此需保留以前的狀態用於回滾。 以下為恢復merge指令 ```bash= git reset ORIG_HEAD ``` #### 3 way merge 重設merge後需要重新將檔案加入儲存庫,我們可以透過`git status`來查看。 ![](https://i.imgur.com/BuJybIf.png) 加入之後(不需要commit),再新增一個test3檔案並add & commit。 ![](https://i.imgur.com/xUiAwFf.png) 執行`git merge bugfix`,會出現以下訊息,直接:wq結束即可。 ![](https://i.imgur.com/aBa160N.png) 透過`git log`會發現產生了一個新的commit ![](https://i.imgur.com/mbEc8DR.png) 我們將他的hash複製後透過`git cat-file -p hashCode`來查詢會發現他會有兩組parent。 ![](https://i.imgur.com/qWD144a.png) 一個是bugfix所對應的最新的commit 我們可以透過`cat .git/refs/heads/bugfix`來確認 ![](https://i.imgur.com/zN9W4QT.png) 另一個則是master對應master當時最新的commit 我們可以透過`cat .git/ORIG_HEAD`取得當時最新的commit ![](https://i.imgur.com/j3lUFvW.png) 這次教學的狀態圖如下, master merge前的狀態 ![](https://i.imgur.com/VgQapkO.png) master merge後會發現,多出一個新的commit指向兩個commit分別為C3與C4,再將master指標移動到最新的commit ![](https://i.imgur.com/fs73A7j.png) 我們可以透過source tree 來查看 ![](https://i.imgur.com/dSNxJGJ.png) #### 新測試(遇到碰撞) 假設我們要作出如下圖的分支狀態,C1分支出bugfix(C2)且C1進行新增add from master並commit變成C3。 ![](https://i.imgur.com/WNvZrMC.png) 首先建立一個新的資料夾來進行此實驗。 ```bash= mkdir newMergeTest cd newMergeTest git init ``` ![](https://i.imgur.com/dgatgW5.png) 新增檔案test.txt在當前目錄並add & commit ![](https://i.imgur.com/wjBZMez.png) 再接著透過git checkout -b bugfix 切換至新的分支,並修改檔案內容新增一行文字再add & commit。 ![](https://i.imgur.com/FhqbBdj.png) 接著切換至master分支並修改test.txt再進行add & commit。(這裡的commit message打錯了應該是3rd才對) ![](https://i.imgur.com/gbipb1W.png) 當我們進行merge時會發現因為修改了雙方共同擁有的檔案因此發生錯誤。 ![](https://i.imgur.com/RVaMwSf.png) 我們可以透過cat test.txt來查看修改的內容 <<<<<<<HEAD的意思是當前master的內容 ![](https://i.imgur.com/EoJlWQ9.png) 我們把索引區的內容印出來後會發現有三筆資料,我們可以透過`git cat-file -p hashCode`來查看內容(這裡不demo) ![](https://i.imgur.com/PxAOWQV.png) 我們可以透過Vscode來解決這個問題(比較好懂)。 Accept Current Change = 接受當前(master)的版本 Accept Incoming Change = 接受分支(bugfix)的版本 Accept Both Change = 兩個都接受(相異之處貼上) 這裡我們選擇Accept Both Change。 ![](https://i.imgur.com/9gikH1B.png) 當儲存完畢後,我們回到命令列將檔案add,我們透過`git ls-files -s`會發現只剩下一個檔案了。 ![](https://i.imgur.com/mtlrOZf.png) 這時候我們只需要用`git commit`就可以了(不需要再加message),輸入完畢後會如同之前遇到的merge狀況一樣,git會提醒你會產生一個merge commit。 ![](https://i.imgur.com/VzDlTau.png) 我們可以透過`git log`查看當前分支狀態。 ![](https://i.imgur.com/vcDlmve.png) 再接著利用`git cat-file -p hashCode`來查看會發現當前commit有兩個parent分別是之前的master與bugfix。 ![](https://i.imgur.com/y2MDIGt.png) #### git rebase fast forward 定義:當分支擁有最新的master commit時,合併回去才是fast forward。 git rebase: ![](https://i.imgur.com/qInT5bN.gif) 1. 創建一個git-rebase的資料夾 2. 在該資料夾進行init 3. 在master創建一個test1.txt 並 add & commit 4. 接著切換到bugfix分支新增一個test2.txt 並 add & commit ![](https://i.imgur.com/8L1HFco.png) 接著切換回master分支創建test3.txt並 add & commit,完成後切換到bugfix進行rebase。 ```bash= git rebase master ``` 我們可以透過`git log`來看修改了什麼 ![](https://i.imgur.com/PoISszZ.png) 此時若在切回master進行merge就會變成fast forward。 ![](https://i.imgur.com/3xnEmHa.png) 透過git log 查看會發現logt記錄變成線性的而不是3 way。 ![](https://i.imgur.com/BO3GuzF.png)