* text=auto
* text eol=lf
text=auto
是否仅适用于使用*
或也可以与特定扩展名一起使用?在这种情况下,区别是什么?
*.txt text=auto
*.txt text eol=lf
* text=auto
* text eol=lf
text=auto
是否仅适用于使用*
或也可以与特定扩展名一起使用?在这种情况下,区别是什么?
*.txt text=auto
*.txt text eol=lf
在Git 2.36.0之前,eol=lf
设置会覆盖任何text
设置,如果你将其应用于每个路径,则只有eol=lf
设置会起作用。自Git 2.36.0以后,eol=lf
仅适用于text
被设置、未指定或设置为auto
且Git确定它是文本文件的情况下。
让我们从这个问题入手并逐步解释:
text = auto
是否仅适用于使用*
或也可以与特定扩展名一起使用?
模式可以包括扩展名。 text = auto
部分是一个属性设置,而模式选择哪些属性应用于哪些文件。
.gitattributes
文件gitattributes
中的每行都匹配或不匹配某些路径名称,例如dir1/dir2/file.ext
或README.md
或其他路径名。正如gitattributes文档所述:
gitattributes
文件中的每一行都具有以下格式:pattern attr1 attr2 ...
也就是说,一个模式后面跟着一个属性列表,用空格隔开。前导和尾随空格将被忽略。以#开头的行将被忽略。以双引号开头的模式将以C风格引用。当模式与所讨论的路径匹配时,列在该行上的属性将赋给该路径。
因此,
*
是模式。这些“模式”与.gitignore
文件中的那些相同,只是不允许使用否定模式。因此,您可以使用类似*.txt
和*.jpg
的模式来匹配文件名扩展名,或者使用dir1/*
这样的模式来匹配特定目录中的文件。.gitignore
和.gitattributes
文件也可以是特定目录本地的,这种情况下它们适用于该目录及其子目录中的文件,但不适用于树中更高的路径。现在,对于
text
与text=auto
,以及eol=lf
或不是,我们得到以下结果:对于给定路径,每个属性可以处于以下状态之一:
已设置
路径具有具有特殊值“true”的属性;这是通过仅在属性列表中列出属性名称来指定的。未设置 [详情略过,但请参见下文]
设置为值
路径具有具有指定字符串值的属性;这是通过在属性列表中列出属性名称,后跟等号=及其值来指定的。未指定
没有任何模式与路径匹配,并且没有任何内容指明路径是否具有属性,该路径的属性被称为未指定。(最后一个的措辞特别糟糕,我认为它实际上意味着“对于与路径匹配的所有模式,没有一个说了什么关于该属性的事情。”)
因此,对于
text
,该属性被设置,对于text=auto
,该属性被设置为值。在这种情况下,值部分是auto
。由于模式是*
,它适用于所有文件。同样的逻辑也适用于
eol=lf
项。如果,首先,这* text=auto * text eol=lf
第二行
text
覆盖了第一行,因此text
被设置(但值未被赋予),eol
被设置为一个值,值为lf
。两行都匹配,并且第二行覆盖了第一行。如果你交换这两行:
* text eol=lf * text=auto
再次提醒,两行都匹配,但现在第二行仅覆盖了
text
设置,所以现在text
被设置为auto
,eol
被设置为lf
。
text
属性如何应用于文件接下来一节gitattributes文档说:
此属性[
text
]启用并控制行末规范化...[如果它是]已设置
...启用行末规范化,并将路径标记为文本文件...未设置
...告诉Git不要尝试在签入或签出时进行任何行末转换...设置为字符串值"auto"
...若Git决定内容是文本...未指定
...Git使用core.autocrlf
配置变量...(这意味着您必须去查找
git config
文档,以找出如果您未指定text
,core.autocrlf
变量做什么)。您选择要么为每个文件设置它,要么为每个文件设置为
auto
。前者表示“为每个文件进行转换”,后者(auto
设置)表示:嘿,Git,请为我决定文件是否为文本。如果您决定它是文本,请进行转换。
eol=lf
如何应用于文件在
text
设置的描述下面,是对eol
设置的描述。在Git 2.36.0之前,它读作:此属性设置要在工作目录中使用的特定行结束样式。它启用行末转换而不进行任何内容检查,有效地设置了
text
属性。设置为字符串值"crlf"
...[因为您设置了lf
而被忽略]设置为字符串值"lf"
此设置强制Git在签入时将换行符规范化为LF,并防止检出文件时将其转换为CRLF。所以,如果你为一个路径设置了
eol=lf
(并且使用*
作为模式,它将应用于每个路径),Git 将把每个文件都视为文本,并在“检入”时从 CRLF 行尾转换为 LF 行尾(此描述措辞不当,实际上转换发生在git add
步骤中)。Git 在检出期间什么都不会做(这也没有表述得完美:转换或者在这种情况下非转换发生在从索引到工作树的提取期间)。在 Git 2.36.0 之后,描述如下:
此属性设置特定的行尾样式以在工作目录中使用。只有在文本属性设置或未设置或设置为 auto 的情况下,或者如果检测到文件为文本并存储在索引中具有 LF 结尾,则此属性才有效。
[其余说明已省略]。这意味着现在对
eol
考虑了text
。在您的情况下,您可以设置text
或将其设置为auto
。在第一种情况下,eol
属性始终适用于匹配模式。在第二种情况下,它仅在 git 确定文件为文本文件时适用。如果使用不同的模式,则会得到不同的结果
请注意,如果选择像
*.txt
这样的模式,则这些属性仅针对与模式匹配的路径设置。对于其他路径,这些属性保持未设置状态。因此,您应该回顾一下文档,看看当这些属性未设置时会发生什么。当然,你可以这样做:
* -text *.txt eol=lf
第一行会显式地在所有文件中 取消设置
text
,使所有文件上的eol
未指定。第二行然后为*.txt
文件 设置eol=lf
的值,覆盖未指定的值。现在 Git 将应用eol=lf
规则到其文件名与*.txt
匹配的所有文件上,并对其余文件使用未指定的 (eol
和 取消设置 的) 文本规则。这个特殊的
-text
语法是我上面删除的内容。使用text=false
不会 取消设置text
,而是将text
设置为字符串值false
。这与将text
未指定(没有特别取消设置)具有相同的效果。使用-text
给它一个特殊的 取消设置 的设置。取消设置 的
text
与 未指定 的text
之间的区别在于当text
未指定时,Git 可能会尝试根据core.*
设置(如core.autocrlf
)猜测是否进行转换。但是,当text
明确地被 取消设置 时,Git 将不会对该文件进行任何猜测或转换。
text eol=lf
: Git将始终在检出时将行尾转换为LF"是错误的吗?它应该是“git在检出时不会执行任何转换”,还是它们实际上具有完全相同的含义? - Marinos Angit add
时间)上应用CRLF-to-LF规则,并且不会在“输出”转换(大致上,在git checkout
时间)上进行任何换行符更改。请注意,一旦发生了任何输入侧转换(添加和提交),神圣的提交版本就只有LF结尾,因此“无转换”和“转换为LF结尾”将具有相同的效果。这使得很难检测是否没有发生转换 - 但源代码在这里表示“没有转换”。 - torek* text=auto
\n* text eol=lf
”,而不是最后一个text eol
设置为elf
(除非我在这里漏掉了一些汇编程序)。 - bballdave025eol=lf
,打错了!我会修复的。 - torek