1. 程式人生 > >git 合併衝突應該瞭解的

git 合併衝突應該瞭解的

處理合並衝突

對於很多人來說,合併時出現衝突是非常可怕的事,這就好像一不小心格式化了自己的硬碟一樣。在這一章節裡我將為你消除這種恐懼。

你不會把事情搞砸

首先你應該記住,你總是可以撤銷一個合併操作,並且返回到衝突發生之前的狀態。也就是說,你永遠有機會放棄並重新開始。

如果你已經掌握了一些關於其它的版本控制系統的使用經驗,例如 Subversion ,你可能會很難過。因為在 Subversion 中處理衝突是被大家公認極為複雜而繁瑣的。這也就是為什麼我們要使用 Git 的原因。簡單地說,它在這方面的工作原理是完全不同於 Subversion 的。Git 能夠在合併過程中顧及到很多方方面面的東西,從而為你創造一個比較簡單的方案來解決可能出現的衝突。

當然,衝突只會妨礙你自己的工作,它是不會涉及到整個團隊的專案倉庫。這是因為在 Git 中,衝突只可能發生在開發人員的本地計算機上,而不是在遠端伺服器上。

什麼是一個合併衝突

在 Git 中,“合併(merging)” 是在形式上整合別的分支到你當前的工作分支的操作。你需要得到在另外一個上下文背景下的改動(這就也就是我們所提到過的,一個有效的分支應該是建立在一個上下文工作背景上的),並且合併它們到你的當前的工作檔案中來。

作為你的版本管理系統,Git 所帶來的最偉大的改善就是它讓合併操作變得非常輕鬆簡單。在大多數情況下,Git 會自己弄清楚該如何整合這些新來的變化。

當然,也存在極少數的情況,你必須自己手動地告訴 Git 該怎麼做。最為常見的就是大家都改動了同一個檔案。即便在這種情況下,Git 還是有可能自動地發現並解決掉這些衝突。但是,如果兩個人同時更改了同一個檔案的同一行程式碼,或者一個人改動了那些被另一個人刪除了的程式碼,Git 就不能簡單地確定到底誰的改動才是正確的。這時 Git 會把這些地方標記為一個衝突,你必須首先解決掉這些衝突,然後再繼續你的工作。

如何解決合併衝突

當面對一個合併衝突時,我們首先要搞明白髮生了什麼。例如是不是你和你的同事都同時編輯了同一個檔案的同一行程式碼呢?是不是他刪除了一個你正在編輯的檔案呢?是不是你們同時添加了一個相同檔名的檔案呢?
當你使用 “git status” 時, Git 會告訴你存在一個 “未合併的路徑(unmerged paths)”,這只是用另外一個方式告訴你,存在一個或多個衝突:

$ git status
# On branch contact-form
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#
#       both modified:   contact.html
#
no changes added to commit (use "git add" and/or "git commit -a")

就讓我們來深入地探討一下,如何去解決這些最常見的衝突。
當兩個改動發生在同一個檔案的同一些行上,我們就要看看發生衝突的檔案的內容了。Git 會非常友好地把檔案中那些有問題的區域在 “<<<<<<< HEAD” 和 “>>>>>>> [other/branch/name]” 之間標記出來。

第一個標記後的內容源於當前分支。在尖括號之後,Git 會告訴我們這些改動是從哪裡(哪個分支)來的。然後有衝突的改動會被 “=======” 分割起來。

現在我們的工作是要清理這些問題行。當我們完成這些清理後,這個檔案應該看起來和我們預期的完全一樣。在過程中你也可能需要諮詢一下那個和你的程式碼發生衝突的同事,從而更好地決定哪些改動才是最終正確的,哪些改動是需要被放棄掉的。可能是你的改動,也可能是他的,或者可能是你們兩個改動的組合。

開啟一個比較原始的檔案編輯器來清理這些衝突看起來是可行的,但是這樣並不簡單。使用一個專門的合併工具可以使這個操作變得更容易(如果你已經安裝了一個在你的本地計算機上……)。你可以通過 “git config” 命令來設定這個合併工具給 Git。更詳細的內容你就要檢視這個工具的文件說明了。
之後當發生合併衝突時,你可以使用 “git mergetool” 命令來呼叫這個工具。

例如,我在 Mac 上使用 “Kaleidoscope.app”:

在左邊和右邊的視窗會標記出那些改動的衝突。比起那些用符號 “<<<<<<<” 和 “>>>>>>>” 來標記衝突的方法來說,這是一個更加優雅的視覺化環境。你可以非常方便地選擇哪個改動是需要被保留的。位於中間的視窗會顯示出處理後的結果,並且你也可以進一步手動編輯它。

現在,當清理檔案並得到最終程式碼後,所有剩下的工作就是將這個結果儲存起來,並且馬上退出這個合併工具。這樣 Git 就會知道你已經完成了這個操作。Git 會在後臺對那個檔案自動地執行 “git add” 命令。這也標誌著衝突已經解決了。如果你_不_使用合併工具,而是手動在文字編輯器中清理這些衝突,你必須手動地將檔案標記為已解決狀態(通過執行命令 “git add <filename>”)。

最終,當所有的衝突被解決後,你必須通過一個正常的提交操作來完成這個清理合並衝突的工作。

如何撤銷一個合併

你應該始終牢記,你可以在任何時間執行撤銷操作,並返回到你開始合併之前的狀態。要對自己有信心,你不會破壞專案中的任何東西。只要在命令列介面中鍵入 “git merge --abort” 命令,你的合併操作就會被安全的撤銷。

當你解決完衝突,並且在合併完成後發現一個錯誤,你仍然還是有機會來簡單地撤銷它。你只須要鍵入 “git reset --hard ” 命令,系統就會回滾到那個合併開始前的狀態,然後重新開始吧!