进阶教程 · Git

安全解决 Git 合并冲突

找到未合并文件,理解两边行为,逐项验证后再继续 merge 或 rebase。

Git 在同一处无法自动选择结果时会暂停操作,把决定留给人。冲突标记只指出文本重叠的位置。安全处理还要回答一个更具体的问题,主线新增了什么行为,功能分支又必须保留什么行为。

先确认当前操作类型

git status
git status --short --branch
git diff --name-only --diff-filter=U

普通 git status 会说明当前正在 merge、rebase 或 cherry-pick,这会决定继续和退出命令。短状态里的 UUAAUD 等组合都表示文件尚未合并。最后一条命令只列未解决文件。

需要查看索引中的冲突记录时,可以运行 git ls-files -u。输出里的 stage 1 是共同祖先,stage 2 和 stage 3 是参与合并的两侧版本。它能确认 Git 正在比较哪些对象,也能帮助排查文件重命名后编辑器只显示一个路径的情况。

安全解决 Git 合并冲突的入口、目标与准备条件操作示意图
图 1 · 进入任务前先确认目标、范围和准备条件

阅读冲突两边的上下文

文本冲突通常出现下面三段标记。

[标记] <<<<<<< HEAD
当前一侧的内容
[标记] =======
另一侧的内容
[标记] >>>>>>> topic

实际文件里没有方括号前缀。这里加上“标记”二字,是为了避免教程仓库把示例误判成尚未处理的冲突。

不要只删掉标记后随便留一边。先查看文件附近代码、相关调用和测试。merge 中可以运行 git log --left-right --oneline HEAD...MERGE_HEAD -- <file>,明确查看参与合并的两侧历史。rebase 中使用 git log --left-right --oneline HEAD...REBASE_HEAD -- <file>,cherry-pick 中使用 git log --left-right --oneline HEAD...CHERRY_PICK_HEAD -- <file>。配置文件冲突要核对键是否重复,业务代码冲突要检查两个分支各自修复的边界条件。重命名和删除冲突还要确认新路径是否已经接管旧入口。

可以逐个文件编辑,也可以借助合并工具。最终文件应当表达一个完整行为,不能保留冲突符号或重复实现。

有些冲突没有文本标记。双方都新增同名文件时会出现 add/add,一边删除而另一边修改时会出现 delete/modify,目录重命名还可能让文件出现在新旧路径之间。此时先决定最终文件应该存在于哪里,再处理内容。只打开带 <<<<<<< 的文件会漏掉这些状态。

生成文件与锁文件也需要追来源。若仓库规定它们由命令生成,先解决源配置,再运行项目锁定的生成命令,检查产物是否只包含预期变化。手工拼接两份锁文件容易留下重复依赖或错误校验值。

标记解决并继续

编辑完成后先检查差异,再把确认过的文件加入索引。

git diff
git add <resolved-file>
git diff --cached

所有冲突都解决后,merge 使用 git merge --continue,rebase 使用 git rebase --continue。Git 可能在下一笔提交再次停下,继续按同样顺序处理。完成以后运行 git diff --check,再执行受影响模块的测试、构建和必要的页面验收。

测试范围沿着冲突内容选择。公共函数发生冲突,运行它的单元测试并查找所有调用者。路由、权限或数据库迁移发生冲突,还要检查相邻流程和失败路径。两个分支各自测试通过,无法证明合并后的组合行为成立。

安全解决 Git 合并冲突的三步关键操作与请求骨架示意图
图 2 · 把关键操作拆成三步,并给每一步留下可观察结果

拿不准就中止当前操作

merge 中可以运行 git merge --abort,它会尝试重建 merge 开始前的状态。merge 开始前已有未提交修改时,这次重建可能失败,尤其要避免在冲突出现后继续改动原有的本地修改。开始 merge 前应先提交或妥善暂存自己的工作。rebase 中可以运行 git rebase --abort,让 HEAD 回到操作开始时的位置。退出后重新比较分支,再向相关改动的作者确认意图。

冲突解决完成只说明 Git 历史能继续。相邻功能是否仍然成立,要靠测试和真实操作确认。交付时记录冲突文件、保留的两边行为、运行过的检查和最后提交号,后来的人就能复核这次选择。

提交前再运行一次 git status --porcelain=v1 --untracked-files=allgit grep -n -E '^(<<<<<<<|=======|>>>>>>>)' -- .-E 固定使用扩展正则,避免本地 grep 配置改变竖线的含义。后一个搜索可能命中文档示例,逐条确认即可。代码中仍有冲突标记时停止提交,把对应文件重新打开处理。

安全解决 Git 合并冲突的结果验收与交付证据清单示意图
图 3 · 用结果、检查与交付证据确认任务真的完成

官方参考