"check out code" 在 git 行尾文档中是什么意思?

What does "check out code" mean in git documentation for line endings?

我真的很困惑 "check out code" 在以下页面中的含义:https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#__code_core_autocrlf_code

If you’re on a Windows machine, set it to true – this converts LF endings into CRLF when you check out code:

添加文件的时候是什么意思?因为每当我将 core.autocrlfinput 更改为 true 时,反之亦然,我在添加文件时看到的差异("check out" 是否意味着 "add"? ):

> git config --global core.autocrlf true

> git add crlf-file.md

> git add lf-file.md
 warning: LF will be replaced by CRLF in lf-file.md.
 The file will have its original line endings in your working directory.

> git config --global core.autocrlf input

> git add crlf-file.md
  warning: CRLF will be replaced by LF in crlf-file.md.
  The file will have its original line endings in your working directory.
> git add lf-file.md

(注意:我正在尝试回答基本问题,这似乎真的是:如果结帐意味着 git checkout,为什么我在 git add 期间收到这些消息?)

这方面的文档有点草率,可能是故意的,因为完全正确的细节有些模糊。要在概念层面上很好地理解它,您应该将行结束修改视为更一般的 smudgeclean 过滤的一部分(因为这事实上它是如何实现的)。

在 Git 中,您当前可以使用的每个文件同时存在于三个位置:

the HEAD commit      the index       the work-tree
---------------      ---------       -------------
README.md            README.md       README.md
file.txt             file.txt        file.txt

文件可以在不同的方向复制,除了所有提交在任何时候都是只读的。因此,您可以从 HEAD 提交复制到索引中,或者从索引复制到工作树中。您还可以从工作树复制到索引中。

(您也可以从索引中进行 new 提交。这将保留旧的 HEAD 提交,而新的提交 变为 HEAD 提交。所以在进行新提交后,HEAD 提交和索引匹配。这不是因为我们修改了任何提交;我们不能这样做。这是因为我们添加了一个新的提交,由索引创建,然后我们停止将旧提交称为 HEAD,而是将新提交称为 HEAD。)

请注意,索引位于 HEAD 和工作树之间 "in the way"。为了将任何文件从 HEAD 复制到工作树,它必须首先通过索引。为了从工作树中进行新的提交,每个新文件都必须通过索引。因此,index/work-tree 转换是 cleaningsmudging 发生的地方。

到"clean"一个文件意味着让它准备好提交。例如,此清理过程可以将 CRLF 行结尾转换为仅 LF 行结尾。 Or, using the ident filter, you can un-make many substitutions, or write your own filter to do virtually anything. To smudge a file means to make it ready for editing and/or use in the work-tree. This can, for instance, translate LF-only line endings into CRLF-endings. As with the cleaning process, you can use the ident filter or your own filter-driver to do anything you want. Git LFS 使用这些驱动程序交换短引用和整个文件内容。

因此,确切的答案是在将文件复制到索引中或从索引中复制出来的过程中应用了行结束转换。最常见的是这两个:

  • git add 从工作树复制到索引中。
  • git checkout 提取到工作树,从提交到索引然后到工作树,或者直接从索引到工作树。

这些 CRLF 到 LF 或 LF 到 CRLF 的转换在这些时候发生。但是 Git 有额外的代码试图凭直觉 稍后进行这些转换 是否会导致对现有提交数据的更改,即使它尚未完成。 那个代码会给你你看到的警告信息:

warning: LF will be replaced by CRLF ...
warning: CRLF will be replaced by LF ...

如果启用 "safe crlf" 选项,则会出现这些警告。因为它们在不同的时间来自不同的代码运行,所以一切都会非常混乱。

考虑一个图书馆。当您将一本书借出图书馆时,在您将其重新借回之前,其他读者无法访问该图书。

旧的集中式版本控制系统的工作方式类似;当您 "checked out" 一个文件时,系统会锁定该文件,在您将其重新签入之前,其他用户无法签出该文件。

较新的版本控制系统往往允许多个用户同时处理一个文件,需要将不兼容的更改合并在一起,而不是严格序列化对文件的访问。不过,术语 "check out" 仍在使用,表示将文件从存储库复制到工作目录的过程。

请注意,当 core.safecrlf 设置为 truewarn 时看到的那些 end of line conversion warnings 并不总是在结帐时有效,因为它可能会被错误触发的内容使用CRLF作为行尾。

此问题已在 Git 2.16(2018 年第一季度)

中修复

参见 commit 649f1f0 (08 Dec 2017), and commit 86ff70a (26 Nov 2017) by Torsten Bögershausen (tboegi)
(由 Junio C Hamano -- gitster -- in commit 720b176 合并,2017 年 12 月 27 日)

convert: tighten the safe autocrlf handling

When a text file had been commited with CRLF and the file is commited again, the CRLF are kept if .gitattributs has "text=auto".
This is done by analyzing the content of the blob stored in the index: If a '\r' is found, Git assumes that the blob was commited with CRLF.

The simple search for a '\r' does not always work as expected:
A file is encoded in UTF-16 with CRLF and commited. Git treats it as binary.
Now the content is converted into UTF-8. At the next commit Git treats the file as text, the CRLF should be converted into LF, but isn't.

Replace has_cr_in_index() with has_crlf_in_index(). When no '\r' is found, 0 is returned directly, this is the most common case.
If a '\r' is found, the content is analyzed more deeply.