什么是 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