合并时的冲突是 Git 体验中经常出现的部分。如果有多个开发人员在处理同一个文件,则遇到合并冲突的几率会增加。大多数时候,Git 会自动弄清楚如何集成新的更改。当两个人更改了文件中的相同行,或者一个开发人员删除了一个文件而另一个开发人员正在修改它时,通常会发生冲突。在这些情况下,Git 无法自动确定哪个是正确的。因此,Git 会通知执行合并的开发人员遇到冲突,团队的其他成员将不知道冲突。现在,执行合并的开发人员有责任解决冲突。
合并冲突的类型
开始合并时:如果工作目录或暂存区发生变化,在合并时,Git 将无法开始合并。发生这种情况是因为挂起的更改可能会被正在合并的提交覆盖。这是发生这种类型的合并冲突时 Git 提供的错误消息:
error: Entry '' not uptodate. Cannot merge. (Changes in working directory)
or,
error: Entry '' would be overwritten by merge. Cannot merge. (Changes in staging area)
这种类型的冲突可以通过执行git stash save “any_message_to_describe_what_is_saved” (将暂存区和工作目录中的任何更改隐藏在单独的索引中)或git checkout
在合并期间:发生这种情况是因为您提交的更改与其他人提交的更改冲突。 Git 将尽最大努力合并这些文件,并将在它列出的文件中留给您手动解决的事情。这是发生这种类型的合并冲突时 Git 提供的错误消息:
CONFLICT (content): Merge conflict in
Automatic merge failed; fix conflicts and then commit the result.
这种类型的冲突可以通过手动修复每个文件的所有合并冲突或使用git reset ––hard (重置存储库以退出合并冲突情况)来解决。
创建合并冲突
为了展示合并冲突如何发生的简单示例,我们可以在任何 UNIX 终端 / GIT bash 中从以下命令集手动触发合并冲突:
步骤 1:使用 mkdir命令创建一个新目录,然后cd进入该目录。
第 2 步:使用 git init命令将其初始化为一个新的 Git 存储库,并使用 touch命令创建一个新的文本文件。
步骤3:打开文本文件并在其中添加一些内容,然后将文本文件添加到repo并提交。
第 4 步:现在,是时候创建一个新分支以将其用作冲突合并。使用git checkout创建和检出新分支。
第 5 步:现在,从这个新分支覆盖对文本文件的一些冲突更改。
第 6 步:将更改添加到 git 并从新分支提交。
通过这个新分支:new_branch_for_merge_conflict,我们创建了一个覆盖 test_file.txt 内容的提交
第 7 步:再次检出master 分支,这次将一些文本附加到 master 分支的 test_file.txt 中。
第 8 步:将这些新更改添加到暂存区并提交。
Step 9:现在是最后一部分,尝试将新分支合并到主分支,您将遇到第二种合并冲突。
所以,现在我们已经成功触发了 Git 中的合并冲突。
识别和解决冲突
正如我们在前面的例子中所经历的那样,Git 会产生一些描述性的输出,让我们知道发生了冲突。我们可以通过运行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 ..." to mark resolution)
both modified: test_file.txt
no changes added to commit (use "git add" and/or "git commit -a")
在打开 test_file.txt 时,我们会看到一些“冲突分隔符”。这是我们的 test_file.txt 的内容:
<<<<<<< HEAD
Adding some content to mess with it later
Append this text to initial commit
=======
Changing the contents of text file from new branch
>>>>>>> new_branch_for_merge_conflict
======== 线是冲突的“中心”。 center 和 <<<<<<< HEAD 行之间的所有内容都是存在于 HEAD ref 指向的当前分支 master 中的内容。或者,中心和 >>>>>>> new_branch_for_merge_conflict 之间的所有内容都是存在于我们的合并分支中的内容。
为了解决我们的合并冲突,我们可以手动从任何一个分支中删除不需要的部分,只考虑对进一步使用很重要的分支内容,同时从我们的文件中删除“冲突分隔符”。冲突解决后,我们可以使用git add命令将新更改移动到暂存区,然后git commit提交更改。