git diff 不加参数时对比工作区和暂存区,即未暂存的修改;不显示已 git add 的变更、未 git rm 的删除文件,默认不递归子模块且受 .gitignore 影响。

git diff 不加参数时对比的是什么
它只对比工作区(Working Directory)和暂存区(Index / Staging Area),也就是你 git add 之前改了但还没暂存的那些内容。这是最常用、也最容易误解的场景——很多人以为它看的是工作区和 HEAD,其实不是。
常见错误现象:git diff 没输出,但 git status 显示有修改 → 很可能你已经 git add 过了,文件进了暂存区,此时工作区和暂存区一致,diff 就为空。
- 只显示「未暂存的修改」,不包含已
git add的变更 - 不会告诉你哪些文件被删了但没
git rm,除非用-s或配合--stat - 默认不递归进入子模块,也不处理忽略文件(
.gitignore生效)
git diff --cached 查看已 add 但未 commit 的差异
这才是真正对应「暂存区 vs HEAD」的命令。你想确认这次 git commit 会塞进去什么,就得用它。
使用场景:写完代码 git add . 后,快速扫一眼到底暂存了哪些改动,避免误提交调试日志或临时注释。
-
--cached和--staged完全等价,后者更直观,推荐用git diff --staged - 如果暂存区为空(即没
git add过任何东西),会提示fatal: No changes added to commit - 注意:它不显示工作区里新创建但未
git add的文件(那些文件连暂存区都没有)
git diff HEAD 看工作区和最新提交的完整差异
这个命令跳过暂存区,直接比工作区和 HEAD(即最近一次 commit)。它等于 git diff + git diff --staged 的合并结果。
性能影响:对大仓库或含二进制文件的项目,git diff HEAD 可能明显变慢,因为要计算两层差异;而 git diff 通常更快,只读取 index 和工作区元数据。
- 会同时显示「未暂存的修改」+「已暂存但未 commit 的修改」
- 新文件(untracked)默认不出现,加
-a或用git add -N && git diff才能纳入比较 - Windows 上行尾符(CRLF/LF)可能触发大量假差异,建议提前配好
core.autocrlf
为什么 git diff 有时不显示删除的文件
Git 默认把未 git rm 的已删文件当作「未跟踪状态」,git diff 不主动报告。这不是 bug,是设计——它只关心「内容变化」,不负责文件存在性管理。
容易踩的坑:你删了一个配置文件,git diff 没输出,就以为 Git 不知道;其实 git status 会标成 deleted:,但 diff 默认沉默。
- 用
git status -s能一眼看到D filename这类标记 - 想让
git diff显示删除,加--diff-filter=D,例如:git diff --diff-filter=D --name-only - 如果文件删了又新建同名文件,Git 可能当成「修改」而非「删除+新增」,取决于内容相似度和 rename 检测阈值
真正麻烦的是混合操作:一边改内容,一边删文件,还顺手 git add 了部分——这时候得组合多个命令交叉验证,不能只盯一个 git diff。


















