Skip to content

差异比较

git diff 系列命令用于比较不同区域或版本之间的文件差异,是代码审查和问题排查的重要工具。

git diff:工作区 vs 暂存区

不带参数的 git diff 比较工作区(当前编辑的文件)与暂存区(已 git add 的内容)之间的差异:

bash
git diff

# 输出示例:
# diff --git a/src/app.js b/src/app.js
# index abc123..def456 100644
# --- a/src/app.js
# +++ b/src/app.js
# @@ -10,7 +10,8 @@ function login(user) {
#    const token = generateToken(user);
# -  return token;
# +  console.log('Login successful:', user.name);
# +  return { token, user };
#  }

输出解读:

  • --- 表示旧版本(暂存区)
  • +++ 表示新版本(工作区)
  • - 开头的行是删除的内容(红色)
  • + 开头的行是新增的内容(绿色)
  • @@ 行显示改动所在位置(行号信息)

git diff --cached:暂存区 vs 最近提交

--cached(也可用 --staged)比较暂存区与**最近提交(HEAD)**的差异,即"如果现在提交,会提交什么内容":

bash
git diff --cached
git diff --staged    # 同义词,语义更清晰

# 这是提交前检查暂存内容的标准命令

git diff HEAD:工作区 vs 最近提交

比较工作区(含未暂存修改)与最近提交的差异,即"自上次提交后,我改动了什么":

bash
git diff HEAD

三种 diff 的关系

HEAD(上次提交)
    ↕ git diff HEAD(工作区 vs HEAD)
    ↕ git diff --cached(暂存区 vs HEAD)
暂存区(Index)
    ↕ git diff(工作区 vs 暂存区)
工作区(Working Directory)

git diff branch1..branch2:分支间差异

比较两个分支的差异:

bash
# 比较 main 和 feature 分支的差异
git diff main..feature
git diff main feature    # 同义

# 比较本地分支和远程追踪分支
git diff main..origin/main

# 比较特定提交
git diff abc123..def456

git diff branch1...branch2:分叉后的差异

三点语法比较的是:branch2 相对于两分支共同祖先的变化,即 branch2 的"独有改动":

bash
git diff main...feature

# 含义:feature 分支相对于从 main 分叉点以来的改动
# 等价于:git diff $(git merge-base main feature)..feature

两点 vs 三点:

A - B - C - D (main)
        \
         E - F (feature)

git diff main..feature   = D 和 F 的差异(两者最新提交的完整差异)
git diff main...feature  = C 和 F 的差异(feature 自分叉后的变化)

三点语法更适合用于 Code Review,看 PR 引入了哪些新变化。

git diff --stat:统计摘要

只显示改动的文件列表和统计数字:

bash
git diff --stat

# 输出:
# src/app.js    | 15 ++++++++-------
# src/auth.js   |  5 ++++-
# tests/app.test.js | 20 ++++++++++++++++++++
# 3 files changed, 33 insertions(+), 7 deletions(-)
bash
# 更简短的统计
git diff --shortstat
# 3 files changed, 33 insertions(+), 7 deletions(-)

git diff -- 文件路径:指定文件

bash
# 只比较特定文件
git diff -- src/app.js
git diff HEAD -- src/app.js

# 比较特定目录
git diff -- src/

# 比较分支间特定文件的差异
git diff main..feature -- src/app.js

-- 用于分隔选项和文件路径,避免文件名与分支名冲突。

其他常用 diff 参数

忽略空白差异

bash
# 忽略行尾空格
git diff -w
git diff --ignore-all-space

# 忽略空白字符的变化(空格数量等)
git diff --ignore-space-change

显示单词级别的差异

bash
# 高亮显示具体哪些词改变了(而不是整行)
git diff --word-diff

# 更精确的颜色高亮(需支持的终端)
git diff --color-words

查看二进制文件差异

bash
# 通常 git diff 不显示二进制文件内容,只显示"Binary files differ"
# 可以使用 --text 强制显示(通常不可读)
git diff --text -- image.png

显示改动统计但不显示内容

bash
git diff --name-only          # 只显示改动的文件名
git diff --name-status        # 显示文件名和状态(M/A/D/R)

与外部 diff 工具对比

bash
# 使用配置的 diff 工具(如 VS Code、vimdiff)
git difftool

# 使用 VS Code diff
git difftool --tool=vscode

# 配置默认 diff 工具
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'

实用场景

bash
# 提交前完整检查(推荐流程)
git diff           # 检查未暂存的改动
git add .          # 暂存所有改动
git diff --cached  # 再次确认暂存区内容
git commit -m "..."

# 对比当前分支与 main 的差异(PR 前检查)
git diff main...HEAD

# 查看上次提交改了什么
git diff HEAD~1 HEAD
git diff HEAD~1    # 等价(对比 HEAD~1 与工作区+暂存区)

# 查看某个文件自某标签以来的变化
git diff v1.0.0 -- src/app.js

# 比较两个标签之间的差异
git diff v1.0.0 v1.1.0

# 查找某行代码是什么时候改变的(结合 blame)
git diff -p -S "some_function()" -- src/

输出格式说明

diff --git a/file.txt b/file.txt
index abc123..def456 100644        ← 文件的 SHA-1(旧/新)和权限
--- a/file.txt                      ← 旧版本(a 前缀)
+++ b/file.txt                      ← 新版本(b 前缀)
@@ -1,5 +1,6 @@                    ← 块头:旧文件从第1行起5行,新文件从第1行起6行
 context line                       ← 上下文行(灰色,无前缀)
-removed line                       ← 删除的行(红色,- 前缀)
+added line                         ← 新增的行(绿色,+ 前缀)
 context line

总结

命令比较对象
git diff工作区 vs 暂存区
git diff --cached暂存区 vs HEAD
git diff HEAD工作区 vs HEAD
git diff A..B提交A vs 提交B(完整差异)
git diff A...B共同祖先 vs B(B 的独有改动)
git diff --stat只显示统计摘要
git diff -- file指定文件的差异