【问题标题】:What is difference between autocrlf and eolautocrlf 和 eol 有什么区别
【发布时间】:2017-02-20 08:52:40
【问题描述】:

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

AUTOCRLF:

行尾转换 虽然 Git 通常会单独保留文件内容,但 它可以配置为将存储库中的行结尾标准化为 LF 并且,可以选择在文件签出时将它们转换为 CRLF。

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

[core] autocrlf = true 这不会强制文本标准化 文件,但确实确保您介绍给 存储库将它们的行尾归一化为 LF 时 添加,以及已经在存储库中规范化的文件 保持正常化。

和 EOL:

此属性设置要在 工作目录。它使行尾转换无需任何 内容检查,有效地设置文本属性。

设置为字符串值“crlf” 此设置强制 Git 规范化行 签入时此文件的结尾并将它们转换为 CRLF 时 文件已签出。

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

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

crlf 文本

-crlf -文本

crlf=输入 eol=lf

似乎两者都在做同样的事情,但compatibility 有一些东西。这是否意味着 autocrlf 已被弃用,而新风格是 eol 或其他什么?我目前有一个包含多个损坏文件的存储库,我想将其转换为 crlf 表示形式。而且您会看到文档使我们感到困惑,而不是澄清事情。

在这种情况下我应该申请什么?

【问题讨论】:

标签: git gitattributes


【解决方案1】:

与其直接回答问题本身——请参阅链接问题的VonC's answer——让我们专注于这个:

我目前有一个包含多个损坏文件的存储库,我想将其转换为 crlf 表示形式。

首先,让我们注意这些选项都不能更改任何现有的提交。这是 Git 的一个基本属性:一旦提交,现有的提交就无法更改。您可以做的是 new 提交。这通常没什么大不了的,因为通常我们只希望 new 的东西是正确的(但请参阅git filter-branch,它在将过滤器应用于其内容后复制提交,并可用于重新复制整个存储库:新存储库不再与旧存储库兼容,但您可以通过这种方式“修复历史记录”)。

接下来,我认为这是理解所有这些行尾/CRLF 属性选项的关键:文件在移入或移出索引时应用到文件。

请记住,Git 的索引是您构建 next 提交的位置。索引的内容最初与当前提交的内容相同:例如,您运行 git checkout master,Git 将名称 master 解析为提交 ID,并将该特定提交复制到您的工作树中——但是复制通过索引。

换句话说,Git 首先发现文件foo.txt 在提交中(并且需要提取)。所以 Git 将那个版本的 foo.txt 移动到索引中。索引的版本完全匹配HEAD commmit 的版本。 Git 不会对索引版本应用任何过滤器,也不会更改任何行尾。

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

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

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

换句话说,在git add-ing 这些文件之后,index 版本可能与工作树版本不匹配。但是,无论如何,Git 都会将索引版本标记为“匹配”。 git status 将直接跳过工作树版本,因为 Git 现在声称索引版本与工作树版本匹配。 有点,因为如果您再次运行git add,索引版本与将添加的内容相匹配

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

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

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


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

.gitattributes 文件指定将哪些转换应用于哪些文件。 core.autocrlfcore.eol 设置不要:Git 必须对哪些文件在哪个步骤进行哪些转换做出最佳猜测。


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

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

【讨论】:

  • 很好的答案,但 gitattributes 中的 core.autocrlf 和 eol 设置 (*.txt text eol=crlf) 就是针对这个问题而设计的 - 在提取和添加索引期间进行 EOL 转换。我只是对同一件事的两个设置感到困惑。经过一番研究,我发现后一种设置只允许更精确的配置。您正在按扩展名配置文件,而不是为存储库中的所有文件进行配置。 autocrlf 已经损坏了我的存储库中的一些文件(例如xls),当我可以用eol 将它们标记为binary
  • 如果你使用*.blah text=auto,那么是的,你是通过扩展(和自动分类)来做的。如果你使用foo.* text=auto,你是通过前缀来做的,如果你使用* text=auto,你是在全局显式调用它,而不是依赖于core.autocrlf(其设置在存储库中Git控制的文件之外)。我认为core.autocrlf 不是版本控制文件的一部分这一事实可能是使用它或避免它的关键原因(我个人避免它,就像我避免使用 Windows 一样:-))。
  • 我希望core.autocrlf 可以像text=... 一样存储在gitattributes 中。但是,我没有尝试并坚持使用新的闪亮 eol。
  • @AlexZhukovskiy: 不,core.autocrlfgit config 设置,这些不能存储在存储库中。
  • 根据gitattributes docs,binary 是扩展为-text -diff 的“宏”。这没有直接关系,但有两个地方文字字符串 binary 是有意义的,在差异驱动程序中(参见 textconv 部分末尾附近的讨论)和作为合并驱动程序(参见“内置合并驱动程序”)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-17
  • 1970-01-01
  • 2010-10-02
  • 2011-12-12
  • 2010-09-16
  • 2012-03-14
  • 2012-02-06
相关资源
最近更新 更多