'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个回答

145

对我来说,这与文件权限有关。我的Windows Git客户端未能复制某些带有非默认权限的Mac/Linux项目提交的文件。

对我来说,解决方案是告诉Git忽略文件权限:

git config core.fileMode false

其他信息: 如何使Git忽略文件模式(chmod)更改?


2
这解决了我在一堆文件中遇到的问题,尽管我认为问题出在文件的创建/修改时间上。 - Derek
这对我解决了问题。fileMode值在Mac/Linux卷上似乎默认为true,在Windows卷上默认为false。我将一个项目从Mac移动到Windows,需要将其切换为false。 - geekinit
2
如果你在 Windows 10 上使用 Docker 容器挂载目录,并运行 VSCode,这也会有所帮助。在容器外部检查 git 状态时,正确地显示您没有更改任何文件。但是,如果在容器内部检查 git 状态,则会显示文件已更改。在容器内运行上述命令可以解决我的问题。 - Frederick Ollinger
这对我有用!谢谢! - ann.piv
这对我在使用WSL时也有效,谢谢。 - Rim

111

1
也许 git diff 会记住之前的内容,即使您已经修改了该文件,而 git add 将刷新它。 - netawater
这对我有用,但是从那篇文档中阅读后我仍然不清楚 --cached 是做什么的。 - otocan

76

git status 显示有差异但 git diff 没有显示的原因有几个:

  • 文件模式(权限位)发生了变化,例如从777变为700。

  • 换行符样式从CRLF(DOS)更改为LF(UNIX)。

找出发生了什么的最简单方法是运行 git format-patch HEAD^ 并查看生成的补丁内容。


14
如果更改了权限文件,请执行以下操作:使用命令 "git config core.filemode false" 忽略文件权限。 - jruzafa
1
有使用Windows的同事会帮助你发现关于行尾的各种有趣的事情。我认为可能会有一些情况下,“git diff”会显示从CRLF到LF的更改,但这可能取决于你的配置。我已经有一段时间没有使用Windows了,所以我不知道默认设置现在是什么样子。 - cmccabe
@NagabhushanSN 我使用一个仓库进行拉取,但不想推送。我不想创建提交,也不想将 git add -A 添加到索引中。我同时使用 Windows 和 Linux,并且遇到了 crlf 问题。但是现在知道如何解决它 现在。所以 dos2unix 不是一个选项.. 等等,jaakko 的答案。 - Timo
我从 git format-patch HEAD^ 得到了 0001-commit.patch. - Timo
这是另一个可能发生的原因:我设置了一个git过滤器(在git配置中的“filter”部分包含一个用于过滤器的“smudge”和“clean”行),git status报告了将应用过滤器的文件(根据.gitattributes文件)已修改,但git diff没有显示任何差异。 - Ansa211
显示剩余2条评论

58

我曾经遇到这样一个问题,有些程序修改了几百个行的结尾,导致git diff列出所有源文件都被改变了。修复行结尾之后,git status仍然显示这些文件被修改了。

我通过添加所有文件到索引中并重置索引来解决这个问题。

git add -A
git reset

core.filemode 被设置为 false。


1
谢谢!运行得非常好! - Starwave
6
我用 git add --renormalize . 解决了该问题,可参考我下面的回答 - Stefano M
我添加了 git restore . 以避免污染索引。 - Timo
git restore . 帮助使索引保持干净。 - Timo

45

正如在之前的回答中提到的那样,这种情况可能是由于行尾问题(CR / LF与LF)而导致的。我使用以下命令解决了这个问题(在Git版本2.22.0下):

git add --renormalize .
根据手册:

按照手册:

       --renormalize
           Apply the "clean" process freshly to all tracked files to
           forcibly add them again to the index. This is useful after
           changing core.autocrlf configuration or the text attribute in
           order to correct files added with wrong CRLF/LF line endings.
           This option implies -u.

4
这是最新的最佳答案。 - Handsome Nerd
无需重置,思考即可。 - Timo
@Timo 是的,这些命令应该可以在不需要之后进行git reset的情况下工作。 - Stefano M
1
谢谢!我执行了 git config --global core.autocrlf true,然后运行了这个命令,问题就解决了。 - Gavin Ray
2
行尾问题只是其中一个例子;其他在文件提交(“clean”操作)和/或提取(“smudge”操作)时执行自动更改的git过滤器也可能是罪魁祸首;请检查您的git配置文件中的“filter”部分。 - Ansa211

20

我怀疑您的Git安装或存储库存在问题。

尝试运行:

GIT_TRACE=2 git <command>

看看是否能得到有用的信息。如果这没帮助,只需使用 strace 并查看出了什么问题:

strace git <command>

