了解与配置 Git autocrlf 文本换行符处理

计算机目前有两个文本换行符的事实标准。涉及两个字符:

  • CR Carriage Return 回车符。转义符 \r ASCII 码 13 (0x0D)
  • LF Line Feed 换行符。转义符 \n ASCII 码 10 (0x0A)

顾名思义,这是古早打字机时期流传下来的控制指令。

用法上:

  • Windows 采用 CRLF 两个字符做行尾,最大程度照顾兼容性。
  • Linux/macOS 采用 LF。其中 macOS 自 2001 年起从 CR 改为 LF

Git 默认使用 LF,即:文本文件检入至仓库时(checkin)换行符使用 LF,检出至工作目录时(checkout)换行符使用 LF

这跟 Windows 的默认值不同,需要处理。Git 提供了一些相关配置项。

首先,Git 只对文本文件做修改 。那么首先要标记或检测一个文件是否为文本文件。这是 .gitattributes 的用途(之一)。

这个片段简要说明其用法:

.gitattributes 复制代码
# auto detect, not mark as text unconditionally
*           text=auto

*.c         text
*.cpp       text

# binary = -text -diff
*.exe       binary
*.lib       binary
*.obj       binary

.gitattributes 可以是仓库级配置,置于仓库根目录;也可以是用户级配置,位置和命名跟 .gitconfig 相同($HOME/.gitattributes $HOME/.config/git/attributes)。

.gitattributes 自上而下后者覆盖前者、仓库级覆盖用户级

其次,Git 会修改文本文件的换行符(End of Line,EOL)和文本编码(Text Encoding)。当然本文只关心换行符。

autocrlf 取值及效果如下所示:

  • $autocrlf=false : checkout as-is, checkin as-is
  • $autocrlf=input : checkout as-is, checkin eol=lf
  • $autocrlf=true : checkout $eol, checkin eol=lf

EOL 取值如下所示:

  • $eol=native : platform preference
  • $eol=lf
  • $eol=crlf

还挺清晰,对吗?考虑考虑下面两种情形:

  1. 检入了文件,文件 eol=crlf
  2. 文本文件的不同的行混用了 crlf lf

#1 很常见,尤其是下载使用他人的代码仓库的时候。这时,如果将其作为文本文件,那么检出时就会遵循 autocrlf,如果配置是 input or true,那么 git diff 全文件每行都不匹配,因为再次检入就会改成 eol=lf 了。

针对这种情况,Git attribute text 的自动检测写法 text=auto 能处理好:

  • text 显式标记为文本文件,处理视同 autocrlf=true
  • text=auto 自动检测是否为文本文件。如果是文本,处理视同 autocrlf=true
    • 特殊情况:如果是文本、已检入过 eol=crlf,处理视同 autocrlf=false

因此 .gitattributes 最佳写法是:

.gitattributes 复制代码
*.c         text=auto eol=native
*.cpp       text=auto eol=native

为何这么做好呢?因为你不是原仓库的唯一所有人,避免破坏原仓库文件 eol 可以避免合并冲突。

可以使用如下命令观察当前状态:

bash 复制代码
> git ls-files --eol a-file-whose-eol-is-crlf
i/crlf    w/crlf    attr/text          a-file-whose-eol-is-crlf

如果你只是仓库消费者,最简单做法是 .gitattributes 写成这样:

.gitattributes 复制代码
*.c         -text eol=input autocrlf=false

如果你是唯一所有人,那么你可以将全量扫描并统一 eol:

bash 复制代码
git add --renormalize .

茴字的另一种写法:

bash 复制代码
git filter-branch --tree-filter 'find . -type f -exec dos2unix {} \;' -- --all

autocrlf eol 不仅可以在 .gitattributes 中配置,还有 .gitconfig 内的一组配置项:

  • core.autocrlf 文本文件处理时的默认值
  • core.eol 默认 =native 所以一般无需配置
  • core.safecrlf 如果要发生不可逆的转换,则 =true 阻止;=warn 发出警告

临了,发现隔壁也有一篇参考文档 Git 优雅处理行结束符,也可看看。

相关推荐
scoone4 分钟前
VSCode 中 Git 功能比较:内置 Git、GitLens 与 Git History 插件
ide·git·vscode
赛博末影猫40 分钟前
git全教程(长期更新)
git
Y编程小白1 小时前
Git版本控制工具--基础命令和分支管理
大数据·git·elasticsearch
只抄2 小时前
Windows “高性能”模式既不高效,也不节能?
windows
Pafey5 小时前
git 删除鉴权缓存及账号信息
git·缓存
databook7 小时前
解锁 Git Log 更多实用技巧
git
wang_yb7 小时前
解锁 Git Log 更多实用技巧
git·databook
树懒_Zz8 小时前
记录 io.springfox 3.0.0 整合 spring boot 2.6.x 由于 springfox bug 引发问题
windows·spring boot·bug
花花鱼9 小时前
VSCode中鼠标指针消失的原因及解决方法
ide·windows·vscode·编辑器