Git History
理解和查看项目历史是使用 Git 的重要技能。本章将详细介绍如何查看、分析和理解 Git 的提交历史。
基本历史查看
git log 基础用法
bash
# 查看完整的提交历史
git log
# 查看简洁的单行历史
git log --oneline
# 限制显示的提交数量
git log -n 5
git log --oneline -10
# 查看图形化的分支历史
git log --graph
# 组合使用
git log --oneline --graph -10创建演示历史
让我们先创建一个有丰富历史的项目来演示:
bash
# 创建演示项目
mkdir git-history-demo
cd git-history-demo
git init
# 创建初始提交
echo "# Git 历史演示项目" > README.md
git add README.md
git commit -m "初始提交: 添加 README"
# 添加更多提交
echo "项目描述" >> README.md
git add README.md
git commit -m "更新 README: 添加项目描述"
echo "console.log('Hello World');" > app.js
git add app.js
git commit -m "添加主应用文件"
echo "body { margin: 0; }" > style.css
git add style.css
git commit -m "添加样式文件"详细的 log 选项
格式化输出
bash
# 自定义格式
git log --pretty=format:"%h - %an, %ar : %s"
# 常用格式选项
git log --pretty=format:"%H" # 完整哈希
git log --pretty=format:"%h" # 简短哈希
git log --pretty=format:"%an" # 作者名字
git log --pretty=format:"%ae" # 作者邮箱
git log --pretty=format:"%ad" # 作者日期
git log --pretty=format:"%ar" # 相对日期
git log --pretty=format:"%s" # 提交信息
git log --pretty=format:"%b" # 提交正文
# 美化的日志格式
git log --pretty=format:"%C(yellow)%h%C(reset) - %C(green)%an%C(reset), %C(blue)%ar%C(reset) : %s"时间和日期过滤
bash
# 查看特定时间段的提交
git log --since="2 weeks ago"
git log --until="2023-12-01"
git log --since="2023-01-01" --until="2023-12-31"
# 相对时间
git log --since="yesterday"
git log --since="1 week ago"
git log --since="2 months ago"
# 具体日期格式
git log --since="2023-01-01 00:00:00"
git log --after="Jan 1 2023" --before="Dec 31 2023"作者和提交者过滤
bash
# 按作者过滤
git log --author="张三"
git log --author="zhangsan@example.com"
# 支持正则表达式
git log --author="张.*"
git log --author=".*@company.com"
# 按提交者过滤
git log --committer="李四"
# 排除特定作者
git log --author="^(?!.*张三).*$" --perl-regexp内容搜索
bash
# 搜索提交信息
git log --grep="修复"
git log --grep="bug" --grep="fix" --all-match
# 搜索代码变更
git log -S "function_name"
git log -G "正则表达式"
# 搜索文件内容变更
git log -p -S "console.log"
# 忽略大小写
git log --grep="BUG" -i文件和路径过滤
bash
# 查看特定文件的历史
git log README.md
git log -- README.md # 更安全的写法
# 查看多个文件
git log file1.txt file2.txt
# 查看目录的历史
git log src/
git log -- src/
# 查看已删除文件的历史
git log --all --full-history -- deleted_file.txt高级历史查看
图形化历史
bash
# 基本分支图
git log --graph --oneline
# 详细分支图
git log --graph --pretty=format:"%C(red)%h%C(reset) -%C(yellow)%d%C(reset) %s %C(green)(%cr) %C(bold blue)<%an>%C(reset)"
# 查看所有分支
git log --graph --oneline --all
# 简化的分支图
git log --graph --simplify-by-decoration --oneline --all统计信息
bash
# 显示修改统计
git log --stat
# 显示简短统计
git log --shortstat
# 显示文件名统计
git log --name-only
# 显示文件状态
git log --name-status
# 显示数字统计
git log --numstat差异显示
bash
# 显示每个提交的差异
git log -p
# 限制差异上下文行数
git log -p -U1
# 只显示特定文件的差异
git log -p -- file.txt
# 显示单词级别的差异
git log -p --word-diff特殊的历史查看
查看合并历史
bash
# 只显示合并提交
git log --merges
# 不显示合并提交
git log --no-merges
# 显示第一父提交
git log --first-parent
# 查看合并的详细信息
git log --merges -p查看分支历史
bash
# 查看两个分支的差异
git log main..feature-branch
# 查看在 feature-branch 但不在 main 的提交
git log main..feature-branch
# 查看在 main 但不在 feature-branch 的提交
git log feature-branch..main
# 查看两个分支的对称差异
git log main...feature-branch查看标签历史
bash
# 查看标签之间的历史
git log v1.0..v2.0
# 查看从标签到现在的历史
git log v1.0..HEAD
# 查看包含特定标签的提交
git log --contains v1.0实用的历史别名
设置常用别名
bash
# 美化的日志
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 简洁的历史
git config --global alias.hist "log --oneline --graph --decorate --all"
# 详细的历史
git config --global alias.ll "log --oneline --graph --decorate --stat"
# 查看最近的提交
git config --global alias.last "log -1 HEAD --stat"
# 查看今天的提交
git config --global alias.today "log --since='midnight' --oneline"使用别名
bash
# 使用设置的别名
git lg
git hist
git ll
git last
git today历史分析工具
gitk 图形界面
bash
# 启动 gitk
gitk
# 查看所有分支
gitk --all
# 查看特定文件的历史
gitk README.md
# 查看特定时间段
gitk --since="1 week ago"git show 命令
bash
# 查看最新提交
git show
# 查看特定提交
git show commit_hash
# 查看特定提交的特定文件
git show commit_hash:file.txt
# 只显示提交信息,不显示差异
git show --name-only commit_hash
# 显示统计信息
git show --stat commit_hashgit blame 追踪代码
bash
# 查看文件每行的最后修改者
git blame file.txt
# 查看特定行范围
git blame -L 10,20 file.txt
# 忽略空白字符变化
git blame -w file.txt
# 显示邮箱而不是用户名
git blame -e file.txt
# 显示原始行号
git blame -n file.txt历史搜索技巧
使用 git bisect 查找问题
bash
# 开始二分查找
git bisect start
# 标记当前提交为坏的
git bisect bad
# 标记已知好的提交
git bisect good commit_hash
# Git 会自动切换到中间的提交
# 测试后标记结果
git bisect good # 或 git bisect bad
# 继续直到找到问题提交
# 结束二分查找
git bisect reset查找引入特定代码的提交
bash
# 查找添加特定代码的提交
git log -S "function_name" --source --all
# 查找修改特定代码的提交
git log -G "regex_pattern" --source --all
# 查找文件重命名
git log --follow -- new_filename.txt查找丢失的提交
bash
# 查看引用日志
git reflog
# 查看所有分支的引用日志
git reflog --all
# 查看特定分支的引用日志
git reflog show branch_name
# 恢复丢失的提交
git checkout commit_hash
git branch recovered-branch历史可视化
创建历史图表
bash
# 生成简单的 ASCII 图
git log --graph --pretty=format:'%h -%d %s (%cr) <%an>' --abbrev-commit --all
# 生成更详细的图表
git log --graph --full-history --all --color --pretty=format:"%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%s"导出历史数据
bash
# 导出为 CSV 格式
git log --pretty=format:'"%h","%an","%ae","%ad","%s"' --date=iso > commits.csv
# 导出为 JSON 格式(需要 jq 工具)
git log --pretty=format:'{"hash":"%H","author":"%an","email":"%ae","date":"%ad","message":"%s"}' --date=iso
# 生成统计报告
git shortlog -sn # 按作者统计提交数
git shortlog -sne # 包含邮箱历史清理和重写
修改历史(谨慎使用)
bash
# 修改最后一次提交
git commit --amend
# 交互式重写历史
git rebase -i HEAD~3
# 压缩提交
git rebase -i HEAD~3
# 在编辑器中将 pick 改为 squash
# 分割提交
git rebase -i HEAD~3
# 在编辑器中将 pick 改为 edit
# 然后使用 git reset HEAD^ 和重新提交过滤历史
bash
# 从历史中移除文件
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
# 移除敏感信息(推荐使用 git-filter-repo)
git filter-repo --path passwords.txt --invert-paths
# 重写作者信息
git filter-branch --env-filter '
if [ "$GIT_COMMITTER_EMAIL" = "old@example.com" ]
then
export GIT_COMMITTER_NAME="New Name"
export GIT_COMMITTER_EMAIL="new@example.com"
fi
if [ "$GIT_AUTHOR_EMAIL" = "old@example.com" ]
then
export GIT_AUTHOR_NAME="New Name"
export GIT_AUTHOR_EMAIL="new@example.com"
fi
' HEAD历史分析脚本
提交统计脚本
bash
#!/bin/bash
# 生成提交统计报告
echo "=== Git 历史分析报告 ==="
echo "生成时间: $(date)"
echo ""
echo "=== 基本统计 ==="
echo "总提交数: $(git rev-list --all --count)"
echo "总分支数: $(git branch -a | wc -l)"
echo "总标签数: $(git tag | wc -l)"
echo ""
echo "=== 作者统计 ==="
git shortlog -sn | head -10
echo ""
echo "=== 最近活动 ==="
echo "最近 10 次提交:"
git log --oneline -10
echo ""
echo "=== 文件统计 ==="
echo "修改最频繁的文件:"
git log --name-only --pretty=format: | sort | uniq -c | sort -rn | head -10代码贡献分析
bash
#!/bin/bash
# 分析代码贡献
echo "=== 代码贡献分析 ==="
# 按作者统计代码行数
git log --shortstat --pretty="%cE" | sed 's/\(.*\)@.*/\1/' | grep -v "^$" | awk 'BEGIN { line=""; } !/^ / { if (line=="" || !match(line, $0)) {line = $0 "," line }} /^ / { print line " # " $0; line=""}' | sort | sed -E 's/# //;s/ files? changed,//;s/([0-9]+) ([0-9]+ deletion)/\1 0 insertions, \2/;s/\(\+\)//;s/\(\-\)//' | awk 'BEGIN {name=""; files=0; insertions=0; deletions=0;} {if ($1 != name && name != "") { print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net"; files=0; insertions=0; deletions=0; name=$1; } name=$1; files+=$2; insertions+=$3; deletions+=$4} END {print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net";}'
echo ""
echo "=== 月度提交趋势 ==="
git log --date=format:'%Y-%m' --pretty=format:'%ad' | sort | uniq -c | sort -k2历史最佳实践
1. 保持清晰的提交历史
bash
# ✅ 好的提交信息
git commit -m "feat: 添加用户登录功能"
git commit -m "fix: 修复登录页面样式问题"
git commit -m "docs: 更新 API 文档"
# ❌ 避免的提交信息
git commit -m "修改"
git commit -m "更新代码"
git commit -m "临时提交"2. 使用语义化提交
bash
# 提交类型
feat: # 新功能
fix: # 修复 bug
docs: # 文档更新
style: # 代码格式化
refactor: # 重构
test: # 测试相关
chore: # 构建过程或辅助工具的变动
# 示例
git commit -m "feat(auth): 添加 OAuth 登录支持"
git commit -m "fix(ui): 修复移动端布局问题"3. 定期清理历史
bash
# 压缩功能分支的提交
git rebase -i main
# 清理合并后的分支
git branch -d feature/completed-feature
# 清理远程分支引用
git remote prune origin故障排除
常见问题
bash
# 问题1: 找不到特定提交
# 解决: 使用 reflog 查找
git reflog | grep "关键词"
# 问题2: 历史太长,查看缓慢
# 解决: 使用分页或限制数量
git log --oneline -20
git log | less
# 问题3: 中文显示问题
# 解决: 配置编码
git config --global core.quotepath false
git config --global gui.encoding utf-8性能优化
bash
# 对于大型仓库,使用浅克隆
git clone --depth 1 <url>
# 获取更多历史
git fetch --unshallow
# 清理不必要的对象
git gc --aggressive --prune=now总结
Git 历史查看的核心要点:
基本命令
bash
git log # 查看历史
git log --oneline # 简洁视图
git log --graph # 图形视图
git show commit_hash # 查看特定提交
git blame file.txt # 追踪代码变更高级技巧
- 🔍 使用过滤器精确查找
- 📊 生成统计和分析报告
- 🎨 自定义格式和别名
- 🔧 使用图形工具辅助
最佳实践
- ✅ 保持清晰的提交信息
- ✅ 使用语义化提交规范
- ✅ 定期清理和整理历史
- ✅ 善用别名提高效率
掌握 Git 历史查看后,你就能够:
- 📈 分析项目发展趋势
- 🐛 快速定位问题来源
- 👥 了解团队贡献情况
- 📚 学习代码演进过程
在下一章中,我们将学习 Git 的合并操作。