.gitattributes中`*text = auto`和`*text eol = lf`之间的差异是什么?

Mar*_* An 4 git gitattributes core.autocrlf

我一遍又一遍地看着.gitattributes的文档,但我找不到这两者之间的差异的明确答案:

* text=auto

* text eol=lf

text=auto仅用于*或者也可以与特定扩展一起使用?在这种情况下,有什么不同?

*.txt text=auto

*.txt text eol=lf

tor*_*rek 10

TL; DR

eol=lf设置将覆盖任何text设置,并且由于您已选择将其应用于每个路径,因此eol=lf如果您使用该设置,则只有该设置才有意义.

完整的解释

让我们从这开始,向外工作:

text=auto仅用于*或者也可以与特定扩展一起使用?

模式可能包括扩展.该text=auto部分是属性设置,并且模式选择要应用于哪个文件的属性.

Git如何读取.gitattributes文件

在每一行.gitattributes匹配或不匹配,一些道路名称,如dir1/dir2/file.extREADME.md或什么的.正如gitattributes文档所说:

gitattributes文件中的每一行都是以下形式:

pattern attr1 attr2 ...
Run Code Online (Sandbox Code Playgroud)

也就是说,一个模式后跟一个属性列表,用空格分隔.前导空格和尾随空格被忽略.以#开头的行将被忽略.以双引号开头的模式以C风格引用.当模式匹配相关路径时,该行上列出的属性将被赋予路径.

因此,*模式.这些"模式" .gitignore文件中的模式相同,只是不允许使用负模式.因此,您可以使用类似*.txt*.jpg匹配文件扩展名的模式,或dir1/*匹配特定目录中的文件之类的模式(尽管还有另一种方法:.gitignore文件,.gitattributes每个目录可以有文件,在这种情况下它们适用于该dierctory及其子目录中的文件,但不包括树中较高的路径).

现在,对于textvs text=auto,eol=lf无论是否,我们发现以下内容:

对于给定路径,每个属性可以处于以下状态之一:

  • 该路径具有特殊值"true"的属性; 这是通过仅列出属性列表中属性的名称来指定的.

  • 取消设置[细节剪切,但见下文]

  • 设置为值

    该路径具有指定字符串值的属性; 这是通过在属性列表中列出属性的名称,后跟等号=及其值来指定的.

  • 不明

    没有模式匹配路径,没有任何说明路径是否具有属性,路径的属性被称为未指定.

(在我看来,这最后一个的措辞特别差.它的确意味着"所有与路径匹配的模式,没有人对此属性说了什么.")

因此text,对于属性设置,并且对于text=auto,属性设置为值.在这种情况下的价值部分是auto.由于模式是*,它适用于所有文件.

同样的逻辑适用于该eol=lf项目.如果,首先,这eol=lf发生在某种模式中,其次,该模式与所讨论的文件匹配,则该eol属性设置为值,值为lf.由于您的建议行是* text eol=lf,这将eol设置为一个值,并将text 设置,但不设置为值.

如果在单个.gitattributes文件中编写两个行序列:

* text=auto
* text eol=elf
Run Code Online (Sandbox Code Playgroud)

第二行text覆盖第一行,因此text设置(但不是值)并eol设置为值,值为lf.两条线匹配,第二条线覆盖第一条线.

如果你颠倒两行:

* text eol=lf
* text=auto
Run Code Online (Sandbox Code Playgroud)

然后两行匹配,但现在第二行只覆盖text设置,所以现在你已经text设置为autoeol设置为lf.

text属性如何应用于文件

gitattributes文档的下一部分说:

此属性[ text]启用并控制行尾标准化.... [如果是]

  • 设置...启用行尾标准化并将路径标记为文本文件...

  • 取消设置...告诉Git在签入或结账时不要尝试任何行尾转换...

  • 设置为字符串值"auto"...如果Git决定内容是文本...

  • 未指定... Git使用core.autocrlf配置变量...

(这意味着你必须去追逐git config文档,找出core.autocrlf做,如果你离开text不明).

您已选择为每个文件设置它,或者为每个文件设置它auto.前者意味着"为每个文件做转换",后者 - auto设置 - 意味着:嘿,Git,请为我决定文件是否是文本.如果您确定它是文本,请执行转换.

如何eol=lf应用于文件

text设置描述的正下方是设置的描述eol:

此属性设置要在工作目录中使用的特定行结束样式.它可以在没有任何内容检查的情况下实现行尾转换,从而有效地设置text属性.

  • 设置为字符串值"crlf"... [剪切因为你设置lf]

  • 设置为字符串值"lf"

    此设置强制Git在签入时将行结尾标准化为LF,并在签出文件时阻止转换为CRLF.

所以,如果你eol=lf设置了一个路径 - 并且*作为模式,它将为每个路径设置- Git会将每个文件视为文本,并在"checkin"中从CR-LF行结尾转换为仅LF行结尾"(这是严厉措辞,再次:转换实际上发生在git add步骤中).Git在结账时不会做任何事情(这也不是完美的措辞:转换 - 或者在这种情况下,非转换 - 在从索引提取到工作树期间发生).

如果使用不同的模式,则会得到不同的结果

请注意,如果选择类似的模式*.txt,则仅为与模式匹配的路径设置这些属性.对于其他路径,这些属性仍未设置.因此,您应该回顾一下文档,看看当这些属性未设置时会发生什么.

当然,你可以这样做:

* -text
*.txt eol=lf
Run Code Online (Sandbox Code Playgroud)

第一行将在所有文件上显式取消设置, text在所有文件上保留eol未指定.然后第二行设置 eol=lf*.txt文件的值,覆盖未指定的值.现在Git将eol=lf规则应用于名称匹配的所有文件*.txt,并对所有剩余文件使用unspecified-eol和unset-text规则.

这个特殊的-text语法是我上面提到的东西.使用text=false 不会取消设置text:它将textset设置为字符串值false.这与text未指定(未特别设置)具有相同的效果.使用-text给它特殊的未设置设置.

设置 text未指定 之间的区别在于text,当text未指定时,Git可以尝试基于设置进行猜测,core.*例如core.autocrlf是否进行转换.什么时候text特别没有设置,Git不会做任何猜测:它根本不会对该文件进行任何转换.

  • @BrunoGomes:这非常混乱,并且与版本相关,因为 Git 2.10(2016 年 9 月)中修复了一个错误。我在编写答案时使用的文档仍然引用了 2.10 之前的行为。我会尽快更新这个答案,但这确实很难描述,因为每五个 Git 版本都必须修复其中的另一个错误。:-) (2认同)