autocrlf 和 eol 有什么区别

What is difference between autocrlf and eol

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

AUTOCRLF:

End-of-line conversion While Git normally leaves file contents alone, it can be configured to normalize line endings to LF in the repository and, optionally, to convert them to CRLF when files are checked out.

If you simply want to have CRLF line endings in your working directory regardless of the repository you are working with, you can set the config variable "core.autocrlf" without using any attributes.

[core] autocrlf = true This does not force normalization of text files, but does ensure that text files that you introduce to the repository have their line endings normalized to LF when they are added, and that files that are already normalized in the repository stay normalized.

和停产:

This attribute sets a specific line-ending style to be used in the working directory. It enables end-of-line conversion without any content checks, effectively setting the text attribute.

Set to string value "crlf" This setting forces Git to normalize line endings for this file on checkin and convert them to CRLF when the file is checked out.

Set to string value "lf" This setting forces Git to normalize line endings to LF on checkin and prevents conversion to CRLF when the file is checked out.

Backwards compatibility with crlf attribute For backwards compatibility, the crlf attribute is interpreted as follows:

crlf text

-crlf -text

crlf=input eol=lf

看来两者的做法是一样的,不过compatibility有点问题。这是否意味着 autocrlf 已被弃用,新版本是 eol 或其他?我目前有一个包含多个损坏文件的存储库,我想将其转换为 crlf 表示形式。你看到文档让我们感到困惑而不是澄清事情。

这种情况应该怎么申请?

与其直接回答问题本身——请参阅 VonC's answer 相关问题——让我们专注于此:

I currently have a repository with multiple corrupted files which I want to convert into crlf representation.

首先,请注意 none 这些选项可以 更改 任何现有提交。这是一个基本的 Git 属性:一旦提交,就不能更改现有的提交。您可以做的是 new 提交。这通常没什么大不了的,因为通常我们只希望 new 内容正确(但请参阅 git filter-branch,它在对内容应用过滤器后复制提交,并且可以使用re-copy 整个存储库:新的存储库不再与旧的兼容,但你可以 "fix history" 这样。

接下来,我认为这是理解所有这些行尾/CRLF 属性选项的关键:t运行sformations are applied to files when they move into or out of the指数.

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

换句话说,Git 首先发现文件 foo.txt 在提交中(并且需要提取)。因此 Git 将该版本的 foo.txt 移至索引。索引的版本 HEAD commit 的版本完全匹配。 Git 不对索引版本应用任何过滤器,也不更改任何行结尾。

索引版本更新后, Git 将文件的那个版本 索引复制到 work-tree.1 在此提取过程中 现在 发生了一些 t运行 变化。如果有污迹滤镜,Git 现在应用它。如果要进行 line-ending 次转换,Git 现在应用这些转换。

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

最终,在使用 work-tree 之后,您可以 运行 git add 某些文件 path-name(或使用 git add -a 或其他添加许多文件)。这会将文件从 work-tree 复制到索引中。2 在此复制期间,现在会发生更多 运行 变化:如果有干净的过滤器,Git 现在应用它。如果要进行 line-ending 次转换,Git 现在应用它们。

换句话说,在 git add-ing 这些文件后,index 版本可能与 work-tree 版本不匹配。但是,Git 无论如何都会将索引版本标记为 "matching"。 git status 将直接跳过 work-tree 版本,因为 Git 现在声称索引版本与 work-tree 版本匹配。它 有点 ,因为索引版本与 将被添加 如果您再次 运行 git add

实际实现使用时间戳,通常具有 one-second 分辨率。 Git 将继续相信索引版本与 work-tree 版本匹配,除非并且直到 OS 触及文件 work-tree 版本上的 time-stamp。 即使您更改要应用的过滤器集 and/or line-ending 转换也是如此。 Git 没有意识到您已经更改了方式行结尾应该可以工作,或者更改 "clean" 过滤器来做一些不同的事情:它只是看到索引的 "cache" 方面显示 "I match work-tree version time-stamp T"。只要work-tree版本的time-stamp还是T,文件一定是"clean".

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

同样,当您 git add 文件时,这些 运行 信息会发生。


通常,在 Windows-like 系统上,您的目标是获取 LF-only repository-format 文件并将它们转换为 CR-LF 文件用于 Windows去处理。 t运行sformation 发生在 out 索引的 to the work-tree 的路上:即,在 git checkout。然后你会想在git add过程中将这些CR-LFwork-tree文件t运行sform成LF-only格式,这样in-repository形式就是Linux(以及 Linus Torvalds,因此 Git :-))更喜欢它们。但是你 可以 将它们以 CR-LF 格式存储在存储库中,如果你真的想惹恼所有 Unix/Linux 的人。这完全取决于您在哪些步骤应用了哪些 t运行 形式(如果有的话):git checkout 时间和 git add 时间。

.gitattributes 文件指定哪些 t运行s 表单应用于哪些文件。 core.autocrlfcore.eol 设置 不: Git 必须最好地猜测哪些文件获得哪些 t运行 信息哪一步。


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

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