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

时间:2017-10-05 16:02:56

标签: git gitattributes core.autocrlf

我一遍又一遍地看着.gitattributes的文件,但我无法找到关于这两者之间差异的明确答案:

* text=auto

* text eol=lf

同样text=auto仅适用于*,还是也可以用于特定扩展程序?在这种情况下,差异是什么?

*.txt text=auto

*.txt text eol=lf

1 个答案:

答案 0 :(得分:9)

TL; DR

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

完整解释

让我们从此开始并向外工作:

  

同样text=auto仅适用于*,还是也可以用于特定扩展程序?

模式可能包含扩展名。 text=auto部分是属性设置,模式选择要应用于哪些文件的属性。

Git如何读取.gitattributes文件

.gitattributes中的每一行都匹配或不匹配某些路径名称,例如dir1/dir2/file.extREADME.md或其他。正如the gitattributes documentation所说:

  

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

pattern attr1 attr2 ...
     

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

因此,*模式。这些"模式"是the same as those in .gitignore files,但不允许使用负面模式。因此,您可以使用*.txt*.jpg之类的模式来匹配文件扩展名或dir1/*之类的模式以匹配特定目录中的文件(尽管还有另一种方法可以执行此操作: .gitignore个文件,每个目录可以有.gitattributes个文件,在这种情况下,它们适用于该目录及其子目录中的文件,但不适用于树中较高的路径。)

现在,对于text vs text=autoeol=lf,我们发现以下内容:

  

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

     
      
  •      

    路径具有特殊值的属性" true&#34 ;;这是   通过列出仅指定属性的名称   属性列表。

  •   
  • 取消设置[已剪切的详细信息,但请参见下文]

  •   
  • 设置为值

         

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

  •   
  • 未指定的

         

    没有模式匹配路径,如果路径有或没有任何说明   没有属性,路径的属性据说   未指定。

  •   

(在我看来,这最后一句话的措辞特别差。它的确意味着"所有与该路径相匹配的模式,没有人说过这个属性。")

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

同样的逻辑适用于eol=lf项。如果,首先,此eol=lf以某种模式发生,其次,该模式与相关文件匹配,则eol属性设置为值,值为lf。由于您建议的行为* text eol=lf,这会将eol设置为一个值,并使text 设置,但未设置为值

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

* text=auto
* text eol=elf

第二行的text会覆盖第一行,以便设置text(但不会设置值)并将eol设置为值,值为lf。两条线匹配,第二条线覆盖第一条线。

如果你反转这两行:

* text eol=lf
* text=auto

然后两行匹配,但现在第二行只覆盖text设置,所以现在您将text设置为auto并{{1设置为eol

lf属性如何应用于文件

the gitattributes documentation的下一部分说:

  

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

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

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

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

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

  •   

(这意味着,如果您未指定core.autocrlf,则必须追查the git config documentation以查找core.autocrlf的作用。

您已选择为每个文件设置它,或者为每个文件将其设置为text。前者表示"对每个文件进行转换"后者 - auto设置 - 意味着:嘿,Git,请为我决定文件是否为文本。如果您确定它是文本,请进行转换。

auto如何应用于文件

eol=lf设置的描述正下方是text设置的说明:

  

此属性设置要在其中使用的特定行结束样式    工作目录。它可以实现无线端转换    内容检查,有效设置eol属性。

     
      
  • 设置为字符串值" crlf" ... [因为你设置了text]

  • 而剪断了   
  • 设置为字符串值" lf"

         

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

  •   

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

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

请注意,如果选择git add之类的模式,则仅为与模式匹配的路径设置这些属性。对于其他路径,这些属性仍为未设置。因此,您应该回顾the documentation并查看未设置这些属性时会发生什么。

当然,您可以这样做:

*.txt

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

这个特殊的*.txt语法是我上面提到的内容。使用-text 不会取消设置text=false:它会将text设置为字符串值text。这与留下false未指定(非具体未设置)具有相同的效果。使用text会为其提供特殊的未设置设置。

未设置 -text未指定 text之间的区别在于,当text未指定时,Git可能会尝试 guess - 基于text设置,例如core.* - 是否进行转换。当core.autocrlf专门未设置时,Git不会做任何猜测:它根本不会对该文件进行任何转换。