autocrlf 和 eol 有什么区别



我正在阅读有关.gitattributes的 git 文档,以解决混合行尾的问题,并发现有两个类似的设置。

AUTOCRLF:

行尾转换 虽然 Git 通常不理会文件内容, 它可以配置为将存储库中的行尾规范化为 LF 以及(可选)在签出文件时将它们转换为 CRLF。

如果您只想在工作目录中使用 CRLF 行尾 无论您使用哪种存储库,都可以设置 配置变量"core.autocrlf",不使用任何属性。

[core] autocrlf = true 这不会强制规范化文本 文件,但确实确保您引入的文本文件 存储库将其行尾规范化为 LF 时 添加,并且已在存储库中规范化的文件 保持正常化。

和停产:

此属性设置要在 工作目录。它无需任何即可实现下线转换 内容检查,有效地设置文本属性。

设置为字符串值"crlf" 此设置强制 Git 规范化行 签入时此文件的结尾,并在 文件已签出。

设置为字符串值"lf" 此设置强制 Git 规范化行 在签入时结束为 LF,并在文件时阻止转换为 CRLF 已签出。

与 crlf 属性的向后兼容性为了向后兼容,crlf 属性解释如下:

CRLF 文本

-crlf -文本

CRLF=input 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移动到索引中。 索引的版本与HEAD提交的版本完全匹配。 Git 不会对索引版本应用任何过滤器,也不会更改任何行尾。

更新索引版本后,Git 会将该文件的版本从索引复制到工作树。1在此提取过程中,现在会发生一些转换。 如果有污迹过滤器,Git 现在就会应用它。 如果要进行行尾转换,Git 现在就会应用这些转换。

在此过程中,工作树文件可能会索引版本不同。 现在 Git 有一个问题,因为现在文件是"脏的"(在工作树中修改)。 这是事情变得特别混乱的地方,尽管大多数时候,这里的细节是看不见的。

最终,在使用工作树后,您可以在某个文件路径名上运行git add(或使用git add -a或其他任何东西来添加许多文件)。 这会将文件从工作树复制到索引中。阿拉伯数字在此复制期间,现在会发生更多转换:如果有干净的过滤器,Git 现在应用它。 如果要进行行尾转换,Git 现在就会应用它们。

换句话说,git add这些文件后,索引版本可能与工作树版本不匹配。 但是,Git 无论如何都将索引版本标记为"匹配"。git status将跳过工作树版本,因为 Git 现在声称索引版本与工作树版本匹配。 它确实如此,因为索引版本与再次运行git add添加的内容相匹配。

实际实现使用时间戳,通常分辨率为一秒。 Git 将继续认为索引版本与工作树版本匹配,除非并且直到操作系统触及文件的工作树版本上的时间戳。即使您更改要应用的过滤条件和/或行尾转换集,也是如此。Git 没有意识到你已经改变了行尾应该工作的方式,或者改变了"干净"过滤器来做一些不同的事情:它只是看到索引的"缓存"方面说"我匹配工作树版本时间戳T"。 只要工作树版本的时间戳仍然是T,文件就必须是"干净的"。

因此,要在更改任何文本转换设置后更新这些内容,您需要让 Git 意识到文件不干净。 您可以touch <path>设置新的时间戳"now",该时间戳与索引中的旧时间戳不匹配。 现在git add -a(或其他什么)将像往常一样扫描,但由于时间戳不匹配,这次它将找到该文件,并重新过滤它以将其添加到索引中。

同样,当您git add文件时,会发生这些转换。


通常,在类似Windows的系统上,您在这里的目标是获取仅LF存储库格式的文件,并将它们转换为CR-LF文件以供Windows处理。 这种转换发生在从索引到工作树的路上:即在git checkout期间。 然后,您可能希望在git add过程中将这些CR-LF工作树文件转换为仅LF格式,以便存储库内形式是Linux(以及Linus Torvalds和Git :-)更喜欢它们的方式。 但是你可以把它们以CR-LF格式存储在存储库中,如果你真的想惹恼所有的Unix/Linux人。 这完全取决于您在哪些步骤应用哪个转换(如果有的话):git checkout时间和git add时间。

.gitattributes文件指定要应用于哪些文件的转换。core.autocrlfcore.eol设置不会:Git 必须对哪些文件在哪一步获得哪些转换做出最佳猜测。


1从技术上讲,索引中的全部内容都是文件的哈希 ID。 文件本身作为 Gitblob对象存储在存储库数据库中。 与提交对象一样,这些 blob 对象是不可变的。 这就是为什么它不能在索引中更改的原因:它实际上只是一个哈希 ID。

2git add进程只是写入一个新Blob,并在任何筛选后写入新 Blob。 如果新 Blob 与某个现有 Blob 完全匹配(逐位),则新 Blob 会重新使用现有 Blob 的数据库条目和哈希 ID,并且不会实际保存 - 现有 Blob 就足够了。 否则,Blob 的数据将存储为具有新 ID 的新文件。 它是进入索引的新哈希 ID。

相关内容

  • 没有找到相关文章

最新更新