Git Diff-Tree 使用指南 | AI生成和翻译

Home 2025.08

这是一份实用的端到端 git diff-tree 指南——包括它的功能、使用时机以及实际工作中真正会用到的选项。我将避免使用大型表格,专注于提供可直接复制的示例说明。

git diff-tree 的实际功能

你会用到的基本形式

  1. 将提交与其父提交进行比较
git diff-tree -p <commit>

如果 <commit> 有一个父提交,你会看到常规补丁。如果是合并提交,除非特别要求(见下文),否则不会显示任何内容。

  1. 显式比较两个树对象/提交
git diff-tree -p <旧树对象或提交> <新树对象或提交>

当你想要比较任意两个时间点,而不仅仅是“提交与父提交”时非常有用。

  1. 仅显示文件名(无补丁)
git diff-tree --name-only -r <commit>

添加 -r 可递归到子目录,从而获得扁平列表。

  1. 显示带变更类型的文件名
git diff-tree --name-status -r <commit>
# 输出类似以下内容:
# A 路径/到/新文件
# M 路径/到/修改的文件
# D 路径/到/删除的文件
  1. 显示补丁(完整差异)
git diff-tree -p <commit>            # 类似 `git show` 的统一差异格式
git diff-tree -U1 -p <commit>        # 较少的上下文(1行)

必须了解的选项(含原因/时机)

规范的脚本模式

1) 列出单个提交中更改的文件

git diff-tree --no-commit-id --name-status -r <commit>

2) 批量处理多个提交(快速!)

git rev-list main --since="2025-08-01" |
  git diff-tree --stdin -r --no-commit-id --name-status

--stdin 避免了为每个提交生成 git 进程,对于大范围操作速度更快。

3) 仅显示目录中的添加和修改

git diff-tree -r --no-commit-id --name-status \
  --diff-filter=AM <commit> -- src/backend/

4) 统计每个文件添加/删除的行数(脚本友好)

git diff-tree -r --no-commit-id --numstat <commit>
# 输出:"<添加行数>\t<删除行数>\t<路径>"

5) 检测并显示提交中的重命名

git diff-tree -r --no-commit-id -M --name-status <commit>
# 输出类似:"R100 旧/名称.txt\t新/名称.txt"

6) 合并提交的补丁

git diff-tree -m -p <合并提交>     # 按父提交显示补丁
git diff-tree --cc <合并提交>      # 组合视图(单个补丁)

7) 初始提交(无父提交)

git diff-tree --root -p <初始提交>

理解原始记录格式(如需手动解析)

使用 --raw(某些模式隐式使用)获取最小化、稳定的记录:

:100644 100644 <旧sha> <新sha> M<TAB>路径

提示: 如果你正在构建可靠的工具,请始终传递 -z 并按 NUL 分割。存在包含换行符的文件名。

比较 git diff-tree 与相关命令(以便选择正确的命令)

实际示例

“这个 PR 合并提交中更改了什么?”

git diff-tree --cc <合并提交> | less

如果需要按父提交查看详细信息:

git diff-tree -m -p <合并提交> | less

“为 CI 步骤提供最新提交修改的文件列表”

git diff-tree --no-commit-id --name-only -r HEAD > changed.txt

“最近 20 次提交中仅添加或修改的 Java 文件”

git rev-list -n 20 HEAD |
  git diff-tree --stdin -r --no-commit-id --name-only --diff-filter=AM |
  grep -E '\.java$'

“统计发布标签间的代码变动(添加/删除的行数)”

git diff-tree -r --no-commit-id --numstat v1.2.0..v1.3.0

“安全处理奇怪的文件名”

git diff-tree -z -r --no-commit-id --name-status <commit> |
  awk -v RS='\0' 'NR%2{status=$0; next}{printf "%s %s\n", status, $0}'

性能注意事项

注意事项与边界情况

可直接复用的“速查代码片段”

# 更改的文件(扁平列表)
git diff-tree --no-commit-id --name-only -r <commit>

Back Donate