Git 行尾转换

最后更新: 2026-04-29 00:23:56 +0800 +0800
原文以英文撰写。您正在阅读AI翻译版本。

Git 可以在仓库边界将文本规范化为 LF,同时在工作树中呈现 LF 或 CRLF。 稳定的 .gitattributes 策略可避免生成取决于平台的提交,并使编辑器只负责检出后的形式。

区分 HEAD、索引和工作树中的字节 #

一个被跟踪的路径有三种相关表示:

  1. HEAD 指向当前提交所存储的 blob。
  2. 索引保存拟用于下一次提交的 blob。
  3. 工作树保存供编辑器和构建工具使用的字节。

对于已规范化的文本,git add 会执行从 CRLF 到 LF 的清理转换。 检出会执行污化转换,将索引中的 LF 转换为选定的工作树行尾。现有提交不会被重写。

sh
git ls-files --eol -- path/to/file
git show HEAD:path/to/file | od -An -t x1
git check-attr -a -- path/to/file

git ls-files --eol 会报告索引、工作树和有效属性的形式。 在处理转换警告之前,应检查这些形式。

使用 .gitattributes 声明仓库策略 #

应提交属性文件,因为这样每个克隆都会共享该策略:

gitattributes
*       text=auto
*.sh    text eol=lf
*.py    text eol=lf
*.bat   text eol=crlf
*.png   binary
*.pdf   binary

text=auto 允许 Git 对未明确指定的路径进行分类。text 强制执行规范化; -text 将其禁用;binary 则是 -diff -merge -text 的内置属性宏。 显式指定 eol=lf 或 eol=crlf 会将路径标记为文本,并控制其检出形式。 应将归档文件、图像、生成的二进制格式和签名制品标记为非文本,因为转换会改变其字节。

仅将配置用作后备方案 #

core.autocrlf 和 core.eol 会影响未由属性作出更具体决定的路径:

core.autocrlf清理后写入索引从索引检出
false不执行 autocrlf 转换不执行 autocrlf 转换
inputCRLF 转换为 LFLF 保持为 LF
trueCRLF 转换为 LFLF 转换为 CRLF

core.eol 可选择 lf、crlf 或 native,用于没有显式 eol 属性的规范化文本。 core.safecrlf=true 会拒绝不可逆转换;warn 会报告这些转换。这两项设置都不能替代已提交的属性策略。

sh
git config --show-origin --get core.autocrlf
git config --show-origin --get core.eol
git config --show-origin --get core.safecrlf

安全地重新规范化 #

添加或修正属性后,应从干净的工作树开始,或先保存未提交的工作。 然后暂存一次有意为之的规范化,并检查其结果:

sh
git add --renormalize .
git diff --cached --check
git diff --cached

应将行尾规范化与语义编辑分别提交,因为单独的提交可以保证代码审查、追溯和回滚的质量。 该操作更新索引,但不会更改被忽略或未跟踪的文件。

应使编辑器设置与检出策略保持一致,尤其是对于强制使用 CRLF 的文件。 编辑器配置影响工作树中的字节,而 .gitattributes 定义版本控制的边界。 不要为了试验而对有价值的未提交文件反复执行添加和检出;应先检查有效属性并保存工作。

评论

在 GitHub 上阅读或评论(发表评论需要登录)