`git` 显示克隆后更改的文件,无需任何其他操作

Ioa*_*dis 3 git newline eol gitattributes core.autocrlf

git clone git@github.com:erocarrera/pydot( 35a8d858b ) 在 Debian 中git config core.autocrlf input显示:

\n\n
modified:   test/graphs/b545.dot\nmodified:   test/graphs/b993.dot\nmodified:   test/graphs/cairo.dot\n
Run Code Online (Sandbox Code Playgroud)\n\n

这些文件具有 CRLF 行结尾,例如:

\n\n
$ file test/graphs/cairo.dot\ntest/graphs/cairo.dot: UTF-8 Unicode text, with CRLF line terminators\n
Run Code Online (Sandbox Code Playgroud)\n\n

.gitattributes文件包含

\n\n
*.py eol=lf\n*.dot eol=lf\n*.txt eol=lf\n*.md eol=lf\n*.yml eol=lf\n\n*.png binary\n*.ps binary\n
Run Code Online (Sandbox Code Playgroud)\n\n

更改core.autocrlf不会影响这些文件的状态。删除.gitattributes也没有效果。更改这些文件dos2unix不会改变它们的状态(如预期),并且返回显示与旧副本unix2dos没有区别。diff文件权限看起来没有变化ls -lsa。另外,据我所知,这些文件具有统一的行结尾vi -b(因此不应该是这种情况unix2dos,或者dos2unix从混合行结尾转换为统一的行结尾,这可以解释这种奇怪的行为)。我使用的是git2.11.0 版本。

\n\n

什么是git变化?

\n\n

有点相关:

\n\n
    \n
  1. 即使内容相同,Git 状态也会显示文件已更改
  2. \n
  3. git clone 之后直接显示为已修改的文件
  4. \n
  5. 克隆一个 git 存储库,它已经有一个肮脏的工作目录......Whaaaaa?
  6. \n
\n\n

在多次讨论的搜索过程中,我没有找到解释此行为的答案。这个问题源自pydot#163

\n\n

更详细地说:

\n\n
git status\n\nOn branch master\nYour branch is up-to-date with \'origin/master\'.\nChanges not staged for commit:\n  (use "git add <file>..." to update what will be committed)\n  (use "git checkout -- <file>..." to discard changes in working directory)\n\n    modified:   test/graphs/b545.dot\n    modified:   test/graphs/b993.dot\n    modified:   test/graphs/cairo.dot\n\nno changes added to commit (use "git add" and/or "git commit -a")\n\ngit diff test/graphs/b993.dot\n\nwarning: CRLF will be replaced by LF in test/graphs/b993.dot.\nThe file will have its original line endings in your working directory.\ndiff --git a/test/graphs/b993.dot b/test/graphs/b993.dot\nindex e87e112..8aa0872 100644\n--- a/test/graphs/b993.dot\n+++ b/test/graphs/b993.dot\n@@ -1,10 +1,10 @@\n-diGraph G{\n-graph [charset="utf8"]\n-1[label="Umlaut"];\n-2[label="\xc3\xbc"];\n-3[label="\xc3\xa4"];\n-4[label="\xc3\xb6"];\n-1->2;\n-1->3;\n-1->4;\n-}\n+diGraph G{\n+graph [charset="utf8"]\n+1[label="Umlaut"];\n+2[label="\xc3\xbc"];\n+3[label="\xc3\xa4"];\n+4[label="\xc3\xb6"];\n+1->2;\n+1->3;\n+1->4;\n+}\n
Run Code Online (Sandbox Code Playgroud)\n\n

更新:

\n\n

出于好奇,我提交了其中一个文件,转储git log -1 -p > diff,并vi -b diff表明git标准化

