<p>git merge --no-commit后手动恢复文件最可控:先执行git merge --no-commit --no-ff 分支名,再用git checkout HEAD -- 文件名保留当前分支版本,最后git commit完成合并。</p>

git merge --no-commit 后手动恢复文件最可控
合并时真正想“忽略”的,往往不是整个文件不参与合并,而是保留当前分支的版本、跳过对方分支对该文件的改动。直接用 git merge --no-commit 是最稳妥的起点——它把所有变更拉进来但不提交,给你一个窗口期做精细干预。
常见错误是合并完立刻 git checkout HEAD -- file,结果把本地未提交的修改也清掉了。正确做法是先确认你要保留的是“当前分支 HEAD 的内容”,再执行恢复:
- 执行
git merge --no-commit --no-ff feature/login - 检查哪些文件被对方改了但你不想要:
git status --porcelain | grep "^MM" - 只恢复目标文件(比如配置文件):
git checkout HEAD -- config/local.env - 确认无误后提交:
git commit -m "merge feature/login, keep local config"
这个流程不依赖全局配置,也不影响其他协作者,适合一次性、临时性的合并场景。
.gitattributes + merge=ours 针对长期固定的文件
如果某个文件(如 infostation.js、application-local.yml)在所有分支里都该保持当前分支版本,那就该用声明式策略,而不是每次手动恢复。核心是两步:定义规则 + 注册驱动。
在项目根目录创建或编辑 .gitattributes:
config/local.env merge=ours infostation.js merge=ours
然后注册 ours 合并驱动(只需一次):
- 本地生效:
git config merge.ours.driver true - 或全局生效:
git config --global merge.ours.driver true
之后只要这些文件在合并中出现冲突,Git 会自动选择“当前分支”版本,不提示、不暂停。注意:这个策略对已存在冲突的合并无效,必须在冲突发生前配置好。
别碰 .gitignore —— 它对已跟踪文件完全无效
很多人第一反应是往 .gitignore 里加 config/local.env,结果发现文件照样被合并、照样起冲突。这是因为 .gitignore 只影响“未被 Git 跟踪”的文件;一旦文件已提交过,Git 就永远把它当普通文件处理,.gitignore 对它形同虚设。
如果你真想让 Git 彻底不管这个文件,得先从历史中移除跟踪:
-
git rm --cached config/local.env(保留本地文件) - 再加进
.gitignore - 提交这次变更
但这么做意味着所有协作者都会丢失该文件的版本记录,且新克隆仓库的人根本拿不到这个文件——除非你额外提供模板或文档说明。所以它适合“纯本地、绝不共享”的文件,不适合团队共用但需差异化配置的场景。
git checkout 恢复时容易搞混的三个 HEAD 含义
执行 git checkout HEAD -- file 看似简单,但实际有三个不同语境下的 HEAD,稍不注意就选错版本:
-
HEAD:指当前分支最后一次提交的内容(最常用) -
HEAD~1:指上一次提交,即合并前的状态(适合合并后反悔) -
origin/main或feature/login:指具体分支的最新提交(适合明确要对方版本)
例如,你在 main 分支上合并 feature/login,想丢掉对方改的 infostation.js,就该用 git checkout HEAD -- infostation.js;但如果已经误提交了,就得用 git checkout HEAD~1 -- infostation.js 再 git commit --amend。混淆这两者,是恢复操作失败最常见的原因。


















