Git:autocrlf=true core.eol=native 与 autocrlf=input 的区别

11

有人能解释一下设置之间的区别吗:

core.autocrlf = true

core.eol = native

并且

core.autocrlf = input

我们什么时候使用这两种情况?

2个回答

15

我们应该在何时使用其中之一?

我的偏好是从不使用。另一方面,我也不使用Windows。 :-) 但是,如果你阅读下面的所有文本,你会看到即使我在使用Windows,我仍会说“永远不要使用”。(即使你正在共享某个上游存储库,你不允许创建.gitattributes文件,你也可以在自己的克隆中使用每个存储库$GIT_DIR/info/attributes文件。)

[它们之间有什么区别?]

要了解区别,我们需要首先注意:

  • 转换是什么?Git可以进行哪些转换?
  • Git何时可以进行转换?Git 何时进行转换?
  • Git如何确定文件是“文本”?

转换、输入和输出:清理和模糊

第一部分非常简单,尽管对于新手来说可能会有一些障碍。Git可以执行任何你想要的转换,因为它有Git称之为清理过滤器模糊过滤器

清理过滤器是你自己可以编写的转换,当你使用git add或等效命令将文件从工作区复制到索引中时,Git将应用这些转换。也就是说,假设你已经将文件检出到了工作区,并对其进行了编辑、替换或运行某个程序对其进行更改。你可能想提交该文件的新版本。所以你必须运行git add path来将文件从工作区复制回索引。(记住,Git从索引中的内容创建新的提交,而不是从工作区中的内容创建。这就是为什么你一直都要git add文件:Git不会自动从工作区复制到索引中。)

每当你运行git add file时,Git都会在文件进入时“清理”它。这是一个输入转换

相反地,你可以编写自己的“smudge filter”,这是在文件数据从Git(即从索引中到达工作树)“出”时所执行的操作。由于Git内部的所有文件都处于一些特殊的、内部的、仅限于Git的格式中,包括那些在索引中准备复制到下一个提交中的文件,因此每个文件都必须转换为所有常规计算机程序都可以处理的正常格式。每当你将文件提取到工作树时,Git都会在输出时“涂污”(弄脏)文件。这是一种输出转换。
Git有时会进行输入转换,而不实际将文件复制到索引中:特别是,如果你运行一个git diff,需要将工作树文件与相同文件的索引或提交副本进行比较,则存储库中的文件已经被“清洗”,而工作树中的文件则都是“涂污”的和“脏”的。它们不能进行比较,直到它们处于相同的状态,因此Git会在执行diff之前“清理”工作树中的文件。
Git有两种内置转换。一种用于清理,即当文件从工作树复制到Git(到索引)时使用,它将CRLF换行符替换为只有换行符的Linux风格的换行符。另一种用于涂污,即从Git复制文件时使用。它将仅有换行符的Linux风格的换行符替换为......呃,某种东西。
这个“某种东西”就是core.eol的作用。你可以让Git用CRLF替换换行符,如果你在Windows上并且你有要求行以CRLF结束的程序,但你也正在与在要求行以LF-Only换行符样式结尾的Linux上工作的人合作,那么你也可以使用这个选项。
或者,你可以让Git使用LF-Only替换换行符......除了这不是一种“替换”,因为换行符实际就是一个换行符“LF”字符。这有点傻,把它称为替代品。
你可以让Git基于你所用的系统选择结尾,这样一个配置,其中core.eol设置为native,可以在Linux和Windows上都可用。

Git在将LF替换为LF(实际上并不是替换)时,会有一些诡异的行为:它倾向于什么都不做,甚至不去检查任何东西,从而运行更快。如果设置了core.safecrlf选项,Git就需要检查文件,并涉及到一些猜测。这个safecrlf选项是为了过度保护和防止对二进制文件造成损坏,因此如果你要进行转换,你需要设置好.gitattributes

二进制文件:Git如何判断一个文件是否为文本?

有些文件,比如.jpg图片文件,根本不是文本文件,不应该以“文本”方式修改其中的任何数据。它们需要用图像处理代码来操作,而不是使用文本编辑器或者类似Git内置转换的笨拙工具。因此,Git需要一种区分文本文件和非文本或者二进制文件的方法。

如果你没有告诉Git哪些文件是哪些,它就必须猜测。Git用于猜测的方法不是查看文件扩展名,例如.jpg或者.txt。这种方法对于名称为README的文件就不起作用。相反,Git查看文件中存储的数据,并根据数据是否“看起来像文本”或“看起来像二进制”进行猜测。

可以想象,这种猜测游戏并不完美。它可能适用于你,但如果不适用,你可以并且应该告诉 Git哪些文件是哪些。你可以通过创建一个名为.gitattributes的文件来实现这一点。在.gitattributes中,你可以列出特定的文件名例如README,或者路径名模式例如*.txt*.jpg,它们被认为是“绝对的文本”或“绝对的二进制”。你可以使用text-text来指定。你也可以告诉 Git:自动猜测! 这可以使用auto来实现:

*.txt   text
*.jpg   -text
guess   auto

如果可以避免,就不要使用auto

如果你从不让Git进行任何转换,那么你无需这样做。告诉Git哪些文件是文本文件,哪些是二进制文件,是为了确保Git正确地进行转换,只有当你需要进行转换时才需要这样做。因此,如果你避免使用Windows,就无需创建.gitattributes并列出你的文件。但创建它并不会真正造成伤害,如果你确实创建了它,应该尽量使其涵盖所有文件,以便Git不必猜测。

现在我们知道了这些,我们可以理解文档了

有了上述内容,我们可以查看git config文档以了解core.autocrlf的作用,并向下滚动到core.autocrlf描述的部分:

将此变量设置为“true”与在所有文件上设置“text”属性为“auto”和core.eol为“crlf”相同。 如果想在当前工作目录中使用CRLF行结束符且存储库使用LF行结束符,则设置为true。此变量可以设置为“input”,此时不执行输出转换。

换句话说,core.autocrlf=true就像在所有文件上使用auto设置一样,这是你应该避免的。因此,你不应该使用它 :-) 它可能会起作用,但我不建议这样做:创建一个正确的.gitattributes并在其中列出所有文件,以便你不必猜测。一旦你的.gitattributes文件列出了所有内容,core.autocrlf=true就没有任何效果,因为.gitattributes设置将覆盖它。

使用core.autocrlf=input告诉Git进行相同的猜测,但仅进行输入转换(例如,在git add清理期间)。我自己不需要此设置,并且无法真正想象任何情况下使用它是个好主意。这样的情况可能存在,但如果要进行转换,应该明确指定它们;一旦你在.gitattributes文件中正确地指定了它们,似乎更有意义同时进行双向转换,因此没有使用input的理由。

至于将core.eol设置为native,文档声称这是默认值(似乎是最好的选择),因此除了覆盖其他配置文件的不良非默认设置之外,没有理由去麻烦它。


2

1
我在混合环境中使用这些设置已经工作了10多年,从未遇到过问题。- 那你的工作经验就太有限了。试试在Windows机器上使用一个明确期望显式LF的系统(任何WSL、docker化或nx-shell为基础的系统),然后再使用autocrlf true。你将会获得一种你在过去10多年中可能没有体验到的经历。提示:即使是简单的shell脚本在shebang中也会因为CRLF而出错,并且你将以那个特定的设置将它们存储(和处理)在你的文件系统中。 - spamove

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接