8. Git diff与日志:看透每一次变更
说实话,Git 最让我着迷的地方,就是它把「变化」这件事记录得清清楚楚。你改了什么、谁改的、为什么改,全都能追溯。这一章,我就带你把这几个看家本领学透。
8.1 git diff:对比差异的瑞士军刀
git diff 说白了就是「找不同」。我在项目里几乎每天都要用,尤其是 code review 的时候。
8.1.1 工作区 vs 暂存区
你改完代码还没 git add 的时候,想看看改了啥?
git diff
这个命令比较的是工作区和暂存区的差异。嗯,这里要注意:如果你已经 git add 了,再改文件,git diff 只会显示新改的部分,不会显示已经暂存的内容。
8.1.2 暂存区 vs 最近提交
想看看你准备提交的内容和上一次提交有啥区别?
git diff --staged
# 或者
git diff --cached
我个人习惯用 --staged,语义更清晰。有一次我差点把调试代码提交上去,就是靠这个命令发现的。
8.1.3 任意两次提交的对比
你可以比较任意两个 commit:
git diff <commit1> <commit2>
比如:
git diff abc123 def456
它会按时间顺序显示差异。如果你只想看某个文件的变更:
git diff abc123 def456 -- src/main.js
8.1.4 只看文件名
有时候我只想知道哪些文件变了,不想看具体内容:
git diff --name-only
git diff --name-status # 还会显示变更类型(M/A/D)
git diff --stat
8.2 git log 高级用法:不只是看历史
git log 默认输出太啰嗦了。我刚开始用的时候,满屏的 commit 信息看得头疼。后来发现,加几个参数就能让它变得清爽。
8.2.1 美化输出
git log --oneline --graph --all --decorate
这个组合我几乎天天用。--oneline 只显示一行,--graph 画出分支图,--all 显示所有分支,--decorate 标出分支和标签的位置。
8.2.2 按作者筛选
git log --author="张三"
想看看某个同事最近在忙啥?或者复盘自己这周干了啥?这个命令很实用。
8.2.3 按时间筛选
git log --since="2024-01-01" --until="2024-06-30"
git log --after="2 weeks ago" # 两周内的提交
8.2.4 按内容搜索
你想想看,有时候你只记得改过某个关键词,但不知道是哪个 commit:
git log -S "某个函数名"
这个 -S 参数会搜索每次提交中新增或删除了该字符串的 commit。我曾经用它找回过一个被误删的配置项。
8.2.5 查看某个文件的修改历史
git log --follow -p src/utils.js
--follow 会跟踪文件重命名,-p 会显示每次修改的具体内容。
8.3 git blame:谁动了我的代码?
这个命令的名字挺有意思——「追责」。不过别想歪了,它不是为了甩锅,而是为了搞清楚某行代码的来龙去脉。
git blame src/app.js
输出结果会显示每一行代码是谁、在哪个 commit、什么时间写的。比如:
abc12345 (张三 2024-03-15 10:30:00 +0800 42) const MAX_RETRIES = 3;
我曾经遇到过一个 bug,某行代码的逻辑明显有问题。用 git blame 一看,发现是三个月前一次紧急修复引入的。找到当事人一问,原来当时漏了一个边界条件。
8.3.1 只看某几行
git blame -L 42,60 src/app.js
只看第 42 到 60 行,省得翻半天。
8.3.2 忽略空白变更
git blame -w src/app.js
有些人改代码喜欢顺手格式化,-w 参数会忽略空白字符的变更,直接找到真正改逻辑的人。
8.4 git reflog:后悔药在这里
git reflog 是我最爱的命令之一。它记录了你在本地仓库的所有操作——包括那些「我以为我删掉了」的东西。
git reflog
输出类似这样:
abc1234 HEAD@{0}: commit: 修复登录bug
def5678 HEAD@{1}: reset: moving to HEAD~1
789abcd HEAD@{2}: commit: 添加新功能
...
看到了吗?即使你 reset 了、rebase 了、甚至删除了分支,只要操作还在 reflog 里,就能找回来。
8.4.1 恢复误删的提交
有一次我不小心 git reset --hard 丢了一个重要的提交。当时冷汗都出来了。后来用 reflog 找到了那个 commit 的 hash,然后:
git cherry-pick abc1234
完美恢复。嗯,从那以后我再也不怕误操作了。
8.4.2 reflog 的保质期
reflog 不是永久保存的。默认情况下,90 天内的「可达」提交和 30 天内的「不可达」提交会被保留。你可以配置:
git config gc.reflogExpire 180 # 不可达提交保留180天
git config gc.reflogExpireUnreachable 90 # 可达提交保留90天
知识体系总览
下面这张图,帮你把这一章的核心逻辑串起来:
这四个工具各有侧重:diff 看「变化内容」,log 看「变化历史」,blame 看「变化来源」,reflog 看「操作记录」。配合使用,基本能覆盖日常开发中所有的追溯需求。
git log --oneline --since="today",看看今天提交了啥。每周用 git diff --stat HEAD~7 回顾一周的工作量。养成习惯后,你会对项目的变化了如指掌。
公众号:蓝海资料掘金营,微信deep3321