什麼是 Git 中的合併衝突?如何處理合併衝突?
在現實世界中,當我們合併分支時,經常會遇到衝突。衝突發生的原因如下:
當同一行程式碼在兩個分支中以不同的方式更改時。
在一個分支中更改了給定的檔案,但在另一個分支中刪除了該檔案。
在兩個不同的分支中兩次添加了相同的檔案,但檔案的內容不同。
在這些情況下,git 將停止合併過程,因為它無法確定如何合併更改。在這種情況下,我們需要手動干預並指示如何繼續合併過程。
下圖顯示了兩個分支master和feature。檔案hello.txt最初包含一行 Hello。初始提交後,由於它們具有單獨的提交,分支已分叉。每次提交都修改了檔案中同一行。
當我們嘗試將更改從 feature 分支合併到 master 分支時,我們會遇到合併衝突錯誤,如第二個圖所示。很明顯,git 將無法確定要保留哪個提交,因為第二行在每個提交中都不同。因此,它將提示我們確認是否只想保留 master 分支的更改,或只想保留 feature 分支的更改,或保留 feature 和 master 分支的更改。
示例
讓我們來看一下這個操作來理解合併衝突。
步驟 1 - 建立一個包含初始提交和hello.txt檔案的倉庫。
$ git init Initialized empty Git repository in E:/tut_repo/.git/ $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ echo hello>hello.txt $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git add . $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git commit -m 'hello.txt' [master (root-commit) b6a745d] hello.txt 1 file changed, 1 insertion(+) create mode 100644 hello.txt
步驟 2 - 建立一個新的分支 feature。切換到 feature 分支並透過編輯hello.txt檔案中的第二行來建立一個新的提交。
$ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git branch feature $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git switch feature Switched to branch 'feature' $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (feature) $ echo hello feature >> hello.txt $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (feature) $ git add . $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (feature) $ git commit -m 'hello feature' [feature a004fa4] hello feature 1 file changed, 1 insertion(+)
步驟 3 - 現在切換到 master 分支並透過向 hello.txt 新增新行來執行新的提交。
$ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (feature) $ git switch master Switched to branch 'master' $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ cat hello.txt hello $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ echo hello master>>hello.txt $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git add . $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git commit -m 'hello master' [master 6478b3e] hello master 1 file changed, 1 insertion(+)
步驟 4 - 我們現在將嘗試將更改從 feature 分支合併到 master 分支。
$ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git merge feature Auto-merging hello.txt CONFLICT (content): Merge conflict in hello.txt Automatic merge failed; fix conflicts and then commit the result. $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master|MERGING)
輸出顯示該分支現在處於合併的中間狀態,因為由於衝突導致自動合併失敗。我們需要手動干預才能完成合並過程。
步驟 5 - 檢查檔案hello.txt的內容
$ cat hello.txt hello <<<<<<< HEAD hello master ======= hello feature >>>>>>> feature
從檔案內容可以看出,第一行沒有改變。第二行將來自這兩個分支。輸出螢幕顯示一個用“=======”表示的分隔符。分隔符的第一半包含分隔符“<<<<<< HEAD”,這意味著內容來自當前分支(HEAD 指向 master)。分隔符的後一半包含分隔符“>>>>>> feature”,這意味著內容來自第二個分支 - feature。現在我們需要決定是保留前半部分還是後半部分,或者保留兩部分的更改。
步驟 6 - 我們決定保留兩部分的更改,因此我們手動修改檔案,只保留內容並刪除分隔符“=======”和分隔符“<<<<<< HEAD”和“>>>>>> feature”。
$ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master|MERGING) $ cat hello.txt hello hello master hello feature
步驟 7 - 現在提交更改並顯示歷史記錄。
$ git add . $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master|MERGING) $ git commit -m 'merge commit' [master 1183ce0] merge commit $ dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master) $ git log --oneline --all --graph * 1183ce0 (HEAD -> master) merge commit |\ | * a004fa4 (feature) hello feature * | 6478b3e hello master |/ * b6a745d hello.txt