'git status' 显示了修改过的文件,但是 'git diff' 没有。

284

我已经查看了所有类似的问题。然而,我进行了双重检查,肯定发生了一些奇怪的事情。

在一个服务器上(Solaris带有Git 1.8.1),我克隆了Git存储库,然后将.git文件夹复制到我的现有实时文件中。这完美地运行了,我可以运行

git status

然后

git diff [filename]

检查任何不同的文件。

在另一个服务器上(使用 Git 1.7.6 的 Solaris),我正在进行完全相同的操作。

git diff [filename]

即使文件内容明显不同,也不显示任何内容。我还尝试添加新文件,提交它,然后进行编辑。相同的问题,git status 显示该文件已更改,但 git diff 什么也没有显示。如果我下载更改的文件并在本地运行 diff,那么我会得到 diff 输出。


16
它是否在你的索引中?如果是的话,你可以用 git diff --cached 查看差异。 - jeremyharris
4
git diff --cached 命令也没有输出任何内容。 - Oliver P
git log 也没有输出。 - Oliver P
假设确实存在一个错误,你应该能够创建一个最小的示例。尝试复现并分享这个样本。 - mheinzerling
  1. 文件模式已更改?在此处查找“core.fileMode”选项[http://www.kernel.org/pub/software/scm/git/docs/git-config.html]。
  2. 另外,当Console2实际运行时,我也遇到了类似的问题,因为可能会出现文件锁定,使得git认为文件已更改。
- madhead
18个回答

3
我刚遇到了类似的问题。使用git diff file时未显示任何内容,因为我将文件添加到Git索引中,但其名称的某些部分为大写:GeoJSONContainer.js
之后,我将其重命名为GeoJsonContainer.js,更改已经停止跟踪。使用git diff GeoJsonContainer.js未显示任何内容。我不得不强制删除索引中的文件,并重新添加该文件:
git rm -f GeoJSONContainer.js
git add GeoJSONContainer.js

2

我对您使用情况的假设:

您有一个包含文件和目录的现有目录,现在想将其转换为从其他地方克隆的Git仓库,而 不更改 当前目录中的任何数据。

实际上有两种方法。

克隆存储库 - mv .git - git reset --hard

这种方法是您所使用的方法 - 将现有存储库克隆到空目录中,然后将 .git 目录移动到目标目录中。为了无问题地工作,通常需要运行以下命令:

git reset --hard

然而,这会改变您当前目录中文件的状态。您可以在完整副本/ rsync上尝试此操作,并研究更改。至少之后,您不应再看到git logstatus之间的差异。
初始化新存储库 - 指向原始点
第二个问题较小:进入目标文件夹,并使用以下命令启动新存储库:
git init

然后您要告诉新的仓库,它有一个祖先在其他地方:

git remote add origin original_git_repo_path

然后安全地执行。
git fetch origin master

将数据复制到本地文件而不更改本地文件。现在一切都应该没问题了。

我总是推荐第二种方式,因为它更可靠。


你似乎在暗示这是一个 git 错误。好的,可能是。我仍然认为我缺乏正确的 git 理解,因为我不像 Linus 那么聪明;-) - towi
@towi:不,我并不是在暗示这是一个git错误,也不是在暗示相反的情况。我对git的内部机制不太熟悉。但是作为一个经验法则,通过将.git文件夹移动到其他工作区域,我们可能会违反git的假设。如果这导致不稳定的行为,我们不能责怪git,而是要责怪自己在玩弄git。git提供了修复的方法,例如reset --hard。只是这不是我们想要的。这正是为什么推荐使用init/remote add方式的原因,一切都很好。 - cfi
@towi 和 Oliver P:虽然我理解您想要解决特定错误案例,但有时候只是建议按照一般推荐方式操作 - 特别是如果它们完全适合您的用例。也不会有数据丢失。而且 remote add 的操作方式仍然可以应用于像 Oliver P 描述的混乱情况。 - cfi
1
一个没有评论的踩票并不能帮助改进这个答案,也不能帮助整个网站。无论谁踩票,请留下评论以便解决问题。 - cfi

2

许多其他答案提到了行尾和core.autocrlf设置的差异。这确实可能是问题所在,但我想指出另一个类似的问题:git过滤器

如果core.autocrlf=true,那么行为就像一个git smudge或clean过滤器,它会自动处理文本,使其在工作树和索引之间移动。

同样,如果您自上次提交文件以来更改了git过滤器设置,可能会导致在git status中出现难以捉摸的差异,而这些差异在git diff中并不显示。这种难以捉摸的差异可能仍然存在,即使在git add X; git diff --cached -- X之后,具体取决于配置的过滤器的性质。

我在使用nbstripout时遇到了这个问题,它是一个Python包,实现了Git过滤器,在将Jupyter笔记本文件添加到索引和差异之前过滤掉元数据。我通过将过滤器配置设置恢复到之前的状态,对受影响的文件运行git restore,然后重新应用更改到我的过滤器配置中来解决了这个问题(因为我想长期保留新的设置)。对于我来说,这些设置存储在.git/config下的filter.nbstripoutdiff.ipynb部分。


1

我曾经遇到过以下描述的同样问题: 如果我输入

$ git diff

Git 没有报错,直接返回了提示符。

如果我输入:

$ git diff <filename>

Git 没有错误��返回了提示符。

最后,通过阅读周围的内容,我注意到 git diff 实际上调用了 mingw64\bin\diff.exe 来完成工作。

问题在于,我正在运行 Windows,并安装了另一个 Bash 实用程序,它更改了我的路径,因此不再指向我的 mingw64\bin 目录。

因此,如果您键入:

git diff

如果它只是返回到提示符,您可能会遇到此问题。

git 运行的实际 diff.exe 位于 mingw64\bin 目录中。

最后,为了修复这个问题,我实际上将我的 mingw64\bin 目录复制到 Git 所寻找的位置。我尝试了一下,但仍然不起作用。

然后,我关闭了 Git Bash 窗口,重新打开它并转到失败的同一存储库,现在它可以工作了。


1
我再次遇到了这个问题,但这次发生的原因不同。我将文件复制到仓库中以覆盖以前的版本。现在我可以看到文件已经被修改,但是diff没有返回差异。
例如,我有一个mainpage.xaml文件。在文件资源管理器中,我将一个新的mainpage.xaml文件粘贴到当前仓库中的文件上。我在另一台机器上完成了工作,然后将文件粘贴到这里。

Git shows modified

文件显示已修改,但运行git diff时,不会显示更改。
这可能是因为文件的文件信息已更改,Git 知道它实际上不是同一个文件。有趣。

Git diff shows nothing

你可以看到,当我在文件上运行diff时,它不会显示任何内容,只是返回提示符。

1

git diff -a 将所有文件视为文本,并且对我有用。


0
我最近从Windows切换到Linux,并保持了我的工作git仓库不变。当我运行git diff时,它显示每个文件的每一行都被更改;当我运行git diff --cached时,它显示没有文件被更改。 git restore .解决了我的问题。

0

我使用了git svn,并且在一个文件上遇到了这个问题。对于文件的每个祖先,我使用ls-tree,发现其中一个有2个子文件夹-Submitsubmit。由于我在Windows上,它们不能同时被检出,导致了这个问题。

解决方案是直接从TortoiseSVN Repo-browser中删除其中一个,然后运行git svn fetch,接着运行git reset --hard origin/trunk


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接