先前用 git 只處理過 text-base 的程式碼,最近要合併(merge)一組二進位檔(binary file)才發現從來沒遇過的情況。
一般來說,git merge 遇到衝突(conflict)的情況,如果是 text-base 的程式碼,會在檔案中插入文字標記讓使用者選擇需要的片段。例如:
<<<<<<< HEAD contact : email.support@github.com ======= please contact us at support@github.com >>>>>>> iss53
在 <<<<<<< 與 ======= 之間的是當下目錄中的版本的片段,======= 與 >>>>>>> 間的則是待合併的版本的片段。由於兩個要合併的版本間有這些程式碼的差異,需要使用者做選擇。要把這些提示文字處理掉才算是解決衝突,以便繼續進行合併。
不過二進位檔案不同版本間無法比較。在衝突操作上,只能就整個二進位檔案進行版本的選擇,而無法針對程式碼片段來處理。
以下以 TortoiseGit 這套 git GUI 做為範例來說明。在 bash 環境下原理也一樣。
在 TortoiseGIt 下遇到衝突會出現下圖這樣子的訊息,說明無法合併二進位檔。
若在右鍵選單中選取 Resolve…(下圖),會跳出需要去解決的衝突檔案列表。
再待處理的衝突檔案上按右鍵,會跑出下圖的選單。
「Resolve conflict using ‘mine’」就是選用當下目錄的版本(HEAD)做為合併後的版本。如果使用者在 master 分支,要合併到 dev 分支,也就是:
$ git checkout master $ git merge dev
「Resolve conflict using ‘mine’」便會使用 master 的版本來解決衝突。相對的,「Resolve conflict using ‘theirs’」便是選用 dev 的版本做為合併後的版本。
還有一個選項是「resolved」,實測後也是選用當下目錄的版本。理論上應該還是有區別,個人猜想是從 git rebase 的操作需要來的。待高手說明了。
至於選單最上面的「Edit conflicts」點開後,因為是二進位檔,無法做所謂「edit」的動作。但是目錄中會跳出三個額外的檔案(下圖),也就是 git merge 時做為合併依據的三方:共同祖先版本(BASE)、現有目錄中的版本(LOCAL)與待合併的分支的版本(REMOTE)。其中 LOCAL 就是前面提到的 mine,而 REMOTE 就是 theirs。使用者也可以在這邊檢視不同版本的細節,供做合併的參考。
當然上述三個檔案對於程式開發是額外的,衝突處理完便可以刪掉了。
發表迴響