Git showing identical files as changed

强颜欢笑 提交于 2021-02-05 19:59:37

问题


Git is showing me an entire file is changed, when I can't seem to figure out the changes. This is cygwin git, but it also happens in 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

I have

$ git config --get core.fileMode
false

and

$ git config --get core.autocrlf
true

I truly have no idea what's going on, everything wants them to be the same, yet git wants to create a commit saying the entire contents was deleted and recreated. Does anyone who knows git plumbing better have a suggestion?. All I can think of is git show is removing/normalizing odd line endings.

UPDATE:

I'm pretty sure its happening because development process is like this. Checkout from git, rsync to dev machine, develop, rsync back. I believe rsync is messing with the line endings some. It's just weird that gits not reporting about the line endings, and it seems to get really confused about what the hell is happening. Even though diffing the binary representation of the files seem to be identical.

UPDATE 2:

So this is super annoying, and I feel like I have stumbled upon a bug in git.

For instance

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

> shows a heap of modified files

I'm pretty sure that should show no changes, no matter where its run, but I get a list of 20 odd things :(


回答1:


This can be caused by a .gitattributes file indicating to git that it should do EOL normalization but the repository containing non-normalized line endings.

The simple fix is to remove the relevant line from .gitattributes. This could be

* text=auto

or

*.cs text

A quick example of how this could happen goes like this:

$ 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"

Now the repository is in a strange state, because .gitattributes claims the file should be normalized before adding it to the index, but the current committed version is not normalized.

However, at this point, git status doesn't notice that, because the file itself has not changed in size or mtime since it was added to the index, so the index is considered to be up to date:

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

But anything which invalidates the index will cause git to consider the file to be dirty:

$ 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")

And git reset --hard or any other action to try to reset the file to the state it's supposed to be in will not fix this. This is because there is no way to add the file to the index in it's current state as it is in the repository, because git has been instructed to normalize that file, and that normalization cannot ever produce the object as it currently is committed.

This is why the GITATTRIBUTES(1) man page recommends to explicitly invalidate the entire index when introducing line-ending normalization like so:

$ 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"

Read the section on "End-of-line conversion" in the gitattributes man page for more details.

Instead of going with the quick fix of just removing that line from .gitattributes, you may want to instead keep the line ending normalization rules and go ahead and normalize them now. That basically just means committing the 20+ changes that won't go away, but you can do so methodically by following the above instructions about introducing line ending normalization (minus editing the .gitattributes), and then feeling confident that it won't happen again, because all the files are now committed with normalized endings, and any future files you add will also be normalized. It's personal preference, mostly.



来源:https://stackoverflow.com/questions/26542226/git-showing-identical-files-as-changed

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!