6
既然这个问题对你来说很有价值,我很想看看你在解决类似问题时学到了什么。 - cfi
5
在我的情况下,我将 -F 标志添加到 LESS 环境变量中,这告诉 less 如果没有足够的信息显示在屏幕上,则退出。由于git使用less作为分页器,而我只有一个很小的差异,所以什么都没有被显示出来。要么我必须向 LESS 环境变量添加 -X,这样即使 less 退出也会在屏幕上显示内容,要么就直接删除 -FGIT_TRACE 显示 less 被执行,这提醒我最近更改了 LESS 变量。这是 @rcwxok 的答案相同的原因,但我想评论一下 GIT_TRACE 如何帮助解决问题。 - Raghu Dodda
这个答案给了我“分页器”的提示,并引导我找到了解决方案,即在.gitconfig中设置core.pager,对我非常有效。 - ytu

10

我遇到了类似的问题:git diff 显示了差异,但 git diff <filename> 却没有。原来是因为我设置了 LESS 变量的值包含 -F (--quit-if-one-screen) 这个选项。移除这个选项解决了问题。


1
不必删除“-F”,添加“-X”也可能起作用,可以参考我下面的答案,那里有一个类似的情况。 - avivr
谢谢你!这让我快疯了。 - hackel

9

简短回答

有时运行git add可以解决问题。

示例

Git状态显示文件已更改,但git diff未显示任何内容...

> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   package.json

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

运行git add命令可解决不一致问题。

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

4
这听起来像是“治标不治本”而不是“治本”,;) - einjohn
@einjohn,你认为这种情况的问题是什么? - Shaun Luttin
1
疾病可能有几种原因。正如其他人所提到的,它可能是权限问题或行尾问题。它也可能是已经暂存的更改。然而,最后一种可能性不符合您的示例。尽管如此,使用您的解决方案,您将不知道原因(疾病),只是消除了问题(似乎存在故障的空差异(症状))。明确一点:我并不是说这是一个不好的解决方案。如果有人只想让问题消失,它可能会有所帮助。...希望我已经解释清楚了我的疾病比喻。 :) - einjohn
@einjohn 大多数情况下似乎是行结尾的问题。statusdiff 似乎有处理它们的不同方式。 - Shaun Luttin
这对我有用:git add 然后取消暂存所有文件。虚假的差异消失了。谢谢。 - Alexei - check Codidact
今天我遇到了这个问题 - 检查了文件权限和行结尾,一切正常。我尝试运行 git add,但是什么也没有添加,不过 git status 会被清除。 - Daniel Chin

8

总结:

换行符问题:

  1. Change autocrlf setting to default true. I.e., checkout Windows-style line endings on Windows and commit Linux-style line endings on remote Git repository:
    git config --global core.autocrlf true
    
  2. On a Windows machine, change all files in the repository to Windows-style:
    unix2dos **
    
  3. Git add all modified files and modified files will go:
    git add .
    git status
    

背景

  • 平台: Windows, WSL

我偶尔会遇到这样的问题,即git status显示我有修改过的文件,而git diff则没有显示任何内容。这很可能是行尾符号的问题。

根本原因

我经常遇到这个问题的原因是,我在 Windows 机器上工作,并在 WSL 中与 Git 进行交互。在不同的操作系统配置之间切换很容易导致行尾符号的问题。由于操作系统使用的行尾格式不同:

  • Windows: \r\n
  • OS X / Linux: \n

常见做法

当您在计算机上安装 Git 时,它会要求您选择行尾设置。通常,常见做法是在远程 Git 存储库中使用(提交)Linux 风格的行尾,并在 Windows 计算机上检出 Windows 风格的行尾。如果您使用默认设置,Git 将为您完成此操作。

Enter image description here

这意味着,如果您有一个 shell 脚本 myScript.sh 和 Bash 脚本 myScript.cmd 在您的存储库中,那么这两个脚本都会以 Linux 样式的行尾存在于您的远程 Git 存储库中,并且在您的 Windows 机器上都以 Windows 样式的行尾存在。

我曾尝试检出 shell 脚本文件并使用 dos2unix 更改脚本的行尾符号,以便在 WSL 中运行 shell 脚本。这就是为什么我遇到这个问题的原因。Git 不断告诉我我的行尾符号修改已经被更改,并询问是否提交更改。

解决方法

使用默认的行尾设置,如果您更改了某些文件的行尾(例如使用了dos2unixunix2dos),则放弃这些更改。 如果行尾符号已经更改,并且您想要摆脱它,请尝试将其添加到git add命令中,以使更改消失。


6
我遇到了这个问题。我的情况与rcwxok发布的LESS问题类似。
在我的情况下,我将PAGER环境变量设置为PAGER='less -RSF'
然而,与之前的答案不同,我不想删除-F选项,因为我明确将其放在那里,希望防止在屏幕上显示短差异。
为了获得所需的结果,我没有删除-F,而是添加了-XPAGER='less -RSFX'。这既解决了git diff问题,又防止了使用less显示短差异。

大写似乎有点奇怪。你是不是想说“less -RSFX”而不是“LESS -RSFX”?选项的大小写是否正确? - StackzOfZtuff
1
是的,谢谢,那是一个错误。不确定是怎么发生的。现在已经修复了。 - avivr

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