我正在阅读有关解决混合行结尾问题的git 文档.gitattributes,并发现有两个类似的设置。
自动CRLF:
行尾转换 虽然 Git 通常不考虑文件内容,但它可以配置为将存储库中的行尾规范化为 LF,并且可以选择在签出文件时将它们转换为 CRLF。
如果您只想在您的工作目录中使用 CRLF 行结尾而不管您使用的是哪个存储库,您可以设置配置变量“core.autocrlf”而不使用任何属性。
[core] autocrlf = true 这不会强制文本文件的规范化,但确实确保您引入存储库的文本文件在添加时将其行尾规范化为 LF,并且已在存储库中规范化的文件保留归一化。
和停产:
此属性设置要在工作目录中使用的特定行结束样式。它可以在没有任何内容检查的情况下进行行尾转换,有效地设置文本属性。
设置为字符串值“crlf” 此设置强制 Git 在签入时对此文件的行尾进行规范化,并在签出文件时将其转换为 CRLF。
设置为字符串值“lf” 此设置强制 Git 在签入时将行尾规范化为 LF,并防止在签出文件时转换为 CRLF。
与 crlf 属性的 向后兼容性 为了向后兼容, crlf 属性解释如下:
文本
-crlf -text
crlf=输入 eol=lf
似乎两者都在做同样的事情,但有一些关于compatibility. 这是否意味着,这autocrlf已被弃用,而新口味是eol什么?我目前有一个包含多个损坏文件的存储库,我想将其转换为crlf表示形式。你会看到文档让我们困惑而不是澄清事情。
在这种情况下我应该申请什么?
与其直接回答问题本身——请参阅VonC对相关问题的回答——让我们专注于这一点:
我目前有一个包含多个损坏文件的存储库,我想将其转换为 crlf 表示。
首先,让我们注意这些选项都不能更改任何现有提交。这是一个基本的 Git 属性:一旦提交,就不能更改现有的提交。您可以做的是进行新的提交。这通常没什么大不了的,因为通常我们只希望新的东西是正确的(但请参阅git filter-branch,它在对提交内容应用过滤器后复制提交,并可用于重新复制整个存储库:新的存储库不再兼容使用旧的,但您可以通过这种方式“修复历史”)。
接下来,我认为这是理解所有这些行尾/CRLF 属性选项的关键:当文件移入或移出索引时,将转换应用于文件。
请记住,Git 的索引是您构建下一次提交的地方。索引的内容最初与当前提交的任何内容相同:git checkout master例如,您运行,Git 将名称解析master为提交 ID 并将该特定提交复制到您的工作树 - 但副本通过索引。
换句话说,Git 首先发现该文件foo.txt在提交中(并且需要提取)。所以 Git 将该版本移动foo.txt到索引中。该指数的版本完全匹配的HEADcommmit的版本。Git 不会对索引版本应用任何过滤器,也不会更改任何行结尾。
更新索引版本后, Git 会将文件的该版本从索引复制到工作树。1在此提取过程中,现在 发生了一些转换。如果有污迹过滤器,Git 现在会应用它。如果要进行行结束转换,Git 现在会应用这些转换。
在此过程中,工作树文件可能与索引版本不同。现在 Git 有问题,因为现在文件是“脏的”(在工作树中修改)。这就是事情变得特别混乱的地方,尽管大多数时候,这里的细节是不可见的。
最终,在使用您的工作树之后,您可能会git add在某个文件路径名上运行(或使用git add -a或添加许多文件)。这将文件从工作树复制到索引中。2 在此复制期间,现在发生了更多转换:如果有一个干净的过滤器,Git 现在会应用它。如果要进行行结束转换,Git 现在会应用它们。
换句话说,在git add-ing 这些文件后,索引版本可能与工作树版本不匹配。但是,Git 无论如何都会将索引版本标记为“匹配”。Agit status将直接跳过工作树版本,因为 Git 现在声称索引版本与工作树版本匹配。这有点确实,因为索引版本匹配什么将被添加,如果你跑了git add一次。
实际实现使用时间戳,通常具有一秒的分辨率。Git 将继续相信索引版本与工作树版本匹配,除非操作系统触及文件的工作树版本上的时间戳。 即使您更改要应用的过滤器和/或行尾转换集,也是如此。 Git 没有意识到你已经改变了行尾应该工作的方式,或者改变了“干净”过滤器来做一些不同的事情:它只是看到索引的“缓存”方面说“我匹配工作树版本时间戳吨”。只要工作树版本的时间戳仍然是T,文件就必须是“干净的”。
因此,要在更改任何文本转换设置后更新这些内容,您需要让 Git 意识到文件不干净。您可以touch <path>设置一个新的“现在”时间戳,它与索引中的旧时间戳不匹配。现在git add -a(或其他)会像往常一样扫描,但由于时间戳不匹配,这次它将找到文件,并将重新过滤它以将其添加到索引中。
同样,这些转换会在您创建git add文件时发生。
通常,在类似 Windows 的系统上,您的目标是将仅 LF 存储库格式的文件转换为 CR-LF 文件以供 Windows 处理。该转换发生在从索引到工作树的路上:即,在git checkout. 然后,您可能希望在此git add过程中将这些 CR-LF 工作树文件转换为 LF-only 格式,以便存储库中的形式是 Linux(以及 Linus Torvalds 和 Git :-) )喜欢它们的方式。但是,如果您真的想惹恼所有 Unix/Linux 人员,您可以将它们以 CR-LF 格式存储在存储库中。如果有的话,这完全取决于您在哪些步骤中应用哪些转换:git checkout时间和git add时间。
该.gitattributes文件指定要应用于哪些文件的转换。在core.autocrlf和core.eol设置不:混帐必须对此做出最好的猜测哪个文件得到在该步骤,转换。
1从技术上讲,索引中的所有内容都是文件的哈希 ID。文件本身作为 Git blob对象存储在存储库数据库中。就像提交对象一样,这些 blob 对象是不可变的。这就是它不能在索引中更改的原因:它实际上只是一个哈希 ID。
2该git add过程只是写入一个新的blob,在任何过滤之后写入新的 blob。如果新 blob 与某个现有 blob 逐位完全匹配,则新 blob 会重新使用现有 blob 的数据库条目和哈希 ID,并且实际上并未保存——现有 blob 就足够了。如果不是,则 blob 的数据将存储为具有新 ID 的新文件。这是进入索引的新哈希 ID。