快速修复
# 一键:仓库根目录加 .gitattributes 并重规范化(一劳永逸)
printf '* text=auto eol=lf\n' > .gitattributes && git add .gitattributes && git add --renormalize . && git commit -m "normalize line endings"
之后 git ls-files --eol 应显示 i/lf w/lf。
你会遇到什么
改动一行代码,git diff 却把整个文件标成修改(每行都是红+/绿-);git add 时冒 warning: LF will be replaced by CRLF(或反向 CRLF will be replaced by LF);同一仓库在 Windows 和 Linux/WSL 两边 checkout 出来"看起来一样"但 diff 永远不干净;
脚本在 Windows 上 clone 下来后报 \r 相关执行错误。
换行符策略没统一。
本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。
为什么会这样
Windows 文本默认 CRLF(\r\n),Linux/macOS 默认 LF(\n)。git 的 core.autocrlf 控制转换,而入库格式取决于首次提交时各人的配置:
| 配置 | 行为 | 适用 |
|---|---|---|
| autocrlf=false | 不做转换,CRLF 直接入库 | Windows 旧默认——跨平台仓库的坑源 |
| autocrlf=true | 提交转 LF、检出转 CRLF | Windows 推荐 |
| autocrlf=input | 提交转 LF、检出不转 | Linux 推荐 |
多人各配各的,仓库里 CRLF/LF 混合入库,就是"谁提交谁踩坑"的源头。warning: LF will be replaced by CRLF 本身无害,但出现 = 行尾策略没统一。
行尾转换发生在「写出/读入」两个方向:core.autocrlf 控制的是提交时把工作区 CRLF 转成 LF 入库、检出时按配置转回——它只改文本流的字节,不识别文件类型,所以二进制文件在 autocrlf=true 下也可能被误转(.gitattributes 的 -text 就是用来豁免的)。
仓库里最终存什么,取决于每个提交者自己的配置:autocrlf=false 的人把 CRLF 原样提交,autocrlf=true 的人提交时转 LF——同一仓库两种字节并存,git 的 diff 就会显示整行改动。
确定性推论:LF will be replaced by CRLF 警告 = 检出时发生了转换,说明配置已生效但策略未统一;跨平台仓库应该在 .gitattributes 里用 * text=auto + 显式声明(*.sh text eol=lf 等)把策略写进仓库,而不是依赖每个人的本地配置——配置是每台机器自己的,属性是跟着仓库走的。
一步步来
1. 症状无害时(只是 warning、diff 没乱) — 必做
确认全队统一 core.autocrlf(Windows 用 true,Linux/mac 用 input),warning 会消失。
2. diff 全红/已混入库(推荐,一劳永逸) — 必做
仓库根目录加 .gitattributes:
* text=auto eol=lf
然后重规范化(把历史里已入库的 CRLF 全部转成 LF):
git add .gitattributes
git add --renormalize .
git commit -m "normalize line endings"
3. 只想管特定类型 — 必做
.gitattributes 写 *.sh text eol=lf、*.bat text eol=crlf 等,其余不动。
4. 避免再犯 — 必做
新仓库先在根目录提交 .gitattributes(* text=auto)再写内容;不要用 autocrlf=false 做跨平台仓库的默认(那会把 CRLF 存进仓库)。
怎么确认修好了
入库格式统一(实测输出形态):
git ls-files --eol → 全部 i/lf w/lf,无 warning
git diff → 只显示真实改动(加 1 行只报 1 insertion,实测)其它环境的表现
| 环境 | 说明 |
|---|---|
| Windows | autocrlf=true(提交转 LF、检出转 CRLF) |
| Linux/mac | autocrlf=input |
| 已混入库 | .gitattributes + git add --renormalize .(实测修复) |
| 特定文件 | *.sh text eol=lf、*.bat text eol=crlf |
| 新仓库 | 先提交 .gitattributes 再写内容 |
症状
- 改动一行代码,
git diff却把整个文件标成修改(每行都是红+/绿-); git add时冒warning: in the working copy of 'xxx', LF will be replaced by CRLF the next time Git touches it(或反向CRLF will be replaced by LF);- 同一仓库在 Windows 和 Linux/WSL 两边 checkout 出来内容「看起来一样」但 diff 永远不干净;
- 脚本(.sh/.py)在 Windows 上 clone 下来后报
\r相关执行错误(CRLF 进入脚本)。
特征:纯文本文件;报错带「换行符」字样;Windows/Linux 双环境协作的仓库最常见。
原因
Windows 文本默认 CRLF(\r\n),Linux/macOS 默认 LF(\n)。git 的 core.autocrlf 控制转换,而入库格式取决于首次提交时各人的配置:
autocrlf=false(Windows 旧版 git 默认、很多老教程推荐):提交时不做任何转换,CRLF 直接被存进仓库——后续任何 LF 工作区一比对就全行不同,diff 全红;autocrlf=true(Windows 推荐):提交转 LF、检出转 CRLF;autocrlf=input(Linux 推荐):提交转 LF、检出不转。
多人各配各的(Windows 默认 false + Linux 默认 input 或 false),仓库里 CRLF/LF 混合入库,就是「谁提交谁踩坑」的源头。warning: LF will be replaced by CRLF 只是提示 git 会在下次操作时转换,本身无害,但它出现 = 行尾策略没统一。
解法
- 症状无害时(只是 warning、diff 没乱):确认全队统一
core.autocrlf(Windows 用true,Linux/mac 用input),warning 会消失。 - diff 全红/已混入库(推荐,一劳永逸):
仓库根目录加 .gitattributes:
* text=auto eol=lf
然后重规范化(把历史里已入库的 CRLF 全部转成 LF):
git add .gitattributes
git add --renormalize .
git commit -m "normalize line endings"
之后 git ls-files --eol 应显示 i/lf w/lf(入库/工作区都是 LF)。
- 只想管特定类型:
.gitattributes写*.sh text eol=lf、*.bat text eol=crlf等,其余不动。 - 避免再犯:新仓库先在根目录提交
.gitattributes(* text=auto)再写内容;不要用autocrlf=false做跨平台仓库的默认(那会把 CRLF 存进仓库)。
验证证据
- 本地实测(2026-08-29,WSL Ubuntu,git 2.53.0):
- 复现 1(diff 全红):
autocrlf=false提交 CRLF 文件(git ls-files --eol显示i/crlf w/crlf)→ 工作区改成 LF 后git diff把 2 行显示成 3 删 2 加(全行变化); - 复现 2(warning 正向):
autocrlf=true时 add LF 文件 →warning: in the working copy of 'lf.txt', LF will be replaced by CRLF the next time Git touches it; - 复现 3(warning 反向):
autocrlf=input时 add CRLF 文件 →warning: ... CRLF will be replaced by LF ...; - 修复:根目录
.gitattributes(* text=auto eol=lf)+git add --renormalize .→ 入库格式全部i/lf w/lf,无 warning; - 修复后 diff 只显示真实改动(加 1 行只报 1 insertion)。
- 实测复现日志(2026-08-29)
适用工具 (1)
本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。
git · 外部工具来源与证据
← 编码代理与终端 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