2.6 查看仓库状态(git status)与历史(git log)


2.6 查看仓库状态(git status)与历史(git log)

本节摘要git status 回答"现在仓库是什么状态",git log 回答"项目过去发生了什么"。本节先逐段拆解 status 的四类输出(分支、未跟踪、未暂存、已暂存),再讲 log 的基本结构、格式化选项(--oneline、--graph、--decorate)、过滤选项(-n、--author、--since、--grep、路径范围),最后给出两者配合使用的日常工作流。

读前必看

阅读完本节,你应当能够:

  1. 完整解读 git status 输出中的分支信息、三类文件状态与"干净"提示。
  2. 用 git status -s 的紧凑格式快速判断每个文件的暂存状态。
  3. 用 git log 查看历史,并能用 --oneline、--graph、--decorate 组合出友好视图。
  4. 用 -n、--author、--since、--grep 和路径参数过滤提交历史。

一、问题与直觉

新手第一次用 Git 时,眼睛常常是蒙的:屏幕上刷出一大段文字,绿的红的一大堆,完全不知道哪些重要、哪些可以无视。有人索性不看 status,凭感觉 add 提交,结果提交内容总和自己想的不一样。

其实 status 的输出是有固定结构的,就像机场的航班信息大屏——看起来信息很多,但每一行都有固定位置和含义。看懂它,你就能随时掌握"仓库现在处于什么状态、下一步该做什么"。

log 则是另一块屏:它显示历史航班,让你知道"这架飞机是怎么一路飞过来的"。看历史不是考古癖,而是排查问题的起点——"这个 bug 是哪次改动引入的"这个问题,全靠 log 才能回答。

这两个命令一个管"现在",一个管"过去",配合使用,等于给仓库装了一前一后两块仪表盘。本节的目标,就是让你把这两块仪表盘彻底读熟。

还有一个常被忽略的事实:status 是很多人的"第一命令",但它不该是唯一命令。只看 status 不看 log,你对仓库的理解停留在"现在有什么";加上 log,你才拥有"项目怎么一路走来"的完整视角。排查 bug、评估改动影响、了解队友工作进度,全都依赖 log。所以本节特意把两者放在一起讲——它们是一对,不是两个。一个管眼前的路况,一个管来时的路线,少了任何一块仪表盘,你都在盲开。

二、核心原理

status:仓库的实时仪表盘

git status 的输出按从上到下顺序分为几个区:

第一区:当前分支。 顶部 On branch main 告诉你现在在哪条分支上。

第二区:与远程的关系。 如果分支跟踪了远程分支,会提示领先/落后/同步(如 Your branch is up to date with 'origin/main')。

第三区:未跟踪文件。 Untracked files 区列出 Git 从没见过的新文件,提示用 add 开始跟踪。

第四区:未暂存的修改。 Changes not staged for commit 区列出已跟踪但工作区有改动、还没 add 的文件。

第五区:已暂存的修改。 Changes to be committed 区列出已 add、等待提交的文件。

干净提示。 如果一切都已提交,显示 nothing to commit, working tree clean——这是最让人安心的一行。

一个文件可能同时出现在第四区(工作区有新改动)和第五区(暂存区有旧版本)——这就是三区不一致的正常呈现。

图 2-6 git status 的五个信息区

图 2-6 git status 的五个信息区

status 的一个完整示例

把空泛的描述换成真实输出,感受一下它的结构:

On branch main Your branch is ahead of 'origin/main' by 2 commits. (use "git push" to publish your local commits) Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: readme.md modified: app.js Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: config.json Untracked files: (use "git add <file>..." to include in what will be committed) notes/

解读这份输出:你在 main 分支,本地领先远程 2 个提交(该 push 了);readme.md 是新文件已暂存,app.js 的某版本已暂存;config.json 在工作区改了但没 add;notes/ 目录整个是新的没跟踪。注意 status 还贴心地把每条建议命令写在括号里——它就是一份自带操作说明的体检报告,照着提示走基本不会错。

status -s:紧凑模式

git status -s(--short)把每行压成"两位状态码 + 文件名",适合快速扫描:

状态码 含义
?? 未跟踪
A 已暂存的新文件
M 工作区已修改
M 暂存区有修改
D 工作区已删除
AM 已暂存又改过

两位状态码第一位代表暂存区,第二位代表工作区。MM 表示"暂存区和工作区都有修改"。

log:项目的历史档案

git log 默认按时间倒序列出所有提交,每条包含哈希、作者、日期、提交消息:

