Bootstrap

Git 中行尾符 LF 和 CRLF 的转换问题处理方法

引言

行尾符(Line Endings)在不同操作系统里可能不一样,比如 Windows 用 CRLF1(回车+换行),而 Linux 和 Mac 用 LF(换行)。

为什么有这样的差异?

早期的计算机使用物理打印设备作为控制台,其打印头会在磁带上打印字符,打印一行的步骤需要两步:移动打印头到磁带最右侧和上移磁带。这就对应着回车和换行,回车即回到起始位置,换行即新增一行。

img

Windows 遵循了这个做法,而类 Unix 系统觉得这个是一个浪费。

突然想起关于打字机的一部电影:一键成名

img

如果开发者进行跨平台协作,那么在推送和拉取时会出现大量不必要的的 diff 差异。

可以按照以下方式配置 Git 自动处理行尾符。

法1:配置 core.autocrlf

通过设置 Git 配置项 core.autocrlf 可以自动处理 LF 和 CRLF 之间的转换,但是这个只适合个人开发使用,并且有许多弊端,例如可能会损坏二进制文件(如图片),这取决于 Git 怎么识别文件类型(设置方法见后一节)。

Windows 用户:设置 Git 在提交时自动将 CRLF 转换为 LF,检出时转换为 CRLF:

# 单项目配置
git config core.autocrlf true

# 全局配置
git config --global core.autocrlf true

配置后,推送时可能会有提示“LF will be replaced by CRLF the next time Git touches it”。

Linux/Mac 用户:设置 Git 在提交时自动将 CRLF 转换为 LF,但不用修改检出文件,保持原样即可:

git config --global core.autocrlf input

法2:修改 Git 属性(attributes)

(团队开发适合该方法)

Git 属性是针对某些路径和某类型文件设置的一系列行为规则,包括将某类文件识别为二进制文件、将二进制文件转为文本格式、合并策略、关键字展开以及换行符的转换规则,具体可参考Git 属性 – Pro Git 2。具体在.git/info/attributes或根目录下的.gitattributes文件里设置(文件不存在就新建,一般选择后者)。

使用 .gitattribute 文件的流程如下:

①在项目根目录下创建 .gitattributes

# 所有文件自动使用 LF 行尾符
* text=auto eol=lf

# 标记二进制文件,避免换行符转换
*.png binary
*.zip binary
...

②本地应用属性到所有文件

git add --renormalize .

# 或者

git rm --cached -r . # 取消追踪所有文件
git reset --hard  # 回退到上次提交的状态

③检测

# 检查某个文件的 Git 属性
$ git check-attr -a -- <file>

# 查看已跟踪文件的行尾
$ git ls-files --eol
i/lf    w/crlf  attr/text=auto   crlf.txt # i 表示索引中的行尾, w 表示工作目录的行尾

④推送到远程仓库


  1. CR → Carriage return,对应转义字符 \r,LF → Line Feed,对应转义字符 \n↩︎

;