引言
行尾符(Line Endings)在不同操作系统里可能不一样,比如 Windows 用 CRLF1(回车+换行),而 Linux 和 Mac 用 LF(换行)。
为什么有这样的差异?
早期的计算机使用物理打印设备作为控制台,其打印头会在磁带上打印字符,打印一行的步骤需要两步:移动打印头到磁带最右侧和上移磁带。这就对应着回车和换行,回车即回到起始位置,换行即新增一行。
Windows 遵循了这个做法,而类 Unix 系统觉得这个是一个浪费。
突然想起关于打字机的一部电影:一键成名:
如果开发者进行跨平台协作,那么在推送和拉取时会出现大量不必要的的 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 表示工作目录的行尾
④推送到远程仓库
CR → Carriage return,对应转义字符
\r
,LF → Line Feed,对应转义字符\n
。 ↩︎