Git 中 diff 查看不同版本的文件差异

FreeGuideOnline 最新 2026-07-07

Git diff:查看不同版本间的文件差异

Git 的核心能力之一就是追踪文件的每一次变更。而 git diff 命令,就是用来精确比较这些差异的利器。无论你想知道工作区改了什么、暂存区里有什么、或者两个提交之间到底哪里不同,git diff 都能给你清晰、详细的答案。本教程将从零开始,带你掌握这个最常用的 Git 命令。

理解三个关键区域

在深入 diff 之前,先快速回顾一下 Git 中文件所处的三个区域,这是理解所有比较逻辑的基础:

  • 工作区(Working Directory):你电脑上能直接看到的项目文件夹,正在编辑的文件就在此处。
  • 暂存区(Staging Area / Index):一个隐式的“预备区”,通过 git add 命令,你告诉 Git 希望在下个提交中包含哪些修改。
  • 本地仓库(Repository):通过 git commit,暂存区的快照就被永久保存为一个提交对象(commit)。

git diff 的魔力就在于,它能灵活地选取这三个区域中的任意两个进行比对。

基本用法:查看工作区与暂存区的差异

这是你日常使用最频繁的操作。当你修改了文件,但还没执行 git add 时,用下面的命令就能看到“从上次暂存到现在,你到底改了些什么”。

git diff

这个命令比较的是 当前工作区暂存区 之间的差异。如果暂存区是空的(没有执行过 git add),那么它将自动比较最新的提交(HEAD)。

让我们看一个简单的输出示例。假设你将 hello.txt 文件中的 “Hello, World” 改成了 “Hello, Git”,运行 git diff 会显示:

diff --git a/hello.txt b/hello.txt
index 557db03..263ecaf 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1 @@
-Hello, World
+Hello, Git

关键部分解读:

  • diff --git a/hello.txt b/hello.txt:指明正在比较的文件。
  • --- a/hello.txt+++ b/hello.txta 表示变更前的版本,b 表示变更后的版本。
  • @@ -1 +1 @@:差异块的位置信息,表示从第一行开始,旧版本共1行,新版本也共1行。
  • -Hello, World:以 - 开头的行表示被删除的内容。
  • +Hello, Git:以 + 开头的行表示被新增的内容。

比较暂存区与最新提交的差异

你已经用 git add 将修改放入了暂存区,但在提交前还想确认一下暂存区里究竟放了什么内容。这时可以使用 --staged--cached 参数。

git diff --staged

--cached 参数在 Git 中与 --staged 完全等价,你可以根据习惯选用。)

这个命令比较的是 暂存区最近一次提交(HEAD) 之间的差异。它展示的是你即将通过 git commit 提交的所有内容。如果输出为空,说明暂存区干净,可以安全提交。

比较两个提交之间的差异

当你想查看项目历史中某两个版本之间的具体代码变动时,就需要比较提交。Git 支持多种灵活的方式来指定提交。

1. 比较两个明确提交

直接使用两个提交的哈希值(或分支、标签)。

git diff commit1 commit2

示例:比较提交 a1b2c3de4f5g6h 的差异。

git diff a1b2c3d e4f5g6h

2. 比较当前提交与另一个提交

使用 HEAD 指代当前提交。以下命令比较的是 HEAD 的父提交和 HEAD 之间的差异。

git diff HEAD^ HEAD

或者更简单地,查看上次提交带来的改变:

git diff HEAD^

3. 比较某个提交与它的父提交

这个技巧可以让你快速查看某次提交到底引入了什么变更。

git diff a1b2c3d^ a1b2c3d

或者使用更简洁的写法:

git diff a1b2c3d^!

4. 查看最近几次提交的整体差异

HEAD 与多个提交前的版本比较。

# 比较最近两次提交(HEAD^ 与 HEAD 之间的差异)
git diff HEAD^^ HEAD

# 更清晰的方法:比较当前提交与3个提交之前的版本
git diff HEAD~3 HEAD

比较工作区与任意提交的差异

有时你想知道,自己当前在工作区的未保存修改,相对于过去某个历史版本究竟变了多少。

git diff <commit>

这个命令比较 工作区指定的提交。它不会考虑暂存区的状态,只看你实际编辑了哪些内容。例如,查看工作区相对于上一次提交的变更:

git diff HEAD

注意: 这与 git diff 不同。如果暂存区为空,它们效果相同;但如果暂存区里有东西,git diff 显示的是工作区 vs 暂存区,而 git diff HEAD 显示的是工作区 vs 最新提交,把暂存区里的改动也包含在内了。

限定比较范围:只看特定文件

在所有上述比较场景中,你都可以在命令末尾添加文件路径,将差异范围限定到指定文件。

# 只查看 app.js 在工作区与暂存区之间的差异
git diff app.js

# 比较暂存区中 main.py 文件与最近提交的差异
git diff --staged main.py

# 比较两个提交中 docs/ 目录下的所有文件
git diff v1.0 v2.0 -- docs/

-- 是一个分隔符,用来明确后面的参数是文件路径而非提交名称。在处理文件名和分支名可能冲突时非常有用。

常用差异输出选项

git diff 的输出不仅可以阅读,还有许多参数帮你调整输出格式,提取更关键的信息。

简洁模式:只显示文件名与状态

光看代码改动细节太冗长?用 --name-status 只看哪些文件被增删改。

git diff --name-status HEAD^ HEAD

输出示例:

M    src/main.c
A    README.md
D    old_script.sh

状态字母表示:M 修改,A 新增,D 删除。

仅显示文件名

如果你只需一个被修改文件的列表,使用 --name-only

git diff --name-only HEAD~2 HEAD

统计概览

--stat 获得一个带增删行数统计的总结。

git diff --stat master feature-branch

输出类似:

 app/config.py  | 12 ++++----
 src/utils.js   |  5 +++--
 2 files changed, 11 insertions(+), 6 deletions(-)

图形化差异工具

命令行输出的 diff 对初学者可能不够直观。你可以配置 Git 调用外部图形化差异工具。

常见的外部工具包括 meldkdiff3vimdiff 等。以配置 meld 为例:

git config --global diff.tool meld

配置完成后,使用 git difftool 代替 git diff,就会弹出图形界面进行比对。

git difftool HEAD^

同样,git difftool 支持所有 git diff 的参数。图形化工具让合并冲突、对比补丁变得一目了然,是提升效率的好帮手。

掌握 git diff 不仅仅是记住几个命令,更是理解了 Git 数据模型的精髓。现在,打开你的终端,用你自己的项目去亲手实验每一个命令,很快你就能精确地追踪代码的每一次呼吸。