【问题标题】:Git showing identical files as changedGit 将相同的文件显示为已更改
【发布时间】:2014-10-24 05:48:52
【问题描述】:

当我似乎无法弄清楚更改时,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 到开发机器,开发,rsync 返回。我相信 rsync 弄乱了一些行尾。 gits 没有报告行尾,这很奇怪,而且似乎对到底发生了什么感到非常困惑。即使区分文件的二进制表示似乎是相同的。

更新 2:

所以这非常烦人,我觉得我偶然发现了 git 中的一个错误。

例如

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

> shows a heap of modified files

我很确定它应该不会显示任何变化,无论它在哪里运行,但我得到了一个包含 20 件奇怪事情的列表:(

【问题讨论】:

  • 你对git config --get core.autocrlf false也有同样的看法吗?
  • 是的,同样的事情。我什至确保使用git rm --cached . -r 和git reset --hard 将其全部取消。然后我通过开发工具运行它,转到git status 并得到整个文件已“更改”。我愿意接受我的过程正在更改文件(我想是行尾),但我希望 git 能够真正告诉我如何。这让我很困惑,尤其是考虑到哈希对象的输出是一样的。
  • 你使用的是什么操作系统和git版本?
  • Cygwin,所以是 windows。具体 7. Git 版本是 2.1.1 如上面的代码块。一个有趣的旁注是,git reset --hard 或 git checkout -- . 不会删除此文件。所以 git 的那些部分认为文件没有改变并且不会覆盖磁盘上的内容,但是 diff 提交的一半会! :(
  • 您能在简单的 DOS 会话中尝试使用常规的 msysgit 1.9.4 吗?

标签: git cygwin


【解决方案1】:

这可能是由一个 .gitattributes 文件向 git 指示它应该进行 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 已被指示规范化该文件,并且规范化永远无法生成当前提交的对象。

这就是为什么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)有条不紊地这样做,然后确信它不会消失再次发生,因为所有文件现在都以规范化结尾提交,并且您添加的任何未来文件也将被规范化。主要是个人喜好。

【讨论】:

    猜你喜欢
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 2021-11-19
    相关资源
    最近更新 更多