最后更新日期:2022/10/6
在Git中使用git merge
命令合并兩個分支的時候,有可能產(chǎn)生這種情況:
$ git merge A
Auto-merging merge.txt
CONFLICT (content): Merge conflict in merge.txt
Automatic merge failed; fix conflicts and then commit the result.
這就是發(fā)生了沖突(conflict)。
為什么會有沖突?要如何解決呢?請看下文介紹。
為什么會發(fā)生沖突?
簡單來說,就是兩個分支都對同一個文件做了更改,當這兩個分支合并的時候,Git不知道要采用哪一個更改,便發(fā)生了沖突。

舉個栗子,假設(shè)剛開始master
分支版本為C0
,然后依次發(fā)生了以下情況:
- 小A基于
C0
創(chuàng)建新分支new_branch
,并在該分支上改動了文件merge.txt
,提交得到版本C2
- 小B在主分支
master
上進行開發(fā),同樣改動了merge.txt
,提交得到版本C1
此時,如果用git merge
將master
與new_branch
合并,就會發(fā)生沖突。完整的過程如圖1所示。
Git提示沖突,也是一件好事,它其實是在告訴你:
“你讓我合并new_branch
和master
兩個分支,但是它們兩個都改動了merge.txt
,一個說要這樣改,一個說要那樣改,我應(yīng)該聽誰的呀?你來幫我看下吧!”。(形象解釋)
在講解如何解決沖突之前,我們得先有一個沖突。下面將根據(jù)圖1制造出一個沖突。
制造一個沖突
制造圖1的沖突分為4個步驟:
- 第一步:初始化倉庫及文件
- 第二步:在新分支上更改并提交文件
- 第三步:在主分支上更改并提交文件
- 第四步:執(zhí)行合并,觸發(fā)沖突
第一步:初始化倉庫及文件
首先創(chuàng)建一個新倉庫。打開Git Bash,順序執(zhí)行以下命令:
$ mkdir git-merge-test
$ cd git-merge-test
$ git init
Initialized empty Git repository in path/to/your/work/dictionary/git-merge-test/.git/
以上命令在當前位置創(chuàng)建了一個名為git-merge-test
的文件夾,并將其初始化為Git倉庫。
然后創(chuàng)建倉庫文件。在倉庫根目錄下新建merge.txt
,寫入以下內(nèi)容:
這是第一行,這行不會被修改
這是第二行
添加merge.txt
到暫存區(qū)并提交更改:
$ git add .
$ git commit -m"初始化倉庫內(nèi)容"
[master 8bc6262] 初始化倉庫
Date: Wed Oct 5 16:30:35 2022 +0800
1 file changed, 2 insertions(+)
create mode 100644 merge.txt
此時,master
處于圖1中的C0
。
第二步:在新分支上更改并提交文件
然后,創(chuàng)建一個新分支new_branch
::
$ git checkout -b new_branch
Switched to a new branch 'new_branch'
說明:
git checkout -b 分支名
表示創(chuàng)建一個新分支并切換到這個分支上。
修改merge.txt
:
這是第一行,這行不會被修改
我在new_branch分支上修改了第二行
添加merge.txt
并提交更改:
$ git commit -am"修改merge.txt"
[new_branch 8eb88a9] 修改merge.txt
1 file changed, 1 insertion(+), 1 deletion(-)
說明:
git commit -am"提交信息"
中的選項a
表示先git add
所有發(fā)生改動的文件再提交。
此時,new_branch
位于圖1中的C2
。
第三步:在主分支上更改并提交文件
$ git checkout master
Switched to branch 'master'
$ echo "我在master分支上添加了第三行" >> merge.txt
$ git commit -am"新增內(nèi)容到merge.txt"
[master 52c86fa] 新增內(nèi)容到merge.txt
1 file changed, 1 insertion(+)
上述命令的意思是,先切換回master分支,然后往merge.txt
中添加一行內(nèi)容(">>
"表示追加重定向文件),最后提交更改。
此時,master
位于圖1中的C1
。
第四步:執(zhí)行合并,觸發(fā)沖突
在合并之前,我們先捋一下現(xiàn)在的狀況:
- 最初的
merge.txt
的內(nèi)容為:這是第一行,這行不會被修改 這是第二行
- 在
new_branch
分支上改動后的merge.txt
內(nèi)容為:這是第一行,這行不會被修改 我在new_branch分支上修改了第二行
- 在
master
主分支上改動后的merge.txt
內(nèi)容為:這是第一行,這行不會被修改 這是第二行 我在master分支上添加了第三行
兩個分支都改動了merge.txt
,合并會發(fā)生什么呢?下面就來試一下。
在master
分支上執(zhí)行git merge new_branch
,嘗試把new_branch
分支合并過來:
$ git merge new_branch
Auto-merging merge.txt
CONFLICT (content): Merge conflict in merge.txt
Automatic merge failed; fix conflicts and then commit the result.
可以看到,沖突發(fā)生了。
在解決沖突之前,應(yīng)該先要知道如何查看沖突。下面將進行介紹。
如何查看沖突?
文章剛開始已經(jīng)提到,合并時發(fā)生沖突,是因為兩個分支都對同一個文件做了更改。當合并master
和new_branch
的時候,Git發(fā)現(xiàn)對于merge.txt
,一個分支這樣改,另一個分支那樣改,就陷入了兩難。從報錯信息可知,沖突需要我們手動解決后方可提交。
很多人到這里就懵了,不知道該怎么弄。實際上,我們現(xiàn)在正處于合并的“中間狀態(tài)”。合并的中間狀態(tài)就是合并了,但還沒完全合并。。好吧,是廢話,意思就是你執(zhí)行git merge
了,但git merge
并沒有執(zhí)行完成(因為發(fā)生沖突了),需要你解決沖突后繼續(xù)進行。
敲入git status
,就可以看到這樣的信息:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: merge.txt
no changes added to commit (use "git add" and/or "git commit -a")
git status
告訴我們以下信息:
- “You have unmerged paths”:我們現(xiàn)在正處于合并的中間狀態(tài),有一些沒有合并的文件;
- “Unmerged paths”:下面列出了所有未合并的文件,都顯示為紅色(網(wǎng)頁上看不到)??梢钥吹?,
merge.txt
沒有合并,因為兩個分支都更改了它(“both modified
”),發(fā)生了沖突。我們要先把沖突解決了。
那我們現(xiàn)在就來查看沖突。用編輯器打開merge.txt
,會發(fā)現(xiàn)內(nèi)容變成了這樣:
這是第一行,這行不會被修改
<<<<<<< HEAD
這是第二行
我在master分支上添加了第三行
=======
我在new_branch分支上修改了第二行
>>>>>>> new_branch
里面多了三行我們看不懂的記號:
<<<<<<< HEAD
=======
>>>>>>> new_branch
這些記號是標記沖突內(nèi)容的分隔線,解釋如下:
-
<<<<<<< HEAD
和=======
之間的內(nèi)容:是master
分支修改的內(nèi)容(準確來說是HEAD
指針指向的分支修改的內(nèi)容); -
=======
和>>>>>>> new_branch
之間的內(nèi)容:是new_branch
分支修改的內(nèi)容; -
分割線之外的內(nèi)容:是兩個分支都沒有改動的內(nèi)容(如
merge.txt
第一行)。
看懂了嗎?然后,解決沖突就變得很簡單了。
如何解決沖突?
解決沖突只需3步:
- 編輯沖突文件。決定要保留的內(nèi)容,然后刪掉三行分割線
-
git add
將沖突文件添加到暫存區(qū) -
git commit
提交
對于第1步,要按照你的具體情況去改。通常情況下,我們有這兩種做法:
- 保留其中一個修改,刪掉另一個
- 同時保留兩個修改
不管怎樣,最終改好的文件會原封不動地提交到倉庫中。另外需要注意,最后不要忘了刪掉三行分隔線,即:<<<<<<< HEAD
,=======
,>>>>>>> new_branch
在我們的例子中,假如我們想同時保留兩個分支的修改,那么可以編輯merge.txt
,僅刪掉三行分隔線,其他部分不用管,得到以下內(nèi)容:
這是第一行,這行不會被修改
這是第二行
我在master分支上添加了第三行
我在new_branch分支上修改了第二行
改好后,就可以提交了:
$ git add merge.txt
$ git commit -m "合并new_branch分支并解決沖突"
[master 0c88c4f] 合并new_branch分支并解決沖突
查看合并后的提交記錄:
$ git log
commit 0c88c4f9210af067125c9027f3e5885065f88dd0 (HEAD -> master)
Merge: 52c86fa 8eb88a9
Author: lanjianghao <528601933@qq.com>
Date: Wed Oct 5 22:28:34 2022 +0800
合并new_branch分支并解決沖突
commit 52c86fa51bca34c7763ed7b56b7705b3ce31379c
Author: lanjianghao <528601933@qq.com>
Date: Wed Oct 5 19:23:32 2022 +0800
新增內(nèi)容到merge.txt
commit 8eb88a9d1dc88b30333492ec44c12685aaa8187c (new_branch)
Author: lanjianghao <528601933@qq.com>
Date: Wed Oct 5 19:17:06 2022 +0800
修改merge.txt
commit 8bc626277eec39e413dcdd764642865b5291674e
Author: lanjianghao <528601933@qq.com>
Date: Wed Oct 5 16:30:35 2022 +0800
初始化倉庫
可以看到,日志中新增了一條合并記錄。
總結(jié)
-
為什么合并時發(fā)生了沖突?
- 要合并的兩個分支改動了同一個文件,Git不知道要采用哪個,還是兩個都采用,需要由你來決定。
-
怎樣查看沖突?
-
git status
查看沖突的文件 - 編輯器打開沖突的文件,查看沖突的內(nèi)容
- 沖突內(nèi)容分隔線怎么看:
未沖突的內(nèi)容(兩個分支都未改動)在分隔線外面 <<<<<<< HEAD Git當前所在分支修改的內(nèi)容(準確來說是HEAD指針指向的分支修改的內(nèi)容) ======= 要合并過來的分支修改的內(nèi)容 >>>>>>> branch_to_merge
-
-
怎樣解決沖突?
-
git status
查看沖突的文件 - 編輯沖突文件,解決沖突(記得刪除三行分隔線)
git add 沖突文件
git commit -m "提交信息"
-
其他問題
-
我不想繼續(xù)合并了,如何退出合并的中間狀態(tài)?
前文中提到,如果執(zhí)行git merge --abort
git merge
合并時發(fā)生沖突,則會進入合并的中間狀態(tài)。合并的中間狀態(tài)下將無法執(zhí)行其他一些操作(如切換分支)。
如果不想繼續(xù)合并,要先用git merge --abort
命令退出。該命令會使你回到執(zhí)行git merge 分支
之前的狀態(tài)。
感謝大家能看到這里!本人也還是小白,如果有不對的地方,歡迎指正!文章來源:http://www.zghlxwxcb.cn/news/detail-633976.html
參考:
https://www.atlassian.com/git/tutorials/using-branches/merge-conflicts文章來源地址http://www.zghlxwxcb.cn/news/detail-633976.html
到了這里,關(guān)于詳解Git合并沖突——問題重現(xiàn)、原因及解決 “Automatic merge failed; fix conflicts and then commit the result.“的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!