\n\n
  1 commit 2021d6adc1bc8978fa08d729b3f4d565f9b89651\n  2 Author:\n  3 Date:\n  4 \n  5     DRAFT: experiment to see what changed\n  6 \n  7 diff --git a/test/graphs/b545.dot b/test/graphs/b545.dot\n  8 index ebd3e8f..2c33f91 100644\n  9 --- a/test/graphs/b545.dot\n 10 +++ b/test/graphs/b545.dot\n 11 @@ -1,9 +1,9 @@\n 12 -digraph g {^M\n 13 -^M\n 14 -"N11" ^M\n 15 -  [^M\n 16 -  shape = record^M\n 17 -  label = "<p0>WFSt|1571       as Ref: 1338    D"^M\n 18 -]^M\n 19 -N11ne -> N11:p0^M\n 20 -}^M\n 21 +digraph g {\n 22 +\n 23 +"N11" \n 24 +  [\n 25 +  shape = record\n 26 +  label = "<p0>WFSt|1571       as Ref: 1338    D"\n 27 +]\n 28 +N11ne -> N11:p0\n 29 +}\n
Run Code Online (Sandbox Code Playgroud)\n\n

其他奇怪的观察结果:git checkout克隆后的任何这些文件都没有任何效果。上述提交后,文件b545.dot在工作目录中继续具有 CLRF 行结尾。应用dos2unix后跟并unix2dos没有让人认为git它已经改变(而在提交之前它确实发生了变化,可能是因为提交的文件具有 CLRF 行结尾)。

\n

tor*_*rek 5

发生这种情况正是因为这些文件是以CRLF 结尾提交的,但.gitattributes文件却说要以仅 LF 结尾提交它们。

\n\n

Git 可以并且将会在两个地方进行 CRLF-vs-LF 转换:

\n\n
    \n
  • 从索引提取到工作树期间。存储在提交或索引中的文件始终假定处于“干净”状态,但是当从索引中提取该文件到工作树时,Git 应该应用以“.gitattributes更改”形式指示的任何转换例如,从 LF-only 到 CRLF”,也采用 Git 所谓的涂抹过滤器的形式。

  • \n
  • 将文件从工作树复制回索引期间。存储在工作树中的文件处于“污迹”状态,因此此时,Git 应该应用任何“清理”转换:例如,将 CR-LF 更改为仅 LF,并应用清理过滤器

  • \n
\n\n

请注意,这些转换可能在两个点发生。这并不意味着它们同时发生在这两个点,只是这两个可能的地方。正如.gitattributes文档所述,实际的转换是:

\n\n
    \n
  • eol=lf:索引上没有 -> 工作树;工作树上的 CR-LF 到 LF-only -> 索引
  • \n
  • eol=crlf:索引 -> 工作树上仅 LF 到 CR-LF;工作树上没有 -> 索引
  • \n
\n\n

现在,实际上存储在存储库中、存储在提交中的文件是纯粹只读的。它永远不会在该提交内更改。更准确地说,提交标识(通过哈希 ID)一棵树,该树标识(通过哈希 ID)具有任何内容的 Blob。这些哈希 ID 本身就是对象内容的加密校验和,因此它们自然都是只读的:如果我们尝试更改内容,我们得到的将是一个新的、不同的对象,具有新的、不同的哈希 ID。

\n\n

因为git checkout实际上是通过将原始哈希 ID 从提交树复制到索引来工作的,所以存储在索引中的文件版本必须与存储在提交中的文件版本相同。

\n\n

因此,如果以某种方式 \xe2\x80\x94 不管\ xe2\x80\x94 提交的文件的形式与 Git 的指示不符.gitattributes,那么无论事实如何,这些文件都将在工作树中变得“脏”你没有对他们做任何事如果您要查看git add相关的三个文件,则会将它们从工作树复制到索引,从而删除行结尾处的回车符。因此,就术语而言,它们已git status被修改但尚未准备提交。

\n\n

去掉工作树版本中的回车符会使它们处于相同的状态:它们根据索引中的内容进行修改,因为git add现在将保持它们的仅 LF 行结尾不变,从而产生新的不同的行尾索引中的文件。

\n\n

一个更有趣的问题是:他们是如何以错误的状态进入提交的? 这不是我们可以回答的问题:只有那些做出这些承诺的人才能给出答案。我们只能推测。实现此目的的一种方法是在不生效的情况下添加并提交文件.gitattributes,然后将文件设置为.gitattributes生效而无需git add再次使用 -ing 文件。这样,CR-LF 结尾就会进入某人的索引,从而进入该用户的提交,即使文件.gitattributes现在(但之前没有说)任何新的 git add都应该去掉回车符。

\n