Git显示相同的文件已更改

时间:2014-10-24 05:48:53

标签: git cygwin

当我无法弄清楚这些变化时,Git正在向我展示整个文件已被更改。这是cygwin git,但它也发生在msysgit

$ git --version
git version 2.1.1

$ diff <(git show HEAD:File.cs) <(cat File.cs)
// Shows no differences

$ diff <(git show HEAD:File.cs | xxd) <(xxd File.cs)
// Shows no differences

$ git diff
// shows the entire file has changed

$ git hash-object <(git show HEAD:File.cs)
7b3762473342a5b040835bfef9f6b45c109ba48b

$ git hash-object <(cat File.cs)
7b3762473342a5b040835bfef9f6b45c109ba48b

$ git hash-object File.cs
7b3762473342a5b040835bfef9f6b45c109ba48b

我有

$ git config --get core.fileMode
false

$ git config --get core.autocrlf
true

我真的不知道发生了什么,一切都希望它们是相同的,但是git想要创建一个提交,说明整个内容已被删除并重新创建。知道git管道的人有没有更好的建议?我能想到的只是git show正在删除/标准化奇数行结尾。

更新:

我很确定它的发生,因为开发过程是这样的。从git结账,rsync到dev机器,开发,rsync回来。我相信rsync会破坏一些行结尾。 gits没有报告关于行结尾的事情,这很奇怪,似乎真的很困惑到底发生了什么。尽管差异文件的二进制表示看起来是相同的。

更新2:

所以这太烦人了,我觉得我偶然发现了一个git中的bug。

例如

$ git gc
$ git checkout -- .
$ git clean -fd
$ git status

> shows a heap of modified files

我很确定无论在哪里都不会显示任何变化,但我会得到20个奇怪的列表:(

1 个答案:

答案 0 :(得分:19)

这可能是由.gitattributes文件引起的,该文件指示它应该执行EOL规范化,但是包含非规范化行结尾的存储库。

简单的解决方法是从.gitattributes中删除相关行。这可能是

* text=auto

*.cs text

这可能发生的一个简单示例如下:

$ echo "Hello World" > example.txt
$ unix2dos example.txt #Make sure it uses CRLF
$ git add example.txt
$ git commit -m "commit 1"
$ #Instruct git that all .txt files should be normalized
$ echo '*.txt text' >> .gitattributes 
$ git add .gitattributes
$ git commit -m "commit 2"

现在存储库处于一种奇怪的状态,因为.gitattributes声明文件应该在将其添加到索引之前进行规范化,但是当前提交的版本没有规范化。

但是,此时,git status没有注意到,因为文件本身在大小或mtime中没有改变,因为它已添加到索引中,因此索引被认为是最新的:

$ git status
On branch master
nothing to commit, working directory clean

但是使索引无效的任何事情都会导致git认为该文件是脏的:

$ touch example.txt
On branch master
Changes not staged for commit:

        modified:   example.txt

no changes added to commit (use "git add" and/or "git commit -a")

并且git reset --hard或尝试将文件重置为其应该处于的状态的任何其他操作都无法解决此问题。这是因为没有办法将文件添加到索引中的当前状态,因为它在存储库中,因为已经指示git规范化该文件,并且规范化不能生成当前提交的对象。 / p>

这就是为什么GITATTRIBUTES(1)手册页建议在引入行结束规范化时明确地使整个索引无效的原因如下:

$ echo "* text=auto" >>.gitattributes
$ rm .git/index     # Remove the index to force Git to
$ git reset         # re-scan the working directory
$ git status        # Show files that will be normalized
$ git add -u
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"

有关详细信息,请阅读gitattributes手册页中有关“行尾转换”的部分。

您可能希望保留行结束规范化规则并继续并将其标准化,而不是使用从.gitattributes中删除该行的快速修复。这基本上只是意味着提交不会消失的20多个更改,但是你可以通过遵循上面关于引入行结束规范化的指令(减去编辑.gitattributes)来有条不紊地做,然后确信它赢了再次发生,因为现在所有文件都使用标准化结尾进行提交,并且您添加的任何未来文件也将被标准化。这主要是个人偏好。