解决 Git 冲突时,保护暂存区里的已有工作
把 Git 索引视为需要保护的状态:读取未合并阶段,只处理冲突路径,并证明其他已暂存修改保持不变。
一个仓库看起来只有普通文件冲突,实际同时保存着两类未完成工作。一份运行配置在 Git 索引中存在多个未合并条目;另一份源文件已经暂存了独立且需要保留的修改。仓库当时没有正在进行的 merge、rebase 或 cherry-pick,无法依赖某个完整操作的上下文,也没有适合直接执行的统一中止动作。
若使用范围宽泛的 reset、restore 或 checkout,状态列表可能很快变得简洁,另一份暂存工作也可能随之丢失。最终处理把索引视为需要保护的状态,只解决未合并路径,再分别验证冲突结果和原有暂存差异。任务范围没有包含 commit 与 push,因此处理在暂存区正确后结束。
状态列表里有两条独立事实
第一次检查先拆分仓库的三个视图:
HEAD:最近一次提交的快照;- index:为下一次提交准备的内容;
- working tree:当前磁盘中的文件。
Git 把 index 定义为工作树的一份已保存版本,通常称为暂存区。解决冲突时,同一路径可以在索引中同时保留多个条目。索引因此属于持久的待提交工作,不能把它当作可以随手清空的命令输出(Git 术语表)。
脱敏后的现场状态包括一份未合并的运行配置、一份独立的已暂存应用修改,且没有未暂存内容。
操作元数据缺失也是一项有效证据。索引冲突可以在外层命令或工具状态消失后继续存在;界面显示“合并更改”,也无法证明 MERGE_HEAD、rebase 元数据或 cherry-pick 序列仍然有效。此时应以索引中的真实条目为准。
选择内容前先读取未合并阶段
git ls-files --unmerged 只列出未合并路径,并显示对应阶段号。Git 文档说明,一个未合并路径最多保留三份记录:stage 1 是共同祖先,stage 2 与 stage 3 分别对应两侧内容(git-ls-files)。
git ls-files --unmerged
git show :1:file
git show :2:file
git show :3:file
“ours”和“theirs”只有在操作上下文清楚时才容易理解。rebase 等流程会让这两个称呼产生误导。逐份读取阶段内容,能够避免只凭侧别标签覆盖整份文件。
本次处理中,一侧的若干设置已经完整存在于另一侧。最终结果保留完整配置块与有用注释,同时清除冲突标记和重复键。敏感值只在本地比较,没有进入审查说明或公开证据。
修改单一路径前先保护索引
编辑前,流程只读记录了暂存文件清单和那份独立暂存差异,为后续比较建立基准:
git diff --cached --name-status
git diff --cached -- file
Git 文档说明,git diff --cached 比较 index 与 HEAD,展示下一次提交将包含的内容,不会把后续未暂存编辑混进来(git-diff)。
随后只修改冲突文件。确认目标内容后,用路径限定命令把该文件的多阶段条目替换为工作树中的解决结果:
git add -- conflicted-file
git add 会使用指定路径的当前内容更新 index。这里的路径范围就是安全边界:它只把这一处标记为已解决,不会顺带暂存仓库里的全部修改(git-add)。
这次处理不需要 git add -A、全仓库 restore 或 reset。它们会把修改范围扩大到尚未建立目标内容的其他路径。
验证要同时证明解决与保留
未合并列表为空,只能证明 Git 不再保存冲突阶段;它无法证明选择的内容正确,也无法证明原有暂存工作仍在。最终检查同时覆盖三类结论:
git ls-files --unmerged不再返回路径;- 对解决后的文件执行冲突标记字面扫描,结果为空;
- 每个应生效的配置键只出现一次;
git diff --cached --name-status仍恰好列出解决路径和此前已暂存路径;- 独立暂存差异与编辑前保存的只读结果一致;
git diff --cached --check通过。
最后一条命令会检查新引入的冲突标记与空白错误,发现问题时返回非零状态(git-diff)。它适合作为末端门禁,但无法判断某个业务配置是否应该保留。内容选择仍需结合三个阶段和文件上下文人工确认。
本次范围明确止于暂存区。提交和推送会改变本地历史与远端状态,需要单独授权,不能由“冲突已经解决”自动推导出来。
宽范围恢复命令为什么危险
很多 Git 恢复步骤默认 index 中只有本次失败操作产生的内容。本次现场不符合这一假设:独立源文件中的暂存修改属于有效工作,必须完整保留。
更安全的顺序是先清点 HEAD、index 与 working tree,再识别未合并路径和操作元数据,读取单个冲突路径的阶段内容,只编辑并暂存该路径,最后用初始清单复核完整 index。
这套顺序也适用于文件更多的仓库。团队越依赖部分暂存、IDE Git 集成和长期本地工作,把整个 index 当作临时冲突残留的风险就越高。
适用边界
二进制冲突、重命名与删除冲突、子模块条目和生成文件无法只靠文本对比解决,需要按文件类型补充验证。换行转换与 clean/smudge filter 还可能让工作树字节和索引字节不同;要求精确保留时,应以 Git 保存的索引视图完成最终比较。
冲突内容若包含凭据或内部地址,不应把三个阶段原文粘贴到 Issue、聊天或 CI 日志。敏感值留在本地比较,公开记录只保留中性结论。现有证据无法确定目标版本时,应让路径继续保持未合并,并请求内容所有者确认。
可复用结论是把 index 当作一份有独立责任边界的待提交快照:先清点,再处理范围最小且已经确认的路径;只有冲突消失、全部无关暂存修改也保持原状,处理才真正完成。
先说明系统,再说明症状
如果需要生产排障、DevOps 交付或物流系统集成协作,请提供当前表现、预期结果、受影响环境、可用日志或数据样例,以及发布限制。我会从现有证据开始判断。
通过邮件开始