【发布时间】:2018-03-17 08:08:52
【问题描述】:
我一遍又一遍地查看.gitattributes 的文档,但我找不到关于这两者之间有什么区别的明确答案:
* text=auto
* text eol=lf
text=auto 是否也仅用于*,或者它也可以用于特定的扩展?在这种情况下有什么区别?
*.txt text=auto
*.txt text eol=lf
【问题讨论】:
标签: git gitattributes core.autocrlf
我一遍又一遍地查看.gitattributes 的文档,但我找不到关于这两者之间有什么区别的明确答案:
* text=auto
* text eol=lf
text=auto 是否也仅用于*,或者它也可以用于特定的扩展?在这种情况下有什么区别?
*.txt text=auto
*.txt text eol=lf
【问题讨论】:
标签: git gitattributes core.autocrlf
eol=lf 设置会覆盖任何 text 设置,并且由于您已选择将其应用于每个路径,因此只有 eol=lf 设置才重要,如果您使用它。
让我们从这个开始,向外工作:
text=auto是否也只能与*一起使用,还是也可以与特定扩展一起使用?
模式可能包括扩展。 text=auto 部分是一个属性设置,模式选择哪些属性应用于哪些文件。
.gitattributes 文件.gitattributes 中的每一行都匹配或不匹配某些路径名,例如 dir1/dir2/file.ext 或 README.md 或其他。正如the gitattributes documentation 所说:
gitattributes文件中的每一行格式为:pattern attr1 attr2 ...即一个模式后跟一个属性列表,用空格分隔。前导和尾随空格将被忽略。以 # 开头的行将被忽略。以双引号开头的模式以 C 风格引用。当模式与相关路径匹配时,将行中列出的属性赋予路径。
因此,* 是模式。这些“模式”是the same as those in .gitignore files,但不允许使用负模式。因此,您可以使用像 *.txt 和 *.jpg 这样的模式来匹配文件扩展名,或者像 dir1/* 这样的模式来匹配特定目录中的文件(尽管还有另一种方法可以做到这一点:像 .gitignore 文件,你每个目录可以有.gitattributes 文件,在这种情况下,它们适用于该目录及其子目录中的文件,但不适用于树中更高的路径)。
现在,对于text 与text=auto,以及eol=lf 与否,我们发现以下内容:
对于给定路径,每个属性都可以处于以下状态之一:
设置
路径具有特殊值“true”的属性;这是 通过仅列出属性的名称来指定 属性列表。
未设置[细节被剪断,但见下文]
设置一个值
路径具有指定字符串值的属性;这是 通过列出属性名称后跟等号来指定 符号 = 及其在属性列表中的值。
未指定
没有模式匹配路径,并且没有说明路径是否有或 没有属性,路径的属性被称为 未指定。
(在我看来,最后一个的措辞特别糟糕。它的真正意思是“在所有匹配路径的模式中,没有人提到这个属性。”)
所以对于text,属性是set,对于text=auto,属性是设置为一个值。在这种情况下,value 部分是auto。由于模式为*,因此适用于所有文件。
同样的逻辑适用于eol=lf 项目。如果,首先,这个eol=lf 出现在某个模式中,其次,该模式与相关文件匹配,那么eol 属性被设置为一个值,该值是lf。由于您建议的行是* text eol=lf,这将使eol 设置为一个值,并将text 设置,但未设置为一个值。
如果您在单个.gitattributes 文件中编写两行序列:
* text=auto
* text eol=lf
第二行的text 覆盖第一行,因此text 被设置(但不是一个值),eol 被设置为一个值,其值为lf。两行匹配,第二行覆盖第一行。
如果你颠倒这两行:
* text eol=lf
* text=auto
然后两行都匹配,但现在第二行只覆盖了text 设置,所以现在你将text 设置为auto 和eol 设置为lf。
text 属性如何应用于文件the gitattributes documentation 的下一部分说:
此属性 [
text] 启用和控制行尾标准化。 ... [如果是的话]
Set ... 启用行尾规范化并将路径标记为文本文件...
Unset ... 告诉 Git 在签入或签出时不要尝试任何行尾转换 ...
设置为字符串值“auto”...如果 Git 确定内容是文本...
未指定...Git 使用
core.autocrlf配置变量...
(这意味着如果您未指定text,则您必须追查the git config documentation 以了解core.autocrlf 的作用)。
您已选择为每个文件设置它,或者为每个文件设置它为auto。前者的意思是“对每个文件进行转换”,而后者——auto 设置——意思是:嘿,Git,请帮我决定文件是否为文本。如果您确定它是文本,请进行转换。
eol=lf 如何应用于文件text 设置的描述正下方是eol 设置的描述:
此属性设置要在 工作目录。它使行尾转换无需任何 内容检查,有效地设置
text属性。
设置为字符串值“crlf”...[因为您设置了
lf而被截断]设置为字符串值“lf”
此设置强制 Git 将行尾标准化为 LF on 签入并防止文件转换为 CRLF 签出。
因此,如果您将eol=lf 设置为路径——并且以* 作为模式,它将为每个 路径设置——Git 会将每个文件都视为文本,然后执行在“签入”时从 CR-LF 行尾转换为仅 LF 行尾(这句话的措辞很糟糕,再次:转换实际上发生在git add 步骤中)。 Git 在结帐期间什么也不做(这也不是完美的表述:转换——或者在这种情况下,非转换——发生在从索引到工作树的提取过程中)。
请注意,如果您选择*.txt 之类的模式,则这些属性仅针对与该模式匹配的路径设置。对于其他路径,这些属性保持未设置。因此,您应该回头查看the documentation,看看当这些属性未设置时会发生什么。
当然,您可以这样做:
* -text
*.txt eol=lf
第一行将明确unset text 在所有文件上,而eol 在所有文件上未指定。然后第二行设置为一个值 eol=lf 用于*.txt 文件,覆盖未指定的值。现在 Git 会将 eol=lf 规则应用于名称与 *.txt 匹配的所有文件,并对所有剩余文件使用 unspecified-eol 和 unset-text 规则。
这个特殊的-text 语法是我在上面剪掉的东西。使用text=false 不会取消设置text:它会将text 设置为字符串值false。这与未指定 text 具有相同的效果(不是专门 unset)。使用 -text 为其提供了特殊的 unset 设置。
未设置 text 和未指定 text 之间的区别在于,当未指定text 时,Git 可以尝试猜测 em>——基于core.*core.autocrlf等设置——是否进行转换。当text 明确未设置时,Git 不会做任何猜测:它根本不会对该文件进行任何转换。
【讨论】:
text eol=lf:Git 将始终在结帐时将行尾转换为 LF”,错了吗?应该是“git不会在结帐时执行任何转换”,还是它们实际上具有完全相同的含义?
eol=lf 与 text 的设置无关,Git 将在“输入”转换上应用 CRLF-to-LF 规则(大致在 git add 时间),并且“输出”转换没有行尾更改(大致在git checkout)。请注意,一旦有任何输入端转换(添加和提交),神圣提交的版本将具有仅 LF 结尾,因此“无转换”和“仅转换为 LF”将具有相同的 效果。这使得很难检测到没有发生转换,但the source 在这里说“没有转换”。
* text=auto \n * text eol=lf”而不是将最后一个 text eol 设置为 elf(除非我在这里错过了一些汇编程序编程。)跨度>
eol=lf,错别字!会修复的。