Git 合并冲突
版本控制系统就是管理多个分布式作者(通常是开发人员)之间的贡献。有时,多个开发人员可能会尝试编辑相同的内容。如果开发人员 A 尝试编辑开发人员 B 正在编辑的代码,则可能会发生冲突。为了缓解冲突的发生,开发人员将在单独的独立分支中工作。git merge
命令的主要职责是合并不同的分支并解决所有冲突的编辑。
了解合并冲突
冲突通常发生在两个人变更文件中的相同行时,或者一个开发人员在另一个开发人员修改文件时删除了文件。在这些情况下,Git 无法自动确定什么是正确的操作。冲突只影响进行合并的开发人员,团队的其他成员没有意识到冲突。Git 会将文件标记为冲突并停止合并流程。然后就由开发人员来解决冲突。
合并冲突的类型
合并可以在两个不同的点进入冲突状态:开始合并和合并流程中。以下是关于如何解决每种冲突情景的讨论。
Git 无法启动合并
当 Git 发现当前项目的工作目录或暂存区域有变化时,将无法启动合并。Git 无法启动合并,因为这些待处理变更可能会被合并的提交写入。发生这种情况时,不是因为与其他开发人员的冲突,而是因为与待处理的本地变更发生冲突。需要使用 git stash
、git checkout
、git commit
或 git reset
来稳定本地状态。启动时合并失败将输出以下错误消息:
error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
Git 在合并过程中失败
合并期间的失败表示当前本地分支和正在合并的分支之间存在冲突。这表明与其他开发人员的代码存在冲突。Git 会尽力合并文件,但会将冲突文件中的问题留给您手动解决。合并中期失败将输出以下错误消息:
相关资料
高级 Git 日志
查看解决方案
了解 Bitbucket Cloud 的 Git
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)
创建合并冲突
为了真正熟悉合并冲突,下一节将模拟冲突,供以后研究和解决。该示例将使用类似 Unix 的命令行 Git 接口来执行示例模拟。
$ mkdir git-merge-test
$ cd git-merge-test
$ git init .
$ echo "this is some content to mess with" > merge.txt
$ git add merge.txt
$ git commit -am"we are commiting the inital content"
[main (root-commit) d48e74c] we are commiting the inital content
1 file changed, 1 insertion(+)
create mode 100644 merge.txt
此代码示例执行了一系列命令来完成以下操作。
- 创建一个名为
git-merge-test
的新目录,切换到该目录,然后将其初始化为新的 Git 代码存储库。 - 创建一个包含一些内容的新文本文件
merge.txt
。 - 将
merge.txt
添加到代码存储库并提交。
现在我们有了一个新的代码存储库,其中包含一个分支 main
和一个包含内容的 merge.txt
文件。接下来,我们将创建一个新分支用作冲突合并。
$ git checkout -b new_branch_to_merge_later
$ echo "totally different content to merge later" > merge.txt
$ git commit -am"edited the content of merge.txt to cause a conflict"
[new_branch_to_merge_later 6282319] edited the content of merge.txt to cause a conflict
1 file changed, 1 insertion(+), 1 deletion(-)
接下来的命令序列实现了以下目的:
- 创建并签出一个名为
new_branch_to_merge_later
的新分支 - 覆盖
merge.txt
中的内容 - 提交新内容
有了这个新分支:new_branch_to_merge_later
,我们创建了一个覆盖 merge.txt
内容的提交
git checkout main
Switched to branch 'main'
echo "content to append" >> merge.txt
git commit -am"appended content to merge.txt"
[main 24fbe3c] appended content to merge.tx
1 file changed, 1 insertion(+)
这条命令链签出 main
分支,将内容附加到 merge.txt
,然后提交。现在,这使我们的示例代码存储库处于有 2 个新提交的状态。一个在 main
分支,另一个在 new_branch_to_merge_later
分支中。此时 git merge new_branch_to_merge_later
,看看会发生什么!
$ git merge new_branch_to_merge_later
Auto-merging merge.txt
CONFLICT (content): Merge conflict in merge.txt
Automatic merge failed; fix conflicts and then commit the result.
爆炸 💥。出现冲突。谢谢 Git 告诉我们这件事!
如何识别合并冲突
正如我们在前面示例中所经历的那样,Git 将生成一些描述性输出,让我们知道冲突已经发生了。我们可以通过运行 git status 命令获得进一步的见解
$ git status
On branch main
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
git status
的输出表明,由于冲突,存在未合并的路径。merge.text
文件现在显示为已修改状态。我们检查一下文件,看看修改了什么。
$ cat merge.txt
<<<<<<< HEAD
this is some content to mess with
content to append
=======
totally different content to merge later
>>>>>>> new_branch_to_merge_later
这里我们使用 cat
命令发布了 merge.txt
文件的内容。我们可以看到一些奇怪的新增内容
<<<<<<< HEAD
=======
>>>>>>> new_branch_to_merge_later
可以把这些新的行看作是"冲突分隔符"。=======
行是冲突的"中心"。中心行和 <<<<<<< HEAD
行之间的所有内容都是存在于 HEAD
引用指向的当前主分支中的内容。或者,介于中心和 >>>>>>> new_branch_to_merge_later
之间的所有内容都是存在于我们的合并分支中的内容。
如何使用命令行解决合并冲突
解决合并冲突的最直接方法是编辑冲突文件。在您最喜欢的编辑器中打开 merge.txt
文件。在我们的示例中,我们只是删除所有冲突分隔符。修改后的 merge.txt
内容应该如下所示:
this is some content to mess with
content to append
totally different content to merge later
编辑完文件后,使用 git add merge.txt
暂存新的合并内容。要完成合并,请执行以下命令创建一个新提交:
git commit -m "merged and resolved the conflict in merge.txt"
Git 将看到冲突已解决,并创建新的合并提交以完成合并。
可以帮助解决合并冲突的 Git 命令
通用工具
git status
使用 Git 时经常使用状态命令,在合并过程中,它将帮助识别冲突文件。
git log --merge
将 --merge
参数传递给 git log
命令将生成一个日志,其中包含合并分支之间冲突的提交列表。
git diff
diff
有助于找出存储库/文件状态之间的差异。这对于预测和防止合并冲突很有用。
git 无法启动合并时的工具
git checkout
checkout
可用于撤销对文件的变更或变更分支
git reset --mixed
reset
可用于撤销对工作目录和暂存区域的变更。
合并期间出现 git 冲突时的工具
git merge --abort
使用 --abort
选项执行 git merge
将退出合并流程,并将分支恢复到合并开始之前的状态。
git reset
可以在合并冲突期间使用 Git reset
将冲突文件重置为已知的良好状态
摘要
合并冲突可能是一种令人生畏的经历。幸运的是,Git 提供了强大的工具来帮助导航和解决冲突。Git 可以通过自动合并功能自行处理大多数合并。当两个不同的分支对文件中的同一行进行编辑时,或者当一个分支中的文件被删除但在另一个分支中编辑时,就会发生冲突。在团队环境中工作时,很可能会发生冲突。
有许多工具可以帮助解决合并冲突。我们在这里讨论过 Git 有很多命令行工具。有关这些工具的更多详细信息,请访问 git log、git reset、git status、git checkout 和 git reset 的独立页面。除了 Git 外,许多第三方工具还提供简化的合并冲突支持功能。
分享此文章
下一主题
推荐阅读
将这些资源加入书签,以了解 DevOps 团队的类型,或获取 Atlassian 关于 DevOps 的持续更新。