Git 衝突處理
當一個專案同時有許多人在進行開發與維護時,時常會遇到兩個人修改同樣的文件甚至是同樣的地方,此時就必須決定該使用誰的版本,或是將兩種版本融合在一起。
在Git的架構裡,當進行Merge、Pull、Rebase、Cherry-Pick甚至是Revert時,發現有兩筆Commit同時修改了相同位置,就會被判定為衝突(Conflict),意味著Git系統無法自動處理這樣的改變,必須由開發者手動解決。今天就來看看Git有哪些常見的衝突形式,以及處理衝突的方法與指令吧!
參考資料:
[GitHowTo]Resolving Conflicts
[Git Docs]git checkout
常見的衝突形式大致上分成下列三種:
1.檔案內容衝突
此為最常見的形式,只要發生衝突的檔案是可以直接用文字編輯器打開(並且一般人能夠閱讀),你就會看到檔案裡出現這些標記符號。
從<<<<<HEAD到=====之間是你當前所指向的分支,從=====到>>>>>branchB之間是你準備要合併進來的分支或Commit,選擇你想使用的版本,或是自行修改成你要的內容,並且將「標記符號刪除」才算解決衝突,最後進行add與commit的動作以完成這次的合併。
2.檔案版本衝突
與第一種非常相似,差別在於檔案內容是無法直接編輯的,例如:函式庫(副檔名.so或.a)、映像檔(副檔名.bin或.iso),因為無法比較內容,因此只能選擇版本,可以透過Git指令來操作。
最後進行add與commit以完成這次的合併。
3.檔案名稱衝突
這情形並不常見,Git系統竟然生成了一個的檔案,並且檔名後方出現~HEAD這樣的符號,為什麼?這代表什麼意思呢?
主要原因是兩個原本沒有任何關聯(Git歷史紀錄裡沒有共同祖先)的檔案,卻擁有相同的檔名,若進行合併,就會出現檔名衝突,因為Git系統不知道該保留哪一個,總不能同時出現兩個檔名相同的檔案吧!所以Git只能先將當前所指向的版本改名,再讓開發者去選擇該保留誰。
要複製這個現象並不複雜,有興趣的可以參考Edward Thomson提供的步驟,同時他也有對此現象提供更詳細的解釋。
在Git的架構裡,當進行Merge、Pull、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
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
both modified: libtest.so
both added : taiwan.bin
與第一種非常相似,差別在於檔案內容是無法直接編輯的,例如:函式庫(副檔名.so或.a)、映像檔(副檔名.bin或.iso),因為無法比較內容,因此只能選擇版本,可以透過Git指令來操作。
$ git checkout --theirs FileName
=> checkout 至準備合併進來的版本
$ git checkout --ours FileName
=> checkout 至當前所指向(HEAD)的版本
=> 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
config.xml~HEAD
這情形並不常見,Git系統竟然生成了一個的檔案,並且檔名後方出現~HEAD這樣的符號,為什麼?這代表什麼意思呢?
主要原因是兩個原本沒有任何關聯(Git歷史紀錄裡沒有共同祖先)的檔案,卻擁有相同的檔名,若進行合併,就會出現檔名衝突,因為Git系統不知道該保留哪一個,總不能同時出現兩個檔名相同的檔案吧!所以Git只能先將當前所指向的版本改名,再讓開發者去選擇該保留誰。
要複製這個現象並不複雜,有興趣的可以參考Edward Thomson提供的步驟,同時他也有對此現象提供更詳細的解釋。
留言
張貼留言