治本靠 .gitattributes 而非 core.autocrlf,因其能统一跨平台换行符归一化规则;core.autocrlf 在多人协作中因各系统配置不一致导致转换错位、diff 失真、merge 冲突与 blame 失效。

多人并发修改时,CRLF/LF冲突不是“谁改错了”的问题,而是 Git 对同一文件在不同系统上做了不一致的换行符归一化动作——结果就是 diff 失真、merge 冲突爆炸、blame 失效。治本靠 .gitattributes,不是调 core.autocrlf。
为什么 core.autocrlf 在多人协作里基本失效
它只作用于单机本地,而团队里 Windows 用户设 true、Mac 用户设 input、CI 机器设 false,三者对同一个文件的“提交前转换”和“检出后还原”规则就完全错位。Git 会把 LF → CRLF(Windows 检出)、CRLF → LF(Mac 提交)、LF → 不动(CI),导致暂存区和工作区反复震荡。
- 刚
git pull完,git status就显示一堆“modified”,其实只是换行符被本地autocrlf悄悄重写了 - 两人同时改一个
.java文件,合并时 Git 认为“整段代码都变了”,因为一方是 CRLF、一方是 LF,且 Git 没法判断哪边该被归一化 -
git blame报错Number of lines annotated by Git is not equal to number of lines in the file,本质是行数统计因换行符长度差异崩了
.gitattributes 必须放在项目根目录且内容精准
这是唯一能覆盖所有开发者本地配置的强制策略。它优先级高于 core.autocrlf,Git 读到就按规则走,不看人。
- 文件名必须是
.gitattributes(不是.gitattributes.txt或其他变体) - 关键行示例:
* text=auto eol=lf—— 对所有文本文件统一提交为 LF,检出也保持 LF(跨平台安全) - 特殊文件单独声明:
*.bat text eol=crlf、*.sh text eol=lf、*.jar binary - 加
core.safecrlf = true全局配置,让 Git 在发现混合换行符时直接拒绝git add,而不是默默转掉
编辑器和格式化工具必须与 .gitattributes 对齐
VS Code、IntelliJ、WebStorm 默认可能按系统习惯写 CRLF,Prettier 默认 endOfLine: 'auto' 也会随系统变——这会直接绕过 .gitattributes 的约束。
- VS Code 用户配
"files.eol": "\n";IntelliJ 在 Settings → Editor → General → Line Separators 设为Unix and macOS (\n) - Prettier 配置里显式写
"endOfLine": "lf",别用auto - EditorConfig 文件里加
end_of_line = lf,并确保root = true - 执行一次
git add --renormalize .强制全量重走归一化,清掉历史遗留的 CRLF
CI/CD 流程里必须验换行符一致性
光靠开发机配置不可靠。每次 PR 或 push 到 main 分支前,CI 应该跑一条硬检查:
- 用
git ls-files -z | xargs -0 file | grep CRLF扫描是否混入 CRLF 文本文件 - 或用
grep -I $'\r$' $(git ls-files)直接找行尾有\r的文件 - 发现即 fail,并提示 “请检查
.gitattributes和编辑器设置” - 不要只靠
prettier --write修——它只修已跟踪文件,新加入的 .md/.yml 可能漏掉
真正麻烦的从来不是第一次配置,而是有人新拉仓库后没删掉自己机器上的 core.autocrlf = true,或者忘了关 VS Code 的“自动检测换行符”开关——这些细节一旦漏掉,就会在下次三人并发改 pom.xml 时突然引爆 merge 冲突。所以 .gitattributes 是底线,CI 检查是护栏,编辑器配置是日常习惯,三者缺一不可。











