📜  合并冲突以及如何处理它们

📅  最后修改于: 2021-10-24 12:46:47             🧑  作者: Mango

合并时的冲突是 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并提交

创建合并冲突Part1

第 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提交更改。