commit f1234567890... Author: 张三 <zhangsan@example.com> Date: Mon Jan 1 10:00:00 2023 +0800 修复订单超时 bug

哈希是完整 40 位 SHA-1,日常用前 7 位就够区分了。

格式化选项

git log --oneline # 每行一条:短哈希+消息 git log --graph --oneline # 加 ASCII 分支图 git log --graph --oneline --decorate # 再加分支/标签标注

最后一条组合是日常最常用的"漂亮历史"视图,能一眼看清分支怎么分叉、又在哪里合并。

过滤选项

git log -n 5 # 最近 5 条 git log --author="张三" # 按作者 git log --since="2023-01-01" # 指定日期之后 git log --until="2023-02-01" # 指定日期之前 git log --grep="bug" # 按提交消息关键词 git log -- 文件名 # 指定文件的提交 git log main..feature # feature 有而 main 没有的提交

这些过滤选项可以组合,比如 git log --oneline --author="张三" --since="2024-01-01" 查"张三今年改了什么"。

log 的三种视图对比

同样是三条提交,三种命令呈现的信息量天差地别:

默认视图(信息最全,适合细看):

commit 9f8e7d6a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e Author: 张三 <zhangsan@example.com> Date: Mon Aug 12 10:00:00 2024 +0800 接入用户登录接口 commit a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8g9h Author: 李四 <lisi@example.com> Date: Sun Aug 11 18:30:00 2024 +0800 添加登录表单页面

--oneline 视图(一屏扫很多条,适合浏览):

9f8e7d6 接入用户登录接口 a1b2c3d 添加登录表单页面 4d5c6b7 初始化项目结构

--graph --decorate 视图(带分支信息,适合看结构):

* 9f8e7d6 (HEAD -> main, origin/main) 接入用户登录接口 * a1b2c3d Merge branch 'feature/login' |\ | * 5f6e7d8 (feature/login) 调整表单校验逻辑 * | 3c4d5e6 修复导航栏样式 |/ * 4d5c6b7 初始化项目结构

第三种视图里 HEAD -> main 表示当前 HEAD 指向 main,origin/main 表示远程跟踪分支,feature/login 是另一个本地分支。看懂这个图,你就掌握了第 3、4 章分支与远程概念的可视化入口。

一个 log 实战排查案例

假设线上有个 bug,你怀疑是两周内某个提交引入的。排查路径:

# 先看最近两周有哪些提交 git log --since="2 weeks ago" --oneline # 锁定了某个可疑提交,看它改了哪些文件 git show --stat 可疑提交哈希 # 再看具体改动内容 git show 可疑提交哈希 # 用 grep 找提交信息里提到该功能的提交 git log --grep="订单" --oneline

这套组合拳在真实工作中一天能用好几次。第 5 章还会介绍更强大的 git bisect,能在几十个提交里自动二分定位问题提交——但日常排查,先练熟 log 的过滤就够了。

三、工程实践要点

status 的兄弟命令:diff

status 告诉你"哪些文件变了",diff 告诉你"具体怎么变的"。两者常搭配使用:

git diff # 工作区与暂存区的差异(未暂存的改动) git diff --cached # 暂存区与上一次提交的差异(已暂存的改动) git diff HEAD # 工作区+暂存区与最近提交的差异 git diff 提交A 提交B # 两个提交之间的差异

日常最常用的是前两个:提交前用 git diff 看自己还没暂存的改动,确认没改错;git diff --cached 看即将提交的内容。这两条命令是"提交前最后一分钟检查"的实质工具。

status 与 log 的配合工作流

日常的"我该做什么"检查循环通常是这样:

  1. git status:看当前有什么改动、该暂存哪些。
  2. 按需 git add,再 git status 确认暂存结果。
  3. 提交前 git diff --cached:看已暂存内容。
  4. 提交后 git log --oneline -n 5:确认提交成功。
  5. 排查历史问题时,用过滤选项缩小范围。
场景 用什么
看当前状态 git status
快速扫文件状态 git status -s
看未暂存改动细节 git diff
看已暂存改动细节 git diff --cached
看最近提交 git log --oneline -n 5
看分支历史 git log --graph --oneline --decorate
找某作者的改动 git log --author
找某个 bug 相关提交 git log --grep

三个值得养成的习惯

第一,提交前必看 status。 这是最便宜的安全检查——一次 status 敲击,能避免"把不该提交的提交了"。

第二,习惯用 -s 扫状态。 熟悉紧凑格式后,扫一眼比读完整输出快得多。

第三,把 --graph --oneline --decorate 存成别名。 回到 2.1 节那个 lg 别名,git lg 一敲就是漂亮历史。

