Git 历史与溯源:log / show / blame
更新时间:2026-08-25。本篇覆盖"读历史"的三条命令:
git log(提交历史)、git show(查看单个对象)、git blame(逐行溯源)。
1. git log:提交历史
bash
git log # 默认详细历史
git log --oneline # 每条一行(哈希+标题)
git log --oneline --graph # 带分支拓扑图(推荐日常使用)
git log -5 # 只看最近 5 条
git log --stat # 附带文件变更统计
git log -p # 附带完整补丁(历史中的 diff)过滤历史
| 需求 | 命令 |
|---|---|
| 某文件的历史 | git log --oneline -- <file> |
| 按作者 | git log --author="name" |
| 按时间 | git log --since="2026-01-01" --until="2026-06-01" |
| 按提交信息关键字 | git log --grep="fix" |
| 按代码内容变化(字符串出现/消失) | git log -S "function_name" |
| 按代码内容变化(正则) | git log -G "pattern" |
| 当前分支独有、未合并进 main | git log main..feature |
| 两个分支共同的祖先 | git merge-base main feature |
bash
# 日常最常用的姿势
git log --oneline --graph --all --decorate提交对象长什么样
bash
$ git log -1
commit 8f3a2b1c9d0e4f5a6b7c8d9e0f1a2b3c4d5e6f7a (HEAD -> main)
Author: Zhang San <zhangsan@example.com>
Date: Mon Aug 25 10:00:00 2026 +0800
feat: 添加批量导出commit hash 是内容寻址的:只要作者、时间、父提交、树内容任一变化,哈希就变——这就是为什么
--amend/rebase会重写后续所有提交的哈希。
2. git show:查看单个对象
bash
git show <commit> # 某次提交的改动
git show <commit> --stat # 只看出改哪些文件
git show <commit>:<file> # 某次提交时某文件的内容
git show <tag> # 附注标签的说明与指向提交
git show HEAD~1 # 上一个提交
git show HEAD^ # 上一个提交(等价写法)相对引用速记:HEAD 当前提交、HEAD~1 上一代、HEAD~2 上两代、HEAD^ 第一个父提交(合并提交时可再 ^2 取第二个父提交)。
3. git blame:逐行溯源
bash
git blame <file> # 每一行来自哪个提交、谁改的
git blame -L 10,20 <file> # 只看第 10~20 行
git blame -w <file> # 忽略空白变化
git blame --show-email <file> # 显示邮箱bash
$ git blame -L 5,8 main.cpp
8f3a2b1c (Zhang San 2026-08-01) 5 int sum = 0;
8f3a2b1c (Zhang San 2026-08-01) 6 for (int i = 0; i < n; i++) {
d4e5f6a7 (Li Si 2026-08-10) 7 sum += arr[i] * 2; # Li Si 改过这行
8f3a2b1c (Zhang San 2026-08-01) 8 }典型用途:发现某行代码有问题 → git blame 找到"谁在哪个提交引入了它" → git show <commit> 查看当时的改动上下文 → 决定是 git revert 还是修复。
溯源排查链路

对比:三条命令
| 命令 | 粒度 | 典型场景 |
|---|---|---|
git log | 提交(列表/拓扑) | 了解演进、找提交号 |
git show | 单个对象(提交/文件/标签) | 细看某次改了什么 |
git blame | 逐行 | 定位某行的引入者与引入提交 |
易错点
git log -- <file>的路径要放在--后面,否则会被当成提交过滤条件。-S(字符串出现次数)与-G(正则匹配)区别:-S找"该字符串出现次数变化"的提交(重命名安全),-G找"匹配正则的行发生变化"的提交,范围更宽。- blame 结果受历史改写影响:rebase 之后 blame 会显示改写时的提交,而不是原始引入者——这是历史改写的代价之一。
一句话总结:log 看历史脉络、show 看单点细节、blame 追逐行来源,三者配合即可把"这行代码为什么是这样"查个水落石出。