Git 衝突處理

當一個專案同時有許多人在進行開發與維護時,時常會遇到兩個人修改同樣的文件甚至是同樣的地方,此時就必須決定該使用誰的版本,或是將兩種版本融合在一起。

在Git的架構裡,當進行MergePull、Rebase、Cherry-Pick甚至是Revert時,發現有兩筆Commit同時修改了相同位置,就會被判定為衝突(Conflict),意味著Git系統無法自動處理這樣的改變,必須由開發者手動解決。今天就來看看Git有哪些常見的衝突形式,以及處理衝突的方法與指令吧!

參考資料:
[GitHowTo]Resolving Conflicts
[Git Docs]git checkout

常見的衝突形式大致上分成下列三種:

1.檔案內容衝突

<<<<<HEAD
int a = 5;
int b = 10;

==========
int a = 6;
int b = 15;
>>>>>branchB

此為最常見的形式,只要發生衝突的檔案是可以直接用文字編輯器打開(並且一般人能夠閱讀),你就會看到檔案裡出現這些標記符號。

從<<<<<HEAD到=====之間是你當前所指向的分支,從=====到>>>>>branchB之間是你準備要合併進來的分支或Commit,選擇你想使用的版本,或是自行修改成你要的內容,並且將標記符號刪除才算解決衝突,最後進行add與commit的動作以完成這次的合併。

2.檔案版本衝突

Unmerged paths: (use "git add <file>..." to mark resolution)

both modified: libtest.so

both added    : taiwan.bin

與第一種非常相似,差別在於檔案內容是無法直接編輯的,例如:函式庫(副檔名.so或.a)、映像檔(副檔名.bin或.iso),因為無法比較內容,因此只能選擇版本,可以透過Git指令來操作。

$ git checkout --theirs FileName
=> checkout 至準備合併進來的版本
$ git checkout --ours FileName
=> checkout 至當前所指向(HEAD)的版本

最後進行add與commit以完成這次的合併。

3.檔案名稱衝突

Untracked files: (use "git add <file>..." to include in what will be committed)

config.xml~HEAD

這情形並不常見,Git系統竟然生成了一個的檔案,並且檔名後方出現~HEAD這樣的符號,為什麼?這代表什麼意思呢?

主要原因是兩個原本沒有任何關聯(Git歷史紀錄裡沒有共同祖先)的檔案,卻擁有相同的檔名,若進行合併,就會出現檔名衝突,因為Git系統不知道該保留哪一個,總不能同時出現兩個檔名相同的檔案吧!所以Git只能先將當前所指向的版本改名,再讓開發者去選擇該保留誰。

要複製這個現象並不複雜,有興趣的可以參考Edward Thomson提供的步驟,同時他也有對此現象提供更詳細的解釋。

留言

這個網誌中的熱門文章

程式語言常用之符號與詞彙 - 中英文對照

Repo 實用指令

什麼是 Bootloader?