合并类型
Git merge 和 rebase 是将目标分支的提交集成到源分支的两种方式。此外,Git merge 会执行快进(fast-forward)或非快进(no-fast-forward)合并。若目标分支的头指针已存在于源分支中,默认会进行快进合并;若不存在,则为非快进合并。Git rebase 则是另一种通过重新排序目标分支提交历史来实现的合并方式。
快进合并

默认情况下,Git merge 使用快进方式将缺失的提交集成到目标分支。例如,使用 pull 命令从远程服务器更新本地分支就会用到它。快进合并不会引发合并冲突,因为当源分支中缺少目标分支的头指针时,Git 就不会应用快进合并。
非快进合并

非快进合并也称为三方合并或真正的合并。它会在目标分支上创建一个新的提交,将源分支和目标分支中的更改集成在一起。这些更改会在两个分支的最后一个共同提交之后进行融合。在这里,就是在 C 之后。若源分支与目标分支存在冲突,此类合并会触发 Git 合并冲突。在上图中,合并提交(X)由源分支与目标分支集成而成,K 和 E 是该合并提交的父提交。
变基

Git rebase 与其他类型稍有不同。它会改变目标分支提交历史的顺序。变基会以这样的方式集成源分支:目标分支先包含源分支的所有更改,然后在最后一个共同提交之后,接上目标分支自身的所有提交。在这里,最后的共同提交是 C,而 D 和 E 来自源分支。K* 与 K 的内容相同但提交 ID 不同;它不再链接到 C,而是链接到 E。与非快进合并类似,若源分支与目标分支存在兼容性问题,Git 会在完成变基前要求您先解决冲突。
Git 合并冲突的类型
Git 合并冲突有两种类型:在开始阶段和合并过程中产生的冲突——参见 Atlassian。本节将介绍两种类型以及各自的解决方法。
合并开始时
如果工作区或暂存区中存在改动,Git merge 会在开始时失败。之所以在开始阶段失败,是为了防止这些改动被即将合并进来的提交覆盖。这种情况是与本地改动冲突引起的,并非与其他分支或开发者冲突。要稳定本地状态,您可以使用 git stash、git commit、git checkout 或 git reset 等命令。
合并过程中
合并过程中失败意味着源分支与目标分支之间存在冲突,通常是因为多位开发者修改了同一个文件。如果自动合并失败,Git 会要求您手动解决问题。您也可以使用第三方工具辅助可视化并整合更改。
解决 Git 合并冲突的命令
本节将学习多种原生命令,用于可视化并解决 Git 合并冲突。
常用命令
Git status 是最常用的命令,用于显示已修改文件、暂存区和提交的状态。在合并过程中,它可用于识别有冲突的文件。
git status
带有 --merge 参数的 Git log 会列出与源分支发生冲突的提交。
git log --merge
默认情况下,git diff 会展示未提交更改与之前提交之间的差异。Git diff 可用于比较分支、提交和文件,有助于预防未来的合并冲突。
git diff
合并开始即失败时的命令
checkout 用于撤销更改或切换到新分支或旧分支。
git checkout
Git reset 用于还原工作区和暂存区中的更改。
git reset --mixed
合并过程中冲突时的命令
--abort 参数会停止合并过程,并将更改还原到合并开始前的原始状态。
git merge --abort
Git reset 通常在合并过程中使用,以将冲突文件还原到原始状态。
git reset
解决删除-修改文件冲突
当您在当前分支删除了文件,而其他人在另一个分支修改了该文件时,就会发生 Git 冲突。在这种情况下,您可以添加文件并提交,
git add <filename>
或者删除文件并提交。
git rm <filename>
📌 Git 合并冲突解决速查表
| 命令 | 说明 | 示例用法 |
|---|---|---|
git status | 显示存在合并冲突的文件 | git status |
git diff | 显示提交或分支之间的差异 | git diff HEAD |
git log --merge | 显示参与冲突的提交 | git log --merge |
git merge --abort | 取消合并并恢复到之前状态 | git merge --abort |
git reset --hard HEAD | 将分支重置到上一次提交的状态 | git reset --hard HEAD |
git checkout -- <filename> | 丢弃某个特定文件中的更改 | git checkout -- README.md |
git mergetool | 打开已配置的合并工具以解决冲突 | git mergetool |
git add <filename> | 编辑后将冲突标记为已解决 | git add README.md |
git commit -m "<message>" | 在合并冲突解决后保存更改 | git commit -m "Resolved merge conflict" |
git rebase --continue | 在解决冲突后继续被中断的变基 | git rebase --continue |
git rm <filename> | 删除在一个分支被删除、另一个分支被修改的文件 | git rm README.md |
git push | 在解决合并冲突后推送更改 | git push origin main |
可视化合并工具
合并工具是用于识别和解决各种合并冲突的用户友好型可视化工具。有些工具还支持比较变更、执行 Git 操作以及项目与仓库管理等功能。Git 合并工具分为两类:仅终端和基于 GUI。仅终端工具会在 PowerShell 或 Bash 中打开,GUI 工具则在窗口环境中打开。
要查看已安装且可用的工具列表,请使用:
git mergetool --tool-help
该列表包含所有可安装并可与 git 命令集成的有效工具。
例如,系统默认安装了 vim 和 nvim;如果您想查看未提交文件与先前提交之间的差异,请输入:
git difftool --tool=vimdiff3
vimdiff3 工具会高亮显示更改,并允许您在终端内比较各个提交。

