5.1 KiB
tags, create time
| tags | create time | ||||
|---|---|---|---|---|---|
|
2026-04-29 20:30 |
LF VS CRLF
概述
换行符是文本中最隐蔽的"地雷"。LF(\n)和 CRLF(\r\n)的选择直接影响 Git 版本控制、跨平台协作和文件处理工具的兼容性。本文从零讲透两种换行符的由来、差异以及如何在项目中统一管理。
正文
为什么会有两种换行符?
在早期计算机系统中,"换行"实际上是两个独立的动作:
| 动作 | ASCII 码 | LF | CR |
|---|---|---|---|
| Line Feed — 移到下一行开头 | 10 (\n) |
✅ | ❌ |
| Carriage Return — 光标回到行首 | 13 (\r) |
❌ | ✅ |
这源于机械打字机的操作习惯:先回车(CR),再换纸(LF)。不同系统对这两个动作的组合方式不同:
graph LR
A["UNIX / Linux / macOS"] -->|"仅 LF (\n)"| B("现代标准")
C["Windows"] -->|"CR + LF (\r\n)"| D("向后兼容")
E["Classic Mac OS (≤9)"] -->|"仅 CR (\r)"| F["已废弃"]
style B fill:#c8f7c5
style D fill:#fff3cd
style F fill:#f8d7da
思考一下:既然 Unix 系的 LF 更简洁,为什么 Windows 没有跟随统一?
因为兼容性是历史包袱——大量已有的 .txt、.doc、二进制工具都依赖 \r\n,强行更改会导致灾难性的破坏。
Git 中的自动转换(核心!)
Git 提供了一个关键配置来化解这个矛盾:core.autocrlf。这是团队协作中最需要注意的部分。
| 配置值 | 行为(检出时) | 行为(提交时) | 适用场景 |
|---|---|---|---|
true |
.gitattributes 匹配的文件从 CRLF→LF |
从 LF→CRLF | Windows 用户 |
input |
不做任何转换 | CRLF→LF | Linux/macOS 用户 |
false |
不做任何转换 | 不做任何转换 | 不推荐 |
关键点:无论你的本地系统用什么,仓库中存储的永远是 LF。这才是正确做法。
实际效果演示
假设你在 Windows 上编辑一个 Go 源文件:
# Windows 用户,core.auticrlf=true
# 本地磁盘上看到的是:
echo "hello\r\nworld\r\n" # 编辑器保存的 CRLF
# 提交时,Git 自动转换:
git add main.go # 暂存区变为 LF
# 仓库里永远是这样:
echo "hello\nworld\n" # Git 对象的纯 LF
如果你在 Linux 上克隆这个仓库,你会得到 LF;如果你在 Windows 上 clone,你会得到 CRLF(由 Git 实时转换)。所有人都不需要手动管理换行符。
常见的踩坑场景
[!WARNING] 常见陷阱 以下情况
core.autocrlf无法介入,需要你手动处理。
1. JSON / YAML 配置文件
某些格式对换行极其敏感:
{"message": "line1\nline2"} // \n 在 JSON string 中有特殊含义
如果你的 JSON 文件用 CRLF,解析器可能把 \r 当作内容的一部分,导致校验失败。
[!TIP] 建议 配置文件应始终使用 LF。在
.gitattributes中强制约束:*.json text eol=lf *.yml text eol=lf *.yaml text eol=lf
2. Shell 脚本(.sh)
Linux 上的 shebang 行必须干净:
#!/bin/bash # ⚠️ 如果这里是 \r\n,内核会找不到解释器
echo "hello" # 报错: /bin/bash^M: bad interpreter
[!TIP] 建议
- 所有 shell 脚本强制 LF,不要交给 Git 自动转换
- 在
.gitattributes中排除脚本文件的 CRLF 转换:*.sh text eol=lf ident *.bat text eol=crlf # BAT 例外,它本就运行在 Windows 上
3. 二进制文件的误判
如果一个图片/压缩包被错误标记为 text 类型,Git 会尝试转换其中的字节序列。如果恰好有连续的 0D 0A(即 \r\n),就会被篡改。
Caution
绝对不要让二进制文件经过
autocrlf或eol转换。Git 默认不会转换二进制文件,所以只需确保别手动标记成text即可。
排查与修复工具
当团队中出现换行符混用时,这些命令能快速诊断:
# 查看当前全局设置
git config --global core.autocrlf
# 找出文件中隐藏的 CRLF
git diff --check # 会在末尾标注 [tabSpace] 警告
# 一次性修复整个项目的换行符
git ls-files -z | xargs -0 sed -i 's/\r$//'
# PowerShell 快速检测
Get-Content file.txt | Format-Hex | Select-Object -First 5
# 如果看到 0D 0A 组合 → 说明是 CRLF
编辑器层面的一致性
光靠 Git 不够,编辑器也必须配合。以下是主流编辑器的推荐配置:
| 编辑器 | 配置项 | 推荐值 |
|---|---|---|
| VS Code | files.eol |
"auto"(跟随 Git 设置) |
| VS Code | files.autoTrimTrailingWhitespace |
true |
| Vim | fileformat |
unix(配合 .vimrc 固化) |
| Neovim | vim.opt.fileformat:set('unix') |
同上 |
| Sublime Text | default_line_ending |
"unix" |
[!NOTE] 最佳实践 让 Git 做唯一的决策者。编辑器设为
auto模式,Git 说了算。这样不会因为个人偏好产生分歧。