Git下的衝突解決

衝突的產生
很多命令都可能出現衝突,但從根本上來講,都是merge 和 patch(應用補丁)時產生衝突。
而rebase就是重新設置基準,然後應用補丁的過程,所以也會衝突。
git pull會自動merge,repo sync會自動rebase,所以git pull和repo sync也會產生衝突。當然git rebase就更不用說了。
衝突的類型邏輯衝突
git自動處理(合併/應用補丁)成功,但是邏輯上是有問題的。
比如另外一個人修改了文件名,但我還使用老的文件名,這種情況下自動處理是能成功的,但實際上是有問題的。
又比如,函數返回值含義變化,但我還使用老的含義,這種情況自動處理成功,但可能隱藏着重大BUG。這種問題,主要通過自動化測試來保障。所以最好是能夠寫出比較完備的自動化測試用例。
這種衝突的解決,就是做一次BUG修正。不是真正解決git報告的衝突。
內容衝突
兩個用戶修改了同一個文件的同一塊區域,git會報告內容衝突。我們常見的都是這種,後面的解決辦法也主要針對這種衝突。
樹衝突
文件名修改造成的衝突,稱爲樹衝突。
比如,a用戶把文件改名爲a.c,b用戶把同一個文件改名爲b.c,那麼b將這兩個commit合併時,會產生衝突。
$ git status
    added by us :    b.c
    both deleted :   origin -name.c
    added by them :  a.c
如果最終確定用b.c,那麼解決辦法如下:
git  rm a.c
git  rm origin -name.c
git add b.c
git commit
執行前面兩個git rm時,會告警「file-name : needs merge」,可以不必理會。
 
樹衝突也可以用git mergetool來解決,但整個解決過程是在交互式問答中完成的,用d 刪除不要的文件,用c保留需要的文件。
最後執行git commit提交即可。
內容衝突的解決辦法發現衝突
一般來講,出現衝突時都會有「CONFLICT」字樣:
$ git pull
Auto -merging  test.txt
CONFLICT (content) : Merge conflict  in  test.txt
Automatic merge failed; fix conflicts  and  then commit the result.
 
但是,也有例外,repo sync的報錯,可能並不是直接提示衝突,而是下面這樣:
error : project mini /sample
注:無論是否存在衝突,只要本地修改不是基於服務器最新的,它都可能報告這個錯誤,解決方法都是一樣。
 
這個時候,需要進入報錯的項目(git庫)目錄,然後執行git rebase解決:
git rebase remote -branch -name
衝突解決的一般過程merge/patch的衝突解決
先編輯衝突,然後git commit提交。
注:對於git來講,編輯衝突跟平時的修改代碼沒什麼差異。修改完成後,都是要把修改添加到緩存,然後commit。
rebase的衝突解決
rebase的衝突解決過程,就是解決每個應用補丁衝突的過程。
解決完一個補丁應用的衝突後,執行下面命令標記衝突已解決(也就是把修改內容加入緩存):
git add  -u
注:-u 表示把所有已track的文件的新的修改加入緩存,但不加入新的文件。
 
然後執行下面命令繼續rebase:
git rebase  -- continue
有衝突繼續解決,重複這這些步驟,直到rebase完成。
 
如果中間遇到某個補丁不需要應用,可以用下面命令忽略:
git rebase  --skip
 
如果想回到rebase執行之前的狀態,可以執行:
git rebase  --abort
 
注:rebase之後,不需要執行commit,也不存在新的修改需要提交,都是git自動完成。
編輯衝突的方法直接編輯衝突文件
衝突產生後,文件系統中衝突了的文件(這裏是test.txt)裏面的內容會顯示爲類似下面這樣:
a123
<&lt; &lt;&lt; &lt;&lt; &lt; HEAD
b789
== == == =
b45678910
>&gt; &gt;&gt; &gt;&gt; &gt;  6853e5ff961e684d3a6c02d4d06183b5ff330dcc
c
其中:衝突標記<&lt;&lt;&lt;&lt;&lt;&lt; (7個&lt;)與=======之間的內容是我的修改,=======與>&gt;&gt;&gt;&gt;&gt;&gt;之間的內容是別人的修改。
此時,還沒有任何其它垃圾文件產生。
 
最簡單的編輯衝突的辦法,就是直接編輯衝突了的文件(test.txt),把衝突標記刪掉,把衝突解決正確。
利用圖形界面工具解決衝突
如果要解決的衝突很多,且比較複雜,圖形界面的衝突解決工具就顯得很重要了。
 
執行git mergetool用預先配置的Beyond Compare解決衝突:
$ git mergetool
Merging :
test.txt

Normal merge conflict  for  'test.txt' :
  {local} : modified
  {remote} : modified
 
201108071803029879.png
 
上面三個窗口依次是「LOCAL」、「BASE」、「REMOTE」,它們只是提供解決衝突需要的信息,是無法編輯的。
下面一個窗口是合併後的結果,可以手動修改,也可以點擊相應顏色的箭頭選擇「LOCAL」或者「REMOTE」。
 
在Beyond Compare中修改衝突保存後,衝突文件(test.txt)中的衝突標記就沒有了,成了修改後的內容,一個文件的衝突編輯就完成了。
 
注意:
啓動Beyond Compare之後,會自動生成幾個包含大寫字母名稱、數字的輔助文件:
20110807180303337.png
 
關閉Beyond Compare時,這幾個輔助文件都會自動刪除,但同時會生成一個test.txt.orig的文件,內容是解決衝突前的衝突現場。
默認該.orig文件可能不會自動刪除,需要手動刪掉。












本文轉sinojelly51CTO博客,原文鏈接:http://blog.51cto.com/sinojelly/633491 ,如需轉載請自行聯繫原作者