在 vimdiff3 中比较同一文件两个版本的差异
Meld
Meld 是一款免费开源工具,可将合并冲突的解决提升到新水平。要与 Git 集成,您需要先从官网下载安装包进行安装。接着将其加入全局配置,使 Git 在默认情况下启动 Meld 来解决冲突。
下面的配置命令仅适用于 Windows 用户。对于 Mac 或 Linux,您只需将 Meld 安装文件路径改为相应系统的路径即可。
git config --global merge.tool meld
git config --global mergetool.meld.path "C:/Program Files (x86)/Meld/Meld.exe"
git config --global diff.tool meld
git config --global difftool.meld.path "C:/Program Files (x86)/Meld/Meld.exe"
设置默认工具后,您可以在 Git 本地目录中输入 git difftool 来启动 Windows 版 Meld,或者使用 git mergetool 按如下方式解决合并冲突。

使用 Meld 解决合并冲突
VSCode
VSCode 提供了最受欢迎且效果最佳的合并冲突解决方式。当 Git 无法自动合并文件时,VSCode 会高亮标出冲突代码,并提供四个选项:接受当前更改、接受传入更改、接受两者、更改对比。您可以使用这些选项清理文件,从而解决所有待处理问题。

使用 VSCode 解决合并冲突
如果您在寻找一站式 Git 操作方案,可以试试 GitKraken。它提供免费客户端和 VSCode 扩展,并内置合并冲突解决工具。
如何解决 Git 合并冲突
本节将学习如何制造一个 Git 合并冲突并将其解决。教程分为两部分:第一部分学习在本地解决 Git 冲突;第二部分介绍在远程服务器(GitHub)上解决冲突。
本地合并冲突
创建合并冲突有助于我们理解这些问题最初是如何产生的。随后,我们可以用更巧妙的方式来解决这些问题,甚至提前预防。
现在我们将创建一个包含单个文件的 Git 仓库,并完成第一次提交,开始上手。
- 创建一个名为 datacamp 的文件夹。
- 进入 datacamp 目录。
- 初始化 Git。
- 创建一个带有指定标题的
README.md文件。 - 将该文件的更改暂存并提交。
mkdir datacamp
cd datacamp
git init
echo "# How to Resolve Git Merge Conflict" > README.md
git add README.md
git commit -m "first commit"
>>> [main (root-commit) 8199ea2] first commit
>>> 1 file changed, 1 insertion(+)
>>> create mode 100644 README.md
接下来,我们将创建一个名为 readme 的新分支,并将标题从“..Git Merge..”改为“..Git..”。使用 -am 参数添加文件并创建提交。
git checkout -b readme
echo "# How to Resolve Git Conflict" > README.md
git commit -am "new branch conflict added"
>>> [readme 155f694] new branch conflict added
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
回到 main 分支,并使用 >> 向 README.md 文件添加一行。保存更改并提交后,我们就成功地在同一文件的两个版本之间制造了冲突。
git checkout main
echo "New change in base branch" >> README.md
git commit -am " a line added to base branch Readme file"
>>> [main f1f1874] a line added to base branch Readme file
>>> 1 file changed, 1 insertion(+)
可以看到,在合并 readme 分支时,Git 提示自动合并失败,需要我们手动修改并提交结果。
git merge readme
>>> Auto-merging README.md
>>> CONFLICT (content): Merge conflict in README.md
>>> Automatic merge failed; fix conflicts and then commit the result.
我们将通过在记事本中打开并编辑该文件来手动解决问题。下图展示了带有 HEAD 的箭头、分隔符,以及指向 readme 的另一个方向的箭头。HEAD 部分显示 main 分支中的现有更改,而 readme 部分是我们要合并的分支,包含不同的标题。
手动解决合并冲突
为解决问题,我们将移除 readme 分支的部分、箭头和分隔符。最终版本应当如下面所示般干净整洁。

冲突已解决
在添加文件并创建提交后,合并冲突就会得到解决。这是解决问题最常见且最简单的方法。您也可以使用集成开发环境(IDE)来更高效地解决问题。
git commit -am "conflict resolved in file README.md"
>>> [main 9994a29] conflict resolved in file README.md
远程合并冲突
要创建并解决远程合并冲突,我们需要在 GitHub 上创建一个新仓库。

