Git: Git日志查看与历史追溯
提交历史记录了项目的所有变更,是版本控制的核心价值。通过查看历史,可以了解项目的演进过程、追溯问题来源、分析开发轨迹。
1. 日志基础概念
(1) 什么是提交历史
提交历史是所有提交按照时间顺序排列的记录,包含:
- 提交ID:40位SHA-1哈希值,唯一标识每次提交
- 作者信息:提交者的姓名和邮箱
- 提交时间:创建提交的时间戳
- 提交信息:描述本次修改的说明文字
- 父提交:指向上一个提交的指针
graph TB
A[最新提交<br/>HEAD] --> B[提交C3<br/>a1b2c3d]
B --> C[提交C2<br/>d4e5f6g]
C --> D[提交C1<br/>h7i8j9k]
D --> E[初始提交<br/>l0m1n2o]
style A fill:#d4edda
style E fill:#fff3cd
(2) 历史的作用
- 版本追溯:了解项目在每个时间点的状态
- 问题定位:查找引入Bug的提交
- 变更审查:审查代码修改记录
- 协作跟踪:了解团队成员的工作内容
- 回退依据:确定回退到哪个版本
(3) Git日志命令
git log 是查看提交历史的主要命令,支持丰富的选项来定制输出。
2. 基本日志查看
(1) 查看完整历史
▶ 示例:查看提交历史
BASH
# 查看完整历史
git log
# 输出格式:
# commit a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
# Author: 张三 <zhangsan@example.com>
# Date: Mon Jan 1 10:00:00 2026 +0800
#
# feat: 添加用户登录功能
#
# commit d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2
# Author: 李四 <lisi@example.com>
# Date: Sun Dec 31 15:30:00 2025 +0800
#
# fix: 修复登录验证错误
(2) 简洁模式
▶ 示例:简洁显示
BASH
# 一行显示一个提交
git log --oneline
# 输出:
# a1b2c3d feat: 添加用户登录功能
# d4e5f6g fix: 修复登录验证错误
# h7i8j9k docs: 更新README
# l0m1n2o Initial commit
# 简写形式
git log --oneline --decorate
# 输出:
# a1b2c3d (HEAD -> main) feat: 添加用户登录功能
# d4e5f6g (origin/main) fix: 修复登录验证错误
(3) 限制显示数量
▶ 示例:限制显示条数
BASH
# 显示最近3次提交
git log -3
# 或者
git log -n 3
# 简洁模式显示最近5次
git log --oneline -5
# 输出:
# a1b2c3d feat: 添加用户登录功能
# d4e5f6g fix: 修复登录验证错误
# h7i8j9k docs: 更新README
# k9l0m1n style: 格式化代码
# n2o3p4q refactor: 优化查询逻辑
3. 日志格式化输出
(1) 格式化选项
| 选项 | 说明 | 用途 |
|---|---|---|
--oneline |
简洁模式 | 快速浏览历史 |
--stat |
显示统计 | 查看文件变更统计 |
-p |
显示差异 | 查看具体修改内容 |
--graph |
图形显示 | 查看分支合并历史 |
--decorate |
显示引用 | 查看分支和标签指向 |
▶ 示例:显示统计信息
BASH
# 显示文件变更统计
git log --stat
# 输出:
# commit a1b2c3d4e5f6...
# Author: 张三 <zhangsan@example.com>
# Date: Mon Jan 1 10:00:00 2026 +0800
#
# feat: 添加用户登录功能
#
# src/auth/login.js | 25 +++++++++++++++++++++++++
# src/auth/index.js | 3 ++-
# 2 files changed, 26 insertions(+), 2 deletions(-)
(2) 显示完整差异
▶ 示例:查看提交差异
BASH
# 显示每次提交的完整差异
git log -p
# 显示最近一次提交的差异
git log -1 -p
# 输出:
# commit a1b2c3d4e5f6...
# Author: 张三 <zhangsan@example.com>
# Date: Mon Jan 1 10:00:00 2026 +0800
#
# feat: 添加用户登录功能
#
# diff --git a/src/auth/login.js b/src/auth/login.js
# new file mode 100644
# index 0000000..abc1234
# --- /dev/null
# +++ b/src/auth/login.js
# @@ -0,0 +1,25 @@
# +function login(username, password) {
# + // 验证逻辑
# +}
(3) 自定义格式
▶ 示例:自定义输出格式
BASH
# 使用预设格式
git log --pretty=oneline
git log --pretty=short
git log --pretty=full
git log --pretty=fuller
# 自定义格式
git log --pretty=format:"%h - %an, %ar : %s"
# 输出:
# a1b2c3d - 张三, 2 hours ago : feat: 添加用户登录功能
# d4e5f6g - 李四, 1 day ago : fix: 修复登录验证错误
# 更详细的格式
git log --pretty=format:"%C(yellow)%h%C(reset) - %C(green)%an%C(reset), %C(blue)%ar%C(reset) : %s"
# 表格格式
git log --pretty=format:"%h | %an | %ad | %s" --date=short
# 输出:
# a1b2c3d | 张三 | 2026-01-01 | feat: 添加用户登录功能
# d4e5f6g | 李四 | 2025-12-31 | fix: 修复登录验证错误
(4) 格式占位符
| 占位符 | 说明 | 示例输出 |
|---|---|---|
%H |
完整哈希 | a1b2c3d4e5f6... |
%h |
短哈希 | a1b2c3d |
%an |
作者名字 | 张三 |
%ae |
作者邮箱 | zhangsan@example.com |
%ad |
作者日期 | Mon Jan 1 10:00:00 2026 |
%ar |
作者日期(相对) | 2 hours ago |
%s |
提交信息 | feat: 添加功能 |
%d |
引用名称 | (HEAD -> main) |
4. 日志过滤查询
(1) 按时间过滤
▶ 示例:时间范围过滤
BASH
# 指定日期之后
git log --since="2026-01-01"
# 指定日期之前
git log --until="2026-01-31"
# 相对时间
git log --since="1 week ago"
git log --since="2 months ago"
git log --after="yesterday"
# 时间范围
git log --since="2026-01-01" --until="2026-01-31"
# 组合使用
git log --oneline --since="1 week ago" --until="yesterday"
(2) 按作者过滤
▶ 示例:作者过滤
BASH
# 按作者名字
git log --author="张三"
# 按作者邮箱
git log --author="zhangsan@example.com"
# 模糊匹配
git log --author="张"
# 组合过滤
git log --author="张三" --since="1 week ago"
(3) 按提交信息过滤
▶ 示例:提交信息搜索
BASH
# 搜索提交信息
git log --grep="fix"
# 多个条件(或关系)
git log --grep="fix" --grep="feat"
# 正则表达式
git log --grep="feat\|fix"
# 忽略大小写
git log --grep="FIX" -i
# 组合过滤
git log --author="张三" --grep="feat"
(4) 按文件过滤
▶ 示例:文件历史查询
BASH
# 查看特定文件的历史
git log -- README.md
# 查看多个文件
git log -- file1.js file2.js
# 查看目录历史
git log -- src/auth/
# 显示文件差异
git log -p -- README.md
# 显示文件变更统计
git log --stat -- README.md
# 只显示修改该文件的提交
git log --oneline -- README.md
# 输出:
# a1b2c3d docs: 更新README
# h7i8j9k docs: 添加安装说明
# l0m1n2o Initial commit
(5) 按提交范围过滤
▶ 示例:提交范围查询
BASH
# 查看两个提交之间的历史
git log a1b2c3d..d4e5f6g
# 查看某个提交之后的历史
git log a1b2c3d..
# 查看某个提交之前的历史
git log ..d4e5f6g
# 查看分支差异
git log main..feature
# 查看两个分支的差异
git log main...feature
5. 图形化显示
(1) 显示分支图
▶ 示例:图形化日志
BASH
# 显示分支合并图
git log --graph
# 常用组合
git log --graph --oneline --all
# 输出:
# * a1b2c3d Merge branch 'feature'
# |\
# | * d4e5f6g Add feature
# * | b7c8d9e Fix bug
# |/
# * c0d1e2f Initial commit
# 带装饰信息
git log --graph --oneline --decorate --all
# 彩色输出
git log --graph --oneline --all --pretty=format:"%C(red)%h%C(reset) - %C(green)%s%C(reset)"
(2) 分支历史可视化
gitGraph
commit id: "Initial commit"
commit id: "Add feature A"
branch feature
checkout feature
commit id: "Feature work"
checkout main
commit id: "Fix bug"
merge feature id: "Merge feature"
commit id: "Release v1.0"
(3) 查看分支演进
▶ 示例:分支演进历史
BASH
# 查看所有分支历史
git log --graph --oneline --all --decorate
# 查看特定分支历史
git log --graph --oneline feature
# 查看分支分叉点
git log --graph --oneline --simplify-by-decoration
# 查看合并提交
git log --merges --oneline
# 查看非合并提交
git log --no-merges --oneline
6. 高级日志技巧
(1) 二分查找
使用 git bisect 定位引入问题的提交:
▶ 示例:二分查找问题提交
BASH
# 开始二分查找
git bisect start
# 标记当前提交为有问题
git bisect bad
# 标记某个提交为正常
git bisect good v1.0.0
# Git会自动切换到中间提交
# 测试后标记为good或bad
git bisect good
# 或
git bisect bad
# 找到问题提交后
# a1b2c3d is the first bad commit
# 结束二分查找
git bisect reset
(2) 查看文件变更历史
▶ 示例:文件历史分析
BASH
# 查看文件的完整变更历史
git log --follow -p -- filename
# 查看文件每一行的修改历史
git blame filename
# 输出:
# a1b2c3d (张三 2026-01-01 10:00:00 1) function login() {
# d4e5f6g (李四 2025-12-31 15:30:00 2) // 验证逻辑
# h7i8j9k (张三 2025-12-30 09:00:00 3) }
# 查看特定行的历史
git log -L 10,20:filename
# 查看函数历史
git log -L :functionName:filename
(3) 引用日志
▶ 示例:查看引用日志
BASH
# 查看HEAD的移动历史
git reflog
# 输出:
# a1b2c3d HEAD@{0}: commit: feat: 添加功能
# d4e5f6g HEAD@{1}: checkout: moving from feature to main
# h7i8j9k HEAD@{2}: commit: Feature work
# l0m1n2o HEAD@{3}: checkout: moving from main to feature
# 查看特定引用的历史
git reflog show HEAD
git reflog show main
# 恢复到之前的状态
git reset HEAD@{5}
❓ 常见问题
Q 如何查看某个文件的修改历史?
A 使用
git log -- <文件名> 查看文件的提交历史,使用 git log -p -- <文件名> 查看详细的修改内容,使用 git blame <文件名> 查看每一行的修改记录。Q 如何查看两次提交之间的差异?
A 使用
git log <提交1>..<提交2> 查看两次提交之间的历史,使用 git diff <提交1> <提交2> 查看具体的文件差异。Q 如何找到引入某个Bug的提交?
A 使用
git bisect 进行二分查找。标记一个已知正常的提交和一个已知有问题的提交,Git会自动定位引入问题的提交。Q log和reflog有什么区别?
A
git log 显示提交历史,是项目演进的记录;git reflog 显示引用的移动历史,包括提交、重置、检出等所有操作,即使提交被丢弃也能在reflog中找到。Q 如何查看已删除文件的历史?
A 使用
git log --all --full-history -- <文件名> 可以查看已删除文件的完整历史,包括删除操作。📖 小节
- 提交历史记录了项目的所有变更,是版本控制的核心价值
- 使用
git log查看历史,支持丰富的格式化和过滤选项 - 格式化输出:--oneline、--stat、-p、自定义格式
- 过滤查询:按时间、作者、提交信息、文件、提交范围
- 图形化显示:--graph 显示分支合并历史
- 高级技巧:bisect二分查找、blame行历史、reflog引用日志
📝 作业
-
基础题:使用
git log的各种选项查看项目历史,包括简洁模式、统计信息、图形化显示,并尝试自定义输出格式。 -
进阶题:使用过滤选项查找特定条件的提交,例如:查找最近一周的提交、查找某个作者的所有提交、查找提交信息包含"fix"的提交。
-
挑战题:使用
git bisect在一个包含多个提交的项目中定位引入某个问题的提交,体验二分查找的强大功能。