一个可视化辅助技巧

如果你习惯看图形界面,可以在终端里试 git log --graph --all 或直接打开 gitk——它们把提交历史画成树状图,分支分叉、合并点一目了然。IDE(VS Code、JetBrains)的 Git 面板也有类似视图。工具不同,底层数据相同,用哪个全凭习惯。我的建议是命令行为主、图形为辅:命令行让你理解机制,图形让你快速概览,两者互补不冲突。

⚠️ 常见坑:提交后不看 log 就直接 push。有时你以为提交成功了,其实被 pre-commit 钩子拦下、或提交到了错误分支。提交完瞄一眼 log,确认哈希和消息都对,再推不迟。

💡 关键直觉:把 status 当"后视镜",log 当"行车记录仪"。后视镜看当下路况决定下一步动作;记录仪回放过去,出了事故(bug)就知道责任方在哪一帧。

常见问题与 FAQ

"status 输出太长了,怎么办?" 用 -s 紧凑模式,或者只关心特定区——多数时候你只需要看"有没有未提交改动"这个结论。

"log 里怎么按时间范围过滤?" 用 --since 和 --until,日期格式灵活,支持"2023-01-01"和"2 weeks ago"这类写法。

"怎么知道某个文件的历史改动?" git log -- 文件路径 列出该文件的提交,配合 git show 哈希 看具体内容。

"git log 和 git reflog 有什么区别?" log 显示提交历史(项目内容的变化),reflog 显示 HEAD 指针的移动记录(包括 reset、checkout 等操作),后者是第 5 章历史修改的救生索,现在先记住它俩不同即可。

"怎么看某次提交改了什么?" git show 提交哈希 显示那次提交的完整 diff;git show --stat 提交哈希 只显示改动文件列表。

"log 输出太多,只想看最近几条怎么办?"-n--max-count 限制条数,git log -n 5 只显示最近 5 条;配合 --oneline 单行显示,几屏历史瞬间压缩成五行。这是日常用得最多的组合之一。

一个容易混淆的点:status 里的"领先落后"是什么意思

当你的分支跟踪了远程分支,status 会显示 Your branch is ahead of 'origin/main' by 2 commitsbehind 之类的字样。这里其实藏着远程协作的核心机制:

  • ahead(领先):你本地有远程没有的提交——你做了新提交但还没 push,该推送了。
  • behind(落后):远程有你本地没有的提交——别人推了新代码,你该 pull 了。
  • ahead and behind(既领先又落后):双方都有新提交,历史分叉了,需要 pull 后合并或 rebase 再 push。

现在不必动手处理这些(第 4 章全是这个),但读懂这两行字,等于提前知道了"远程同步的晴雨表"——每天开工前跑一次 status,就能判断今天的协作状态。同样地,提交后跑一次 status,看到"working tree clean"也会更安心——那意味着你的现场干干净净,随时可以放心做下一步。

关于"读输出"的方法论

最后给一个通用方法论:Git 的每个命令输出都不是噪音,而是结构化信息。status 分区、log 字段、diff 的行前缀(+/-)都有固定含义。遇到看不懂的输出,第一反应不该是"跳过",而是"它为什么这样写"——Git 的输出设计本身就试图教会你它的模型。比如 status 括号里的提示命令、log 里 40 位哈希只显示 7 位的习惯,都是工具向使用者传达信息的渠道。养成"读懂输出"的习惯后,你会发现报错信息也大多能看懂,排查问题的能力会整体上一个台阶。到那时,你不再是"背命令的人",而是"会读仓库的人"。

核心回顾

  • status 五区:分支、远程关系、未跟踪、未暂存、已暂存,加"干净"提示。
  • -s 紧凑格式:两位状态码,第一位暂存区、第二位工作区。
  • log 基础:哈希、作者、日期、消息,按时间倒序。
  • 格式化:--oneline、--graph、--decorate 组合成漂亮历史视图。
  • 过滤:-n、--author、--since、--until、--grep、路径、范围。
  • diff 搭档:git diff 看未暂存改动,git diff --cached 看已暂存改动。
  • 领先落后:ahead 该 push、behind 该 pull,是远程同步晴雨表。
  • 配合工作流:status 看当下、diff 看细节、log 看历史。
  • 习惯:提交前必看 status,提交后瞄一眼 log。
  • 方法论:Git 输出是结构化信息,读懂它等于读懂了 Git 的模型。

下一节进入撤销与恢复:改错了怎么办——restore 与 reset 的分工,这里是救命的章节。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U