在 GitHub 上创建新仓库
接着,添加远程名称(origin)和仓库地址,并使用 upstream 将本地仓库的所有更改推送到远程 main 分支。
git remote add origin https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git
git push --set-upstream origin main
>>> Enumerating objects: 12, done.
>>> Counting objects: 100% (12/12), done.
>>> Delta compression using up to 4 threads
>>> Compressing objects: 100% (6/6), done.
>>> Writing objects: 100% (12/12), 998 bytes | 499.00 KiB/s, done.
>>> Total 12 (delta 2), reused 0 (delta 0), pack-reused 0
>>> remote: Resolving deltas: 100% (2/2), done.
>>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git
>>> * [new branch] main -> main
>>> branch 'main' set up to track 'origin/main'.
为了制造冲突,我们需要同时修改远程和本地的 README.md 文件。您可以使用 GitHub 文件编辑器将“..Git merge..”改为“..Sit-Merge..”,然后提交更改。

在 GitHub 编辑器中修改
然后,在本地仓库中将 README.md 文件更改为仅包含一个简单标题,并提交更改。
echo "# How to Resolve Merge Conflicts in Git Tutorial" > README.md
git commit -am "local branch changes in README.md"
>>> [main c677a13] local branch changes in README.md
>>> 1 file changed, 1 insertion(+), 4 deletions(-)
最后,将更改推送到远程服务器。注意 Git 报错并给出了如何消除问题的提示。
git push
>>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git
>>> ! [rejected] main -> main (fetch first)
>>> error: failed to push some refs to 'https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git'
>>> hint: Updates were rejected because the remote contains work that you do
>>> hint: not have locally. This is usually caused by another repository pushing
>>> hint: to the same ref. You may want to first integrate the remote changes
>>> hint: (e.g., 'git pull ...') before pushing again.
>>> hint: See the 'Note about fast-forwards' in 'git push --help' for details.
我们将遵循最简单的提示:在推送之前先从远程服务器拉取文件。
由于 README.md 文件存在合并冲突,拉取失败。我们本可以像之前一样用记事本手动修复,这次改用可视化工具来辅助处理。
git pull
>>> remote: Enumerating objects: 5, done.
>>> remote: Counting objects: 100% (5/5), done.
>>> remote: Compressing objects: 100% (2/2), done.
>>> remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
>>> Unpacking objects: 100% (3/3), 681 bytes | 75.00 KiB/s, done.
>>> From https://github.com/kingabzpro/DataCamp-Git-Merge-Guide
>>> aaf149d..49b7d14 main -> origin/main
>>> Auto-merging README.md
>>> CONFLICT (content): Merge conflict in README.md
>>> Automatic merge failed; fix conflicts and then commit the result.
合并工具 Meld 会识别出有冲突的文件,并在 Meld 的图形界面中显示。
git mergetool
>>> Merging:
>>> README.md
>>> Normal merge conflict for 'README.md':
>>> {local}: modified file
>>> {remote}: modified file
界面有三列:README_LOCAL_473.md、README.md 和 README_LOCAL_473.md。如果您认为远程更改有效,就点击远程列中的黑色箭头;若希望保留本地更改,则点击本地列中的黑色箭头。就是这么简单。

