This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
all-in-kingsoft/hhs/CHORE/LF VS CRLF.md
T
2026-04-29 13:19:10 +08:00

5.1 KiB
Raw Blame History

tags, create time
tags create time
chore
git
text-formatting
cross-platform
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 说了算。这样不会因为个人偏好产生分歧。

关联笔记