'\r'
;LF(Line Feed) 代表换行,对应字符 '\n'
。由于历史原因,不同的操作系统文本使用的换行符各不相同。主流的操作系统一般使用CRLF或者LF作为其文本的换行符。其中,Windows 系统使用的是 CRLF, Unix系统(包括Linux, MacOS近些年的版本) 使用的是LF。如果开发人员使用 Windows 并且另一个使用 Mac 或 Linux,他们每个人都保存和提交相同的文件,他们可能会在他们的 git diff 中看到行结束更改——从 CRLF 到 LF 的转换,反之亦然。由于单字符更改,这会导致不必要的麻烦,非常烦人。
使用 core.autocrlf
在 Git 中配置行尾
可以使用core.autocrlf
配置告诉git如何处理系统上的行尾。可以通过以下命令完成:
git config --global core.autocrlf [true|false|input]
注意,false值会关闭行尾转换,这通常是不可取的,除非是团队中的每个人都使用相同的操作系统。当然,我觉得这种情况很少发生,所以慎用(除非你使用 .gitattributes 配置,在这种情况下,它会优先于你的 git 配置——稍后会详细介绍)。
所以,一般来说我们只有两个选择:autocrlf true
和 autocrlf input
。这两者有什么区别?
autocrlf true
当 autocrlf 为 true 时(git默认行为),文件将使用 git 在本地检出为 CRLF,但是每当你提交文件时,CRLF 的所有实例都将替换为 LF。基本上,此设置可确保你的代码库在所有文件的最终版本中始终使用 LF,但在获取时在本地使用 CRLF。这是 Windows 开发人员的推荐设置,因为 CRLF 是 Windows 的本机行结尾。
如果使用此选项,则每次在 Windows 上暂存文件以进行提交时可能会看到下面警告:
warning: CRLF will be replaced by LF in <file-name>.
The file will have its original line endings in your working directory.
这并不是说出现问题, Git 只是警告你,根据此设置的预期行为,你的 CRLF 行结尾将在提交时规范化为 LF。
autocrlf input
使用 autocrlf input
,文件在提交时转换为 LF,但在获取时不会转换为任何内容。因此名称为“输入”——你得到是你最初输入的内容。如果一个文件最初被 Windows 开发人员意外提交为 CRLF,你会在本地看到它是 CRLF(如果你修改它,你会强制它变成LF)。如果文件最初是作为 LF 添加的,您会看到它是LF。这通常是一件好事,因为这意味着你将始终在代码库中获得 LF 行结尾(假设你从一开始就使用它)。
input 和 true 之间的唯一区别是输入不会在本地获取时处理行尾。这是 Mac/Linux 开发人员的推荐设置,因为这些操作系统默认使用 LF。
使用 .gitattributes 在 Git 中规范行尾
在你的 repo 的根目录创建一个 .gitattributes 文件来一劳永逸地行尾不一致的问题。 Git 会读取此文件并在您本地获取或提交文件时应用其规则,确保无论每个开发人员如何在本地配置 git 或他们使用什么操作系统,都强制执行行尾约定。
一个简单的 .gitattributes 配置
这是一个 .gitattributes 文件,应该涵盖大多数用例:
# We'll let Git's auto-detection algorithm infer if a file is text. If it is,
# enforce LF line endings regardless of OS or git configurations.
* text=auto eol=lf
# Isolate binary files in case the auto-detection algorithm fails and
# marks them as text files (which could brick them).
*.{png,jpg,jpeg,gif,webp,woff,woff2} binary
提交该文件并将其推送到远程服务器。
git 使用一种简单的算法来检测你的 repo 中的特定文件是文本文件还是二进制文件(例如,可执行文件、图像或字体文件)。默认情况下,此算法用于比较已更改的文件,但它也可以用于强制行尾约定。
这就是上面配置中 text=auto
的作用——它告诉 git 应用其自动检测算法来确定文件是否是文本文件。然后, eol=lf
告诉 git 在本地获取和提交时强制执行文本文件的 LF 行结尾。这适用于 Windows 和 Linux,因为现在大多数跨平台文本编辑器都支持 LF。
Git 的自动检测算法相当准确,但如果它无法正确区分文本文件和二进制文件(如图像或字体文件),我们也可以将文件的子集显式标记为二进制文件以避免作为文本文件处理他们。这可以用下面的代码实现:
*.{png,jpg,jpeg,gif,webp,woff,woff2} binary
现在,提交此文件后,最后一步是重新规范化所有在添加 .gitattributes
之前已签入 git 的文件的所有行尾。你可以使用以下命令执行此操作:
git add --renormalize .
这会根据 .gitattributes
配置中定义的规则重新格式化所有文件。如果先前提交的文件在 git 的索引中使用 CRLF 并且由于此重新规范化而转换为 LF,则它们的行尾将在索引中更新,并且这些文件将暂存以进行提交。唯一要做的就是提交这些更改并将它们推送到远程存储库。之后引入的新文件,其行尾都将作为 LF 签入(和签出)。
Git 行尾:工作树与索引
提交这些重新规范化的文件时,您可能会看到以下消息:
warning: CRLF will be replaced by LF in <file-name>.
The file will have its original line endings in your working directory.
这是预期的行为——CRLF 将成为 Git 索引中的 LF,这意味着当你将这些文件推送到你的存储库时,它们将在你的远程代码库中具有 LF 行结尾。任何后来提取或获取该代码的人都会在本地看到 LF 行结尾。
但是 git 实际上并没有更改文件的本地文件(即其工作树中的那些)的行尾。因此,警告消息的最后一点表示刚刚重新规范化的文件仍会继续在本地使用 CRLF。
在 Git 中验证任何文件的行尾
如果想在所有这些步骤之后仔细检查 Git 索引中的文件是否使用正确的行结尾,可以运行以下命令:
git ls-files --eol
这将显示 git 正在跟踪的所有文件的行尾信息,格式如下:
i/lf w/crlf attr/text=auto eol=lf file.txt
从左到右分别是:
- i:索引中的行尾(被推送到你的仓库的行)。应该是LF。
- w:工作树中的行尾(可能是 CRLF,但如果索引是 LF 也可以)。
- attr:适用于此文件的
.gitattributes
规则。 - 文件名。
或者,你可以在将代码推送到远程后,通过在 Windows 机器上重新克隆您的存储库来仔细检查 git 是否正确规范了您的行尾。你应该看到文件的索引和工作树副本都使用 LF 而不是 CRLF(假设LF是您选择规范化行尾的方式)。
.editorconfig
文件
从技术上讲,一个 .gitattributes
文件是你执行代码库远程副本上显示的行尾所需的全部内容。但是,正如我们在上面看到的,你可能仍然会在本地看到你创建的文件的 CRLF 行结尾,因为 .gitattributes 不会告诉 git 更改文件的工作副本。
当然,这并不意味着 git 的规范化过程不起作用。但是,如果你还使用 ESLint 和 Prettier 对代码进行 linting,这可能会很烦人,在这种情况下,它们会不断抛出错误并告诉您删除那些额外的 CR.
所以,你可以使用 .editorconfig
文件更进一步;这是一个与编辑器无关的项目,旨在创建用于自定义任何给定文本编辑器行为的标准化格式。许多文本编辑器(包括 VS Code
,IDEA
,GitHub
)支持并自动读取此文件(如果存在)。你可以将这样的内容放在工作区的根目录中,你可以在这里深入了解:
root = true
[*]
end_of_line = lf
除了一堆其他设置之外,你还可以指定应用于通过此文本编辑器创建的任何新文件的行尾。这样,如果使用 VS Code 在 Windows 上创建一个新文件,你将始终在工作树中看到行结尾为 LF。
换行问题:warning Delete `␍` prettier/prettier(eslint配置的一些问题)
执行以下命令(可以自动修复这些问题):
npm run lint --fix
原因:
在window系统中,clone代码下来,会自动把换行符LF(linefeed character) (vscode 最下面可以看到)转换成回车符CRLF(carriage-return character)。这时候我们本地的代码都是回车符。
也可以在配置中取消检测
// .prettierrc
{
"endOfLine":"auto"
}
// git clone规则 关闭Git的自动转换设置
git config --global core.autocrlf false