Git 换行符 LF 和 CRLF 的自动转换
Git 换行符 LF 和 CRLF 的自动转换
为什么需要关心换行符
不同操作系统使用不同的字符表示文本行的结束:
- LF (
\n):Linux、macOS 以及现代 macOS 的默认换行符。 - CRLF (
\r\n):Windows 的默认换行符。
当开发团队跨平台协作,或者项目同时包含 Windows 和 Unix 类系统的文件时,不一致的换行符会导致:
- 版本差异里出现大量无意义的“整行修改”。
- 脚本、配置文件在错误的环境下执行失败。
- 代码审查(Code Review)难以聚焦实际逻辑变更。
Git 提供了一套自动转换机制,可以在提交时将 CRLF 转为 LF,在检出时将 LF 转为 CRLF,从而保证仓库内部统一使用 LF,而工作区适配本地操作系统。
核心配置:core.autocrlf
通过设置 core.autocrlf,Git 会在文件的提交和检出过程中自动处理换行符。该配置有三个值:
| 配置值 | 提交时(工作区 → 仓库) | 检出时(仓库 → 工作区) | 适用场景 |
|---|---|---|---|
true |
将 CRLF 转换为 LF |
将 LF 转换为 CRLF |
Windows 开发者的推荐设置 |
input |
将 CRLF 转换为 LF |
不做转换,保留 LF |
Linux/macOS 开发者,或跨平台项目希望工作区保持 LF 的场景 |
false |
不做任何转换 | 不做任何转换 | 项目完全由特定操作系统开发,或对换行符有严格保留要求的场景(如二进制文件) |
设置方式(全局或针对单个仓库):
# 全局设置(推荐 Windows 用户)
git config --global core.autocrlf true
# 全局设置(推荐 Linux/macOS 用户)
git config --global core.autocrlf input
# 仅当前仓库关闭自动转换
git config core.autocrlf false
三种模式的行为细节
true:Git 会认为所有文本文件在检出时应使用CRLF,提交时统一转为LF。这个设置对 Windows 用户最友好,避免因编辑器的自动换行符而引入冲突。input:无论工作区文件是LF还是CRLF,提交时一律转为LF;检出时不做转换。如果开发者使用支持LF的编辑器(如 VS Code、Sublime、Vim),且希望仓库内外都保持LF,这是合适的选择。false:Git 完全不干预换行符,文件原样提交、原样检出。如果团队所有成员都在同一操作系统上工作,且已统一编辑器换行符设置,可以使用此选项。但通常不推荐,因为它放弃了 Git 提供的跨平台保护。
更精细的控制:.gitattributes
core.autocrlf 是全局或仓库级别的“一刀切”设置,无法区分文件类型。.gitattributes 文件则允许你为不同文件或文件类型单独指定换行符转换规则,并且该配置会随仓库传播,确保所有协作者行为一致。
常用属性
text=auto:让 Git 自动检测文件是否为文本。对检测为文本的文件执行换行符规范化(提交时转LF,检出时按core.eol或操作系统转换)。对二进制文件不转换。text:强制标记为文本文件,提交时统一为LF。text eol=lf:提交和检出都强制使用LF。工作区文件也将是LF。text eol=crlf:提交时转LF,检出时强制使用CRLF。-text:取消所有换行符转换,文件被视为二进制,原样提交和检出。binary:-text -diff的别名,标记为二进制文件,既不进行换行符转换,也不生成文本差异。
实战示例
在仓库根目录创建 .gitattributes 文件:
# 所有文件默认自动检测,文本文件规范化
* text=auto
# 明确指定源代码文件使用 LF,即使在 Windows 上检出也保持 LF
*.js text eol=lf
*.ts text eol=lf
*.py text eol=lf
*.sh text eol=lf
# Windows 特有的批处理文件必须使用 CRLF
*.bat text eol=crlf
*.cmd text eol=crlf
# 图片、字体等二进制文件不转换
*.png binary
*.jpg binary
*.woff2 binary
设置完成后,需要将 .gitattributes 文件提交到仓库。该文件对所有克隆仓库的开发者立即生效,优先级高于 core.autocrlf。
如果只想对部分文件重新归一化换行符,可以使用:
# 将所有匹配 *.txt 的文件重新用 LF 标准化
git add --renormalize .
查看当前工作区换行符状态
有时需要确认文件实际使用的换行符,或者排查未预期的转换。常用方法:
- 用
file命令检测(Linux/macOS):file your-file.txt会显示with CRLF line terminators或with LF line terminators。 - 用
cat -A查看行尾字符:cat -A your-file,行尾显示$表示 LF,^M$表示 CRLF。 - 用 Git 查看差异时注意
^M:执行git diff,如果看到行尾有^M字符,说明文件包含 CRLF,但 Git 预期是 LF。 - 检查 Git 生效的配置:
git config core.autocrlf以及git check-attr text your-file可以查看.gitattributes对特定文件的效果。
常见问题与排查
问题:提交后 Git 状态仍显示文件已修改(即使未编辑)
这通常是因为工作区文件换行符与仓库索引中记录的不一致,且 Git 转换规则导致持续变化。 解决方案:
- 确保
.gitattributes或core.autocrlf配置正确。 - 运行
git rm --cached -r .(谨慎操作,会清空暂存区),然后git add --all。这会强制重新添加所有文件,让 Git 应用当前转换规则进行归一化。 - 提交归一化结果。
问题:在 Windows 检出后脚本无法在 WSL 或 Docker 中运行
很可能脚本被转换为了 CRLF,而 Linux 解释器要求 LF。
解决方案:在 .gitattributes 中强制该类脚本使用 eol=lf,例如:
*.sh text eol=lf
问题:.gitattributes 中添加了 * text=auto,但某些文件没被识别为文本
Git 使用类似 file 命令的启发式方法判断二进制内容。如果文件开头包含大量非 ASCII 字节,可能被误判。可以通过显式指定 text 来覆盖:
/my-data.csv text
问题:不小心把二进制文件提交成了文本并损坏了内容
二进制文件(如图片)如果被当作文本进行换行符转换,会破坏内容。务必在 .gitattributes 中为它们设置 binary 或 -text。
最佳实践:从混乱到一致
- 在项目初期就加入
.gitattributes文件,并提交到仓库。这是团队协作中处理换行符最可靠的方式。 - 推荐配置组合:
- 所有仓库包含
.gitattributes:* text=auto。 - Windows 开发者:
git config --global core.autocrlf true。 - Linux/macOS 开发者:
git config --global core.autocrlf input。
- 所有仓库包含
- 编辑器统一配置:建议成员将编辑器默认换行符设置为
LF(VS Code、JetBrains 系列等均支持),并开启“保存时自动去除行尾空白”。从源头减少混乱。 - 避免在仓库中存在混合换行符:一旦出现,立即通过归一化提交解决,不要让不一致蔓延。
- CI 检查:可以在持续集成中运行
git diff --check,它会检测空白字符错误,包括 CRLF,提前阻断问题。
总结
- Git 通过
core.autocrlf和.gitattributes解决跨平台换行符混乱。 core.autocrlf提供三种模式:true(Windows 友好)、input(Unix 友好)、false(不转换)。.gitattributes提供文件级别的精细控制,是团队协作的最佳选择。- 正确配置后,开发者在各自系统上都能舒适地工作,仓库内部始终保持干净的 LF 历史。规范化换行符是构建可持续、多平台项目的基础步骤。