消息本身似乎总是有点……错了?奇怪的?措辞不好?——我不知道该怎么称呼它。该消息的意图是警告您某些情况似乎不一致:您将来查看文件的方式可能与您现在查看文件的方式不兼容。
考虑到这一点,让我们来看看细节:
echo '* text=auto !eol' > .gitattributes
首先,在text=auto:这将text 属性设置为字符串值auto,它告诉Git:请猜测每个文件是文本还是二进制文件。我个人认为这是一个坏主意:您不希望 Git 猜测。你应该告诉它。 Git 的猜测通常相当不错,但我不喜欢我的软件猜测那么多。 :-)
无论如何,让我们转到!eol:这意味着将eol 属性设置为未指定 状态。这可能不是你想要的。它开始未指定,因此如果您不想指定它,您可以不指定它。 ! 前缀的存在是为了更正一些以前的设置:例如,如果默认应该是eol=lf,你可能有:
* eol=lf
但由于不应修改 JPG 文件,因此我们可以仅为 *.jpg 覆盖它:
*.jpg !eol
(虽然*.jpg binary 可能更好:这意味着-diff -merge -text 和-text eol 属性变得不相关)。
所以,到目前为止,我们得到的是:当且仅当 Git 猜测它是文本时,文件才是文本,并且 eol 属性未指定。
git config core.autocrlf false # I guess git attributes overrides this anyway?
text 属性专门覆盖了这个。 The gitattributes documentation 部分表示:
如果未指定 text 属性,Git 使用
core.autocrlf配置变量判断文件是否
应该转换。
这并没有说明如果text 属性是指定的 会发生什么(它是,auto),但稍微回顾一下,我们发现text=auto :
如果 Git 确定内容是文本,则在签入时将其行尾转换为 LF。使用 CRLF 提交文件后,不会进行任何转换。
这里只讨论checkin。文档没有这么说,但这确实是在 git add 期间,Git 可能会将 CRLF 变成 LF-only。
git add t.txt # wait what? warning: LF will be replaced by CRLF in t.txt???
Git 在git add 期间发出这些警告(除非它们通过其他配置被抑制),当它发现任何可疑时。警告是或至少包括您所看到的,我有时称之为措辞不当(因为没有更好的术语)。不过,我没有更好的方式来表达它们,而不是太冗长以至于它变得有问题。
警告:详细 = 此处有问题的描述 ?
只有两个内置的 LF/CRLF 转换:
-
将 CRLF 转换为仅 LF 的“正在进行中”的转换:仅在 git add 期间发生这种情况,并且仅在需要或似乎需要调用时才发生。
-
将 LF-only 转换为 CRLF 的“即将退出”转换:这发生在 git checkout、git reset --hard、git restore(如果使用显式或隐含的 --worktree 运行)和其他类似操作期间.但是,就像正在进行的 CRLF 到 LF 转换一样,它只有在需要或似乎需要时才会发生。
这里发生的情况是,Git 怀疑您将在未来某个时间发生 LF 到 CRLF 的转换。我认为你的设置现在没有这样配置,因为你有!eol并且在Linux上(你在Linux上?也许不是:你在版本字符串中说windows)。所以也许你的设置是现在这样配置的,因为你有!eol并且在Windows上。我不使用 Windows,所以我不确定 Windows 上的默认设置是什么是。
与此同时,t.txt,在您的索引和工作树中都可以看到,具有纯 LF-only 行结尾。如果 Git 执行一个在途的 LF 到转换(从索引副本到工作树副本),你的 工作树 中的 t.txt 文件会突然有 CRLF 行结尾.
这就是这个警告信息的意思。如果将来 Git 对文件进行文本转换,则提取 Git 索引中现在的内容的结果将与 工作树中的 actual 文件不匹配 现在。 Git可以在这里进行的一种转换是将 LF-only 转换为 CRLF,t.txt 目前是 LF-only。
到最后几个步骤
git commit -m 'the plot thickens'
这里的情节并没有真正变厚。所有转换都发生在此之前。提交命令仅获取存储在 Git 索引中的 t.txt 文件(这是 Git 索引中的唯一文件,因为存储库是全新的)并从中进行提交。
git cat-file -p `git rev-parse HEAD:t.txt` > temp.txt
# get raw blob as its really stored, I hope
确实如此,是的。您同样可以从索引中获取:t.txt,或使用git ls-files --stage 获取blob 哈希ID。
注意git commit 步骤没有修改工作树副本。它仍然没有受到影响。要强制 Git 将索引副本提取回工作树,首先删除工作树副本,然后使用任何将重新创建它的 Git 命令。这将运行提取步骤,该步骤将(或不会)根据您的各种配置要求将 LF-only 转换为 CRLF:
rm t.txt
git checkout -- t.txt
您现在可以使用od 或类似名称查看发生了什么。 \n 变成 \r\n 了吗?这告诉你 Git 如何解释你当前的设置(core.autocrlf、core.eol,以及.git/info/attributes 和.gitattributes 中的各种属性)。
注意:git ls-files --eol 从 Git 2.8 开始,能够告诉你更多关于这里发生的事情。它将分别:
- 检查索引中的内容;
- 检查工作树中的内容;和
- 查看适用的属性
到当前在索引中的每个文件。