冲突标记是什么
三方合并失败时,Git 会把两个版本都写进同一个文件,并用一组标记把冲突区间括起来:从 <<<<<<< 到 ======= 之间是当前分支的版本,从 ======= 到 >>>>>>> 之间是另一侧的版本。解决冲突就是把这两段人工合成一段,然后删掉全部标记。
标记里的名字代表谁
标记行后面会跟一个标识:HEAD 或分支名表示「我方」,另一侧在合并时是 MERGE_HEAD 对应的分支,在变基时则是被重放的提交来源。因为 ours 与 theirs 在合并和变基中的含义正好相反,读标记时以分支名为准,不要凭直觉判断。
基本信息
| 适用平台 | Linux / macOS / Windows(Git 2.x) |
|---|---|
| 起始标记 | <<<<<<< 后跟当前分支名或 HEAD |
| 分隔标记 | ======= 分隔两侧内容 |
| 结束标记 | >>>>>>> 后跟另一侧的分支名或提交 |
| 常见状态 | git status 显示 both modified,短格式为 UU |
| 完成条件 | 删光标记、内容合成正确,再 git add 标记已解决 |
典型使用场景
- 合并冲突:双方改了同一文件的同一区域
- 变基冲突:重放提交时与目标分支内容冲突
- 拣选冲突:把提交复制到已分叉的分支时内容不匹配
- 冲突清单:先列出所有未合并文件,再按重要度逐个处理
- 提交前扫描:用 diff --check 找出漏删的标记
- 结构冲突:一方删文件、另一方改文件,需要人工决定保留哪边
常用示例
常用示例
git status --short # 看哪些文件处于冲突状态
git diff --name-only --diff-filter=U # 只列出未合并的文件
git diff # 查看冲突区间与上下文
git checkout --ours -- config/lock.json # 整文件按我方版本解决
git checkout --theirs -- src/defaults.json # 整文件按对方版本解决
git add src/app.py # 手工解决后标记完成
git diff --check # 提交前扫描残留标记冲突标记逐行读法
| 标记 | 含义 | 怎么处理 |
|---|---|---|
| <<<<<<< HEAD | 冲突区间开始,下面是当前分支版本 | 判断这段保留哪些行 |
| ||||||| base | 公共祖先版本 | diff3 风格才有,仅供参考 |
| ======= | 两侧内容的分界 | 上半段到此结束 |
| >>>>>>> feature | 区间结束,上面是对方版本 | 标记之后内容恢复正常 |
| UU / both modified | 文件处于未解决状态 | 解决后必须 git add |
| deleted by us | 一方删除、另一方修改 | 决定保留还是删除 |
冲突范围可能来自整条分支的跨度,而不是你本地刚做的改动。先看清 scope 再动手,一次尽量只处理少量文件,避免越解决越乱。
解决完成后忘记 git add,Git 仍认为文件未解决,后续 merge --continue 或 rebase --continue 会继续报错,容易误判为命令有问题。
编辑器或 IDE 的自动保存可能在解决过程中引入整段重排,把冲突解决得看不出原样。提交前用 git diff --check 和格式化工具复核一遍。
锁文件、生成物这类「整文件以一侧为准」的冲突,直接用 git checkout --ours 或 --theirs 取一侧比手工编辑可靠,取完记得重新生成或重装依赖。
减少冲突的实操习惯
冲突无法完全避免,但可以变少:保持分支短、频繁从主干同步、避免把大范围重命名或格式重排和功能改动混在同一个提交里。改动集中在同一模块时,冲突通常只出现在几行。解决时先理解双方意图再动手,不要机械地保留某一侧,留错版本往往要等测试阶段才暴露。
删除文件引发的冲突状态是 deleted by us 或 deleted by them,处理方式是明确决定保留还是删除该文件,再分别用 git add 或 git rm 记录结果。
看不懂某段冲突的来历时,可以用 git log --merge -p <文件> 查看冲突双方的提交背景,理解为什么会出现这段差异,比只盯着标记更快找到正确解法。