使用 Meld 合并工具解决冲突
完成修改后,保存文件并提交。可以看到,将文件推送到远程服务器时已不再出现合并冲突错误。
git commit -am "remote main branch conflict resolved"
git push
>>> Enumerating objects: 16, done.
>>> Counting objects: 100% (16/16), done.
>>> Delta compression using up to 4 threads
>>> Compressing objects: 100% (6/6), done.
>>> Writing objects: 100% (10/10), 1.08 KiB | 550.00 KiB/s, done.
>>> Total 10 (delta 2), reused 0 (delta 0), pack-reused 0
>>> remote: Resolving deltas: 100% (2/2), completed with 1 local object.
>>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git
>>> 49b7d14..8f5c3aa main -> main
我们已经成功解决了本地与远程的合并冲突。数据科学家和机器学习工程师几乎每天都会处理这些问题。要提升您的 Git 操作技能,请参加 Introduction to Git 课程。
结语
解决 Git 合并冲突是一项复杂且高风险的任务,因为合并缺陷代码可能会破坏软件。合并工具提供了更安全、友好的环境来发现并解决合并冲突。在本教程中,我们学习了 Git 冲突为何发生以及如何解决它们,还介绍了各种合并与冲突类型、常用 Git 命令以及可视化工具。最后,我们在本地与远程仓库中分别创建并解决了一次合并冲突。
如果您刚接触 Git,想了解其工作原理,请阅读:Intro to Git and GitHub Tutorial。
作为一名持证的数据科学家,我热衷于利用前沿技术打造创新的机器学习应用。凭借在语音识别、数据分析与报告、MLOps、对话式人工智能以及自然语言处理方面的扎实背景,我不断打磨构建智能系统的能力,力求带来切实影响。除技术专长外,我也擅长沟通,能够将复杂概念提炼为清晰、简明的表述。因此,我成为数据科学领域备受关注的博主,与不断壮大的数据专业人士社区分享洞见与实践经验。目前,我专注于内容创作与编辑,借助大语言模型打造有力且吸引人的内容,帮助企业与个人更好地发挥数据价值。
FAQs
避免 Git 合并冲突的最佳实践有哪些?
要降低冲突风险:
- 在开始新工作前务必拉取最新更改(
git pull origin main)。 - 与团队沟通,避免修改同一行代码。
- 进行小而频繁的提交,而非又大又复杂的提交。
- 使用功能分支(feature branches),而不要直接向
main提交。 - 在合并前运行
git diff,及早发现潜在冲突。
不使用终端也能解决合并冲突吗?
当然!许多基于 GUI 的 Git 工具能更轻松地解决冲突:
- VS Code:用“接受传入(Accept Incoming)”与“接受当前(Accept Current)”选项高亮并处理冲突。
- GitKraken:提供可视化界面,交互式解决冲突。
- Meld / Beyond Compare:比较与解决差异的合并工具。运行
git mergetool使用已配置的可视化工具。
为什么我解决后还是不断出现合并冲突?
可能原因包括:
- 您忘了在解决后暂存(
git add)并提交(git commit -m "Resolved conflict")文件。 - 其他队友在您解决后又推送了新的冲突更改。尝试
git pull --rebase。 - 您尚未推送解决后的更改就再次合并。请务必在解决冲突后运行
git push。
如果我不小心执行了 git merge --abort,该怎么办?
如果您中止了合并但想要重试,可以:
- 直接重新运行合并命令(
git merge <branch-name>)。 - 使用
git reflog查看中止前的状态,必要时进行恢复。
如何撤销在解决合并冲突时犯下的错误?
如果您在解决冲突时犯了错误:
- 运行
git reset --hard HEAD丢弃所有更改并重新开始。 - 使用
git checkout -- <filename>将特定文件恢复到原始状态。 - 如果已经提交了错误,使用
git revert <commit-hash>创建一个新提交来撤销更改。
如何解决二进制文件中的合并冲突?
Git 无法自动合并二进制文件(如图片、PDF)。解决方法:
- 手动选择保留哪个版本并替换文件。
- 使用
git checkout --theirs <filename>或git checkout --ours <filename>保留其中一个版本。 - 提交已解决的文件(
git add <filename> && git commit -m "Resolved binary file conflict")。
git merge --abort 与 git reset --merge 有什么区别?
git merge --abort:安全地撤销一次合并,将分支恢复到合并前的状态。git reset --merge:类似,但保留已暂存文件;如果您想保留某些更改,此方法更实用。
推送到 GitHub 时出现合并冲突,应如何解决?
什么是变基冲突,该如何解决?
变基冲突是在运行 git rebase <branch> 时,变更无法干净地应用所导致。解决方法:
- 手动解决冲突后,运行
git rebase --continue。 - 若想取消变基,使用
git rebase --abort。 - 若要忽略有冲突的提交,使用
git rebase --skip。
能否通过 Git 设置在合并分支时避免冲突?
Git 具备有时能帮上忙的自动合并策略:
- 使用
git merge -X theirs <branch>可始终接受对方分支的更改。 - 使用
git merge -X ours <branch>可始终保留当前分支的更改。但此法并非万无一失,需谨慎使用。

什么是 Git 合并冲突?
Git 版本控制系统的核心在于团队协作与项目共建。开发者通常在各自独立的分支上工作,完成后再将更改合并到主分支。这种协作方式效率高、也有助于发现缺陷。有时多位开发者会修改同一行代码,当尝试合并这些更改时,就会产生冲突。
Git 冲突的简单示例
上图是典型 Git 合并冲突的完美示例。主分支中有一文件,内容为“HELLO, WORLD!”。用户名为 abid 的用户 fork 了主分支,并将文本改为“HELLO, CAT!”。与此同时,原主分支也被修改为“HELLO, DOG!”。合并这两个分支时会触发合并冲突并中止流程。
git merge命令的首要职责是合并两个分支并自动解决冲突。然而,不时会出现两人修改了同一行代码,或删除了另一位开发者仍在使用的关键文件的情况。Git 会标记这些更改并停止合并过程。在此情形下,冲突无法自动解决;开发者需要手动修改或使用工具来解决冲突。