git clone git@github.com:erocarrera/pydot
的Debian中的 git config core.autocrlf input
(35a8d858b)显示:
modified: test/graphs/b545.dot
modified: test/graphs/b993.dot
modified: test/graphs/cairo.dot
这些文件具有CRLF行结尾,例如:
$ file test/graphs/cairo.dot
test/graphs/cairo.dot: UTF-8 Unicode text, with CRLF line terminators
.gitattributes
文件contains:
*.py eol=lf
*.dot eol=lf
*.txt eol=lf
*.md eol=lf
*.yml eol=lf
*.png binary
*.ps binary
更改core.autocrlf
对这些文件的状态没有影响。删除.gitattributes
也没有效果。使用dos2unix
更改这些文件不会更改其状态(按预期方式),而使用unix2dos
返回时与diff
相比,与旧版本无差异。使用ls -lsa
,文件权限不会改变。此外,就vi -b
而言,文件具有统一的行结尾(因此不应该是unix2dos
或dos2unix
从混合行转换为统一行结尾的情况,可以解释这种奇怪的行为)。我正在使用git
版本2.11.0。
git
认为改变了什么?
有点相关:
在我搜索几个讨论期间,我没有找到解释此行为的答案。此问题源自pydot
# 163。
更详细:
git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: test/graphs/b545.dot
modified: test/graphs/b993.dot
modified: test/graphs/cairo.dot
no changes added to commit (use "git add" and/or "git commit -a")
git diff test/graphs/b993.dot
warning: CRLF will be replaced by LF in test/graphs/b993.dot.
The file will have its original line endings in your working directory.
diff --git a/test/graphs/b993.dot b/test/graphs/b993.dot
index e87e112..8aa0872 100644
--- a/test/graphs/b993.dot
+++ b/test/graphs/b993.dot
@@ -1,10 +1,10 @@
-diGraph G{
-graph [charset="utf8"]
-1[label="Umlaut"];
-2[label="ü"];
-3[label="ä"];
-4[label="ö"];
-1->2;
-1->3;
-1->4;
-}
+diGraph G{
+graph [charset="utf8"]
+1[label="Umlaut"];
+2[label="ü"];
+3[label="ä"];
+4[label="ö"];
+1->2;
+1->3;
+1->4;
+}
更新:
出于好奇,我提交了其中一个文件,转储git log -1 -p > diff
,vi -b diff
显示git
标准化
1 commit 2021d6adc1bc8978fa08d729b3f4d565f9b89651
2 Author:
3 Date:
4
5 DRAFT: experiment to see what changed
6
7 diff --git a/test/graphs/b545.dot b/test/graphs/b545.dot
8 index ebd3e8f..2c33f91 100644
9 --- a/test/graphs/b545.dot
10 +++ b/test/graphs/b545.dot
11 @@ -1,9 +1,9 @@
12 -digraph g {^M
13 -^M
14 -"N11" ^M
15 - [^M
16 - shape = record^M
17 - label = "<p0>WFSt|1571 as Ref: 1338 D"^M
18 -]^M
19 -N11ne -> N11:p0^M
20 -}^M
21 +digraph g {
22 +
23 +"N11"
24 + [
25 + shape = record
26 + label = "<p0>WFSt|1571 as Ref: 1338 D"
27 +]
28 +N11ne -> N11:p0
29 +}
其他奇怪的观察结果:git checkout
克隆后的任何这些文件都没有任何效果。 在上述提交之后,文件b545.dot
继续在工作目录中具有CLRF行结尾。应用dos2unix
后跟unix2dos
并不会使git
认为它已更改(而在提交之前,可能是因为已提交的文件具有CLRF行结局)。
答案 0 :(得分:3)
这恰好发生在,因为这些文件 是通过CRLF结尾提交的,但.gitattributes
文件表示只使用LF结尾提交它们。
Git可以并且将在两个地方进行CRLF-vs-LF转换:
从索引到工作树的提取过程中。存储在提交或索引中的文件始终假定为&#34; clean&#34;状态,但是当从索引中提取该文件到工作树时,Git应该以{#1}}的形式应用.gitattributes
指示的任何转换,例如,改变LF-only到CRLF&#34;以及Git称之为涂抹过滤器的形式。
在从工作树复制文件到索引期间。存储在工作树中的文件位于&#34;污迹&#34;在这一点上,Git应该应用任何&#34;清洁&#34;转换:例如,将CR-LF更改为仅LF,并应用清理过滤器。
请注意,可以发生这两种转换。这并不意味着他们将发生在两个点上,只是这些是两个可能的地方。正如.gitattributes
文档说明的那样,实际转换是:
eol=lf
:无索引 - &gt;工作树;仅在工作树上使用CR-LF到LF - &gt;索引eol=crlf
:LF-only to CR-LF on index - &gt;工作树;工作树上没有 - &gt;索引现在,存储在提交中的存储库中实际存在的文件纯粹是只读的。它可以永远在提交内部进行更改。更确切地说,提交(通过散列ID)标识(通过散列ID)标识具有其具有的任何内容的blob的树。这些哈希ID本身就是对象内容的加密校验和,因此它们自然都是只读的:如果我们尝试更改内容,我们得到的是具有新的不同哈希ID的新的不同对象。
因为git checkout
实际上是通过将提交树中的原始哈希ID复制到索引来实现的,所以索引中存储的文件版本必须与提交中存储的文件版本相同。
因此,如果以某种方式 - 无论如何 - 提交的文件的形式与.gitattributes
指示Git要做的事情不一致,那么这些文件将会变得非常糟糕。 #34;在工作树中,无论你没有对他们做任何事情!如果你有git add
这三个文件,那么它们会将它们从工作树复制到索引,因此从它们的行结尾中删除回车符。因此,它们以git status
的形式被修改但尚未进行提交。
在工作树版本中删除回车会使它们处于相同的状态:它们会根据索引中的内容进行修改,因为git add
现在将保留其LF - 只有行结尾不变,产生索引中的新的不同文件。
一个更有趣的问题是:他们是如何进入处于错误状态的提交的?这不是我们可以回答的问题:只有那些提交这些提交的人才能产生这样的答案。我们只能推测。实现此目的的一种方法是在没有.gitattributes
生效的情况下添加和提交文件,然后将.gitattributes
设置为生效而不再使用git add
文件。这样,CR-LF结尾进入某人的索引,因此进入该用户的提交,即使.gitattributes
文件现在表示(但没有早先说)任何 new git add
都应该去掉回车。
答案 1 :(得分:2)
更改
core.autocrlf
不会影响这些文件的状态
它应该,但只有在再次克隆之后:
git config --global core.autocrlf false
git clone git@github.com:erocarrera/pydot pydot2
cd pydot2
git status
这会在全球范围内停用core.autocrlf
,但这只是为了测试。
答案 2 :(得分:1)
感谢@torek的解释(同意我的conjecture)。
总之,非对称git
配置导致commit(checkout(Index))
不是身份映射。在索引中使用CRLF时,此特定配置检出CRLF,但在生效的输入转换(eol=lf
)之后,git
将提交LF而不是CRLF。
这种混淆的根本原因是比较:
这并不表示文件是否已更改。在将输入转换应用于已提交的内容之后,应该比较的是git
将提交的内容。显然,如果这两个项目不同,则文件已更改。
根据这个推理,可以声明存储库&#34;不稳定&#34;,因为它认为自己在没有与世界交互的情况下被修改。这支持通过将提交的文件更改为LF或更改.gitattributes
(我更喜欢提交LF)来避免此状态。
在这种情况下,git
将为工作目录中的LF和CRLF提交LF,因此dos2unix
和unix2dos
对提交结果没有影响,因此对于提交结果都没有影响档案的状态。