微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

git 行结尾行为与文档不匹配 警告:详细=此处有问题的描述?进入最后几步

如何解决git 行结尾行为与文档不匹配 警告:详细=此处有问题的描述?进入最后几步

我看到 git 以行结尾做事,这似乎与我在本网站和官方文档上看到的所有内容相矛盾,甚至与它自己的警告消息相矛盾。 (或者我可能在阅读理解方面失败了。)这是一个小复制。

# repro.sh
git --version # 2.27.0.windows.1
mkdir empty
cd empty
echo '* text=auto !eol' > .gitattributes
echo hi > t.txt
git init
git config core.autocrlf false # I guess git attributes overrides this anyway?
git add t.txt # wait what?  warning: LF will be replaced by CRLF in t.txt???  I thought git likes LF?
git commit -m 'the plot thickens'
git cat-file -p `git rev-parse HEAD:t.txt` > temp.txt # get raw blob as its really stored,I hope
od -c t.txt # original file in working dir ends in LF
od -c temp.txt # file from git also ends in LF,despite git warning??
# end of script

这有意义吗?我认为 git 有时喜欢在“git add”上将 CRLF 转换为普通 LF 并在结账时执行相反的操作,但我从未听说过它在 git add 上将普通 LF 转换为 CRLF,因为警告似乎有威胁。然后它不这样做。检入的文件正是我在我的工作目录中拥有的文件,正如 cat-file.conf 所验证的那样。那么为什么要发出警告呢?怎么回事?

解决方法

消息本身似乎总是有点......错了?奇怪的?措辞不当? - 我不知道该怎么称呼它。该消息的意图是警告您有些事情似乎不一致:您将来查看文件的方式可能与您现在查看文件的方式不兼容。

考虑到这一点,让我们进入细节:

echo '* text=auto !eol' > .gitattributes

首先,在 text=auto 上:这将 text 属性设置为字符串值 auto,它告诉 Git:请猜测每个文件是文本文件还是二进制文件.我个人认为这是一个坏主意:你不想让 Git 猜测。你应该告诉它。 Git 的猜测通常很好,但我不喜欢我的软件猜测那么多。 :-)

无论如何,让我们继续讨论 !eol:这意味着将 eol 属性设置为 unspecified 状态。这可能不是您想要的。它开始未指定,因此如果您不想指定它,您可以不指定它。 ! 前缀存在以便您可以更正一些以前的设置:例如,如果默认值应该是 eol=lf,您可能有:

* eol=lf

但由于不应修改 JPG 文件,因此我们可以仅针对 *.jpg 覆盖它:

*.jpg !eol

(虽然 *.jpg binary 可能更好:它意味着 -diff -merge -text 并且对于 -texteol 属性变得无关)。

所以,到目前为止,我们所拥有的是:一个文件是文本,当且仅当 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 提交文件后,不会进行任何转换。

这里只讨论签入。文档没有说明这一点,但这确实是在 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-only 的“in the way in”转换:这仅在 git add 期间发生,并且仅当它被调用或似乎被调用时才会发生。>

  • 将 LF-only 转换为 CRLF 的“在出路”转换:这发生在 git checkoutgit reset --hardgit 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 索引中的内容的结果将与您的工作树中的实际文件不匹配现在。 Git 可以在这里做的一种转换是将 LF-only 变成 CRLF,而 t.txt 目前是 LF-only。

进入最后几步

git commit -m 'the plot thickens'

这里的情节并没有真正变厚。所有转换都发生在此之前。 commit 命令仅获取存储在 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.autocrlfcore.eol 以及 .git/info/attributes.gitattributes 中的各种属性)。

注意:从 Git 2.8 开始,git ls-files --eol 能够告诉你更多关于这里发生的事情。它将分别:

  • 检查索引中的内容;
  • 检查工作树中的内容;和
  • 查看哪些属性适用

到当前在索引中的每个文件。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。