TL;DR
在 Git 2.36.0 之前,eol=lf
设置覆盖任何text
设置,并且由于您已选择将其应用于每条路径,因此只有eol=lf
如果您使用它,设置很重要。
Git 2.36.0 之后,eol=lf
仅适用于text
已设置、未指定或设置为auto
Git 确定它是一个文本文件。
完整解释
让我们从这个开始并向外努力:
Also is text=auto
仅适用于*
或者它也可以与特定的扩展一起使用?
模式可以包括扩展。这text=auto
部分是一个属性设置,并且模式选择将哪些属性应用于哪些文件。
Git 如何读取.gitattributes
File
中的每一行gitattributes
匹配或不匹配某些路径名,例如dir1/dir2/file.ext
or README.md
管他呢。作为gitattributes 文档 says:
中的每一行gitattributes
文件的格式为:
pattern attr1 attr2 ...
也就是说,一个模式后跟一个属性列表,用空格分隔。前导和尾随空格将被忽略。以 # 开头的行将被忽略。以双引号开头的模式以 C 风格引用。当模式与相关路径匹配时,该行列出的属性将被赋予该路径。
Hence, *
is the pattern。这些“模式”与.gitignore文件,但不允许使用负模式。因此,您可以使用类似的模式*.txt
and *.jpg
匹配文件扩展名或类似的模式dir1/*
匹配特定目录中的文件。两个都.gitignore
and .gitattributes
文件也可以位于特定目录的本地,在这种情况下,它们适用于该目录及其子目录中的文件,但不适用于树中更高的路径。
现在,为了text
vs text=auto
,并且对于eol=lf
无论是否,我们发现以下内容:
对于给定路径,每个属性可以处于以下状态之一:
Set
该路径具有特殊值“true”的属性;这是
通过仅列出属性名称来指定
属性列表。
Unset[细节被剪掉,但见下文]
设置一个值
路径具有指定字符串值的属性;这是
通过列出属性名称后跟等号来指定
符号 = 及其在属性列表中的值。
未指定
没有模式与路径匹配,也没有说明路径是否具有该属性,该路径的属性被称为“未指定”。
(在我看来,最后一个的措辞特别糟糕。它的真正意思是“所有匹配路径的模式”,没有人提到这个属性。)
So for text
,属性为set,并且对于text=auto
,属性为设置为一个值. The value本例中的部分是auto
。由于图案是*
,它适用于所有文件。
同样的逻辑也适用于eol=lf
物品。如果,首先,这eol=lf
出现在某种模式中,其次,该模式与有问题的文件匹配,然后eol
属性被设置为一个值,该值为lf
。由于您的建议行是* text eol=lf
,这将使eol
设置为一个值,并且会使text
set, but 未设置值.
如果你写成一个.gitattributes
文件,该两行序列:
* text=auto
* text eol=lf
第二行的text
覆盖第一个,所以text
is set(但不是一个值)和eol
is 设置为一个值,值为lf
。两行都匹配,并且第二行覆盖第一行。
If you reverse两行:
* text eol=lf
* text=auto
然后又两条线都匹配但现在第二行只覆盖text
设置,所以现在你有text
set to auto
and eol
set to lf
.
How the text
属性适用于文件
下一节gitattributes 文档 says:
这个属性[text
] 启用并控制行尾标准化... [如果是]
Set
...启用行尾标准化并将路径标记为文本文件...
Unset
...告诉 Git 不要在签入或签出时尝试任何行尾转换...
设置为字符串值“auto”
...如果 Git 判定内容是文本...
未指定
... Git 使用core.autocrlf
配置变量...
(这意味着你必须去追寻git config文档找出什么core.autocrlf
如果你离开的话text
未指定)。
您已选择为每个文件设置它或将其设置为auto
对于每个文件。前者的意思是“对每个文件进行转换”,后者的意思是“对每个文件进行转换”auto
设置)意味着:嘿,Git,请帮我决定该文件是否是文本。如果您确定它是文本,请进行转换。
How eol=lf
适用于文件
就在描述下方text
设置是这个描述eol
环境。在 Git 2.36.0 之前,它是这样的:
该属性设置要在
工作目录。它无需任何操作即可实现行尾转换
内容检查,有效设置text
属性。
设置为字符串值“crlf”
... [剪断,因为你设置lf
]
设置为字符串值“of”
此设置强制 Git 在签入时将行结尾标准化为 LF,并防止在签出文件时转换为 CRLF。
所以,如果你有eol=lf
设置路径(并与*
作为模式,它将被设置为every路径),Git 会将每个文件视为文本,并在“签入”时进行从 CRLF 行结尾到 LF 行结尾的转换(这再次表达得不好:转换实际上发生在git add
步)。 Git 在签出期间不会执行任何操作(这也不是完美的措辞:转换(或者在本例中为非转换)发生在从索引提取到工作树的过程中)。
Git 2.36.0 之后,描述现在为:
此属性设置要在工作目录中使用的特定行结束样式。仅当设置或未指定文本属性时,该属性才有效,或者设置为自动时,文件将被检测为文本,并以 LF 结尾存储在索引中。
[为简洁起见,省略其余描述]
这意味着text
现在考虑到eol
。在你的情况下,你要么设置text
或将其设置为auto
。在第一种情况下eol
属性始终适用于匹配模式。在第二种情况下,仅当 git 确定该文件是文本文件时才适用。
如果您使用不同的模式,您会得到不同的结果
请注意,如果您选择类似的模式*.txt
,那么这些属性是set仅适用于与模式匹配的路径。对于其他路径,这些属性仍然存在unset。因此,你应该回顾一下文档看看当这些属性是时会发生什么unset.
当然,您可以这样做:
* -text
*.txt eol=lf
第一行将明确unset text
在所有文件上,留下eol
所有文件上均未指定。然后是第二行设置为一个值 eol=lf
for *.txt
文件,覆盖未指定的值。现在 Git 将应用eol=lf
规则到名称匹配的所有文件*.txt
,并使用未指定的 (eol
and unset) 所有剩余文件的文本规则。
这个特别的-text
语法是我上面剪掉的东西。使用text=false
does not unset text
,而是离开text
设置为字符串值false
。这与离开具有相同的效果text
未指定(不具体unset)。使用-text
赋予它特殊的unset环境。
之间的区别unset text
and an 未指定 text
就是那个时候text
未指定,Git 可能会尝试guess(基于core.*
设置如core.autocrlf
) 是否进行转换。然而,当text
具体是unset,Git 根本不会对该文件进行任何猜测或转换。