You are about to commit CRLF line separators to the Git repository...

接手一个项目,提交代码的时候报错弹出如下提示框:

JetBrains 家的 IDE 真的很智能了,你看 Fix 按钮都给你做了。
大多数人看到这个提示框可能直接点了 Fix 按钮,但却不知道它 Fix 了什么?甚至 CRLF 是什么都不知道。

提示框内容翻译为中文如下:

您即将提交 CRLF 行分隔符到 Git 存储库,
建议将 core.autocrlf Git 属性设置为 input 以避免行分隔符问题。
如果选择 Fix and Commit,将执行 git config -global core.autocrlf input。
如果选择 Commit as Is,配置值不会改变

可以看出就是换行符导致了此问题。一般在不同操作系统进行协同开发时会出现,因为不同操作系统的换行符是不一样的。因此先要知道不同操作系统换行的组成。

CRLF

CRLF是Carriage-Return Line-Feed的缩写,意思是回车换行,就是回车(CR, ASCII 13, \r) 换行(LF, ASCII 10, \n)。换行在有的ASCII码表也用newline(简nl)来进行表示,这里的lf是line feed的概念,意思是一样的。

  • Windows 下,由 回车符 CR (0x0D) (\r) 和 换行符 LF (0x0A) (\n) 组成。
  • Linux 和 macOS 下,仅用 换行符 LF 表示换行。

为什么两类操作系统使用不同的换行

那为什么 Windows 会有回车和换行这两个概念呢?直接都用换行不就得了。

*是为了要兼容历史问题,Windows 起源于 MS-DOS, DOS 要兼容 CP/M(CP/M*世界上第一个微机操作系统),而 CP/M 考虑到兼容早期的老式机器,而老式机器换行沿用早期打字机的 CRLF 设计。 **
也就是计算机沿用了打字机的 CRLF 设计。但是那时候存储器很贵,一些人认为在每行结尾加两个字符太浪费了,留下一个就够了。这其中有人用 LF (\n),例如 Unix 。也有人用 CR (\r),例如 Mac OS 经典操作系统(Mac OS 9 以及之前)。后来 Mac OS X 也把 Mac OS 9 的规矩废除了,投奔Unix,所以改成用 LF (\n)。

两种换行导致的问题

但是两类不同系统的换行也导致了一个问题。
Unix 系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“ <回车><换行>”,即“ \r\n”;Mac系统里,每行结尾是“<回车>”。一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

而本文的问题正是因为代码是从 Windows 上拷贝到 macOS,macOS 上的换行为 LF,而 Windows 上的换行为 CRLF,提交代码就会提示 You are about to commit CRLF line separators to the Git repository

解决

Git 在维护版本库的时候统一使用的是 LF,这样就可以保证文件跨平台的时候保持一致。
在 Linux 和 macOS 下默认的换行符也是 LF,那也就不存在什么问题。
在 Windows 下默认的换行符是 CRLF,那么我们需要保证在文件提交到版本库的时候文件的换行符是 LF。

通过配置 Git 就能解决。

  • Windows 上开发

    • Git 可以在你提交时自动地把行结束符 CRLF 转换成 LF,而在签出代码时把 LF 转换成 CRLF。用 core.autocrlf 来打开此项功能,如果是在 Windows 系统上,把它设置成 true,这样当签出代码时,LF会被转换成CRLF:

      1
      $ git config --global core.autocrlf true
    • 如果你是Windows程序员,且正在开发仅运行在Windows上的项目,可以设置false取消此功能,把回车符记录在库中:

      1
      $ git config --global core.autocrlf false
  • Linux 或 macOS 上开发

    Linux 或 macOS 系统使用 LF 作为行结束符,因此你不想 Git 在签出文件时进行自动的转换;当一个以 CRLF 为行结束符的文件不小心被引入时你肯定想进行修正,把 core.autocrlf 设置成 input 来告诉 Git 在提交时把CRLF 转换成 LF,签出时不转换:

    1
    $ git config --global core.autocrlf input

You are about to commit CRLF line separators to the Git repository...

https://ganzhixiong.com/p/d81881a4/

Author

干志雄

Posted on

2022-03-19

Updated on

2022-03-19

Licensed under

Comments