Git Internals
Git 提交图与历史表达
理解为什么 Git 历史本质上是提交图,而不是简单时间线,以及 merge、rebase 如何重新表达这张图。
- 想建立稳定 Git 心智模型的学习者
- 经常遇到历史、引用、恢复问题的开发者
- 会看基础命令输出
- 知道提交、分支、HEAD 这些名词
- 只背底层术语却不连接到实际命令
- 把对象、引用、工作区混成一层理解
数据 / 性能事实
- O(log N)commit-graph enables bounded reachability queries instead of walking full object chains出处: git-commit-graph(1) official manual
关键引语
The commit-graph file stores the commit graph structure and selected commit metadata in a binary format to speed up graph walks used by commands like git log --graph and git status.
学完这篇你会掌握什么
- 理解 Git 提交图与历史表达 的核心作用和适用场景
- 掌握 Git 提交图与历史表达 的基本用法和常用参数
- 理解为什么 Git 历史本质上是提交图,而不是简单时间线,以及 merge、rebase 如何重新表达这张图。
- 理解 1. 为什么“历史图”比“提交列表”更准确 相关的概念
- 掌握 2. 普通提交如何形成一条线 相关的操作
- 知道在什么场景下使用该命令,什么场景下避免使用
先想一个问题
你每天都在用 Git 命令,但偶尔会遇到一些 '奇怪' 的行为——比如明明没改文件却被提示有改动,或者 rebase 时突然多了预期之外的冲突。你想理解 Git 底层是怎么工作的。
一句话理解
Git 保存的是提交图。线性日志只是这张图的一种阅读方式,不是 Git 底层真正的唯一结构。
1. 为什么“历史图”比“提交列表”更准确
如果把 Git 历史只理解成列表,你会很难解释:
- merge commit 为什么会有两个父节点
- rebase 为什么会生成一组新的提交 ID
- 为什么同一段改动能以不同图形结构被表达
把它看成图之后,这些现象就自然很多。
2. 普通提交如何形成一条线
大多数提交只有一个父提交,因此从阅读体验上会像一条线:
A -> B -> C -> D
这只是“图在这个局部看起来像线”,并不代表 Git 只有线性结构。
3. merge commit 表达了什么
merge commit 往往有两个父节点。它告诉 Git:
- 这里有两条历史线
- 它们在这个提交处汇合
所以 merge 的价值不只是“把代码拼起来”,还在于把“曾经并行开发过”这个事实保留下来。
4. rebase 为什么看起来更线性
rebase 的做法不是修改旧提交,而是:
- 取出一组提交表达的改动
- 换到新的基底上
- 重新生成一组提交对象
结果就是:
- 图结构被重新表达
- 提交 ID 会变化
- 阅读上通常更线性
5. merge 和 rebase 的真正差异
它们都可以完成“把两边改动整合起来”这件事,但历史表达不同。
merge
- 保留分叉与汇合
- 历史图更忠实于协作过程
- 已共享历史通常更安全
rebase
- 让一组提交接到新的基底后面
- 历史看起来更直
- 适合整理尚未共享的个人分支
6. 为什么 commit ID 会跟着历史结构变化
因为 commit 对象里不仅保存内容快照,还保存父提交关系。只要父节点不同,commit 对象就不是同一个对象,ID 也会跟着变化。
这就是 rebase 会“改写历史”的底层原因。
7. 为什么看图能帮助你判断风险
当你知道历史是图,就更容易判断:
- 某个 merge commit 是不是一个真实的汇合点
- 当前分支是不是只比主线多出一小段未共享提交
- reset 或 force push 会不会让别人依赖的路径突然消失
8. 用图来重新理解常见命令
git log --graph
它不是在“制造图”,而是在把已经存在的提交父子关系可视化。
git merge
它常常是在图里新增一个有多个父节点的提交。
git rebase
它会把旧改动重新表达成另一段提交链。
git cherry-pick
它会把某个提交表达的改动单独复制成一条新的提交节点。
常见误区
rebase 只是把提交“挪一挪”
不准确。更准确的说法是:rebase 基于新的父链重新生成提交对象。
merge 比 rebase 更“脏”
这不是底层结论,而是阅读偏好和协作策略差异。merge 更强调保留真实分叉结构,rebase 更强调线性表达。
一个实用判断原则
如果你关心“团队真实怎样并行协作过”,merge 的图更直观;如果你关心“合并前把自己的一段提交整理清楚”,rebase 更合适。
给你的练习
- 在一个测试仓库中练习该命令的基本用法,观察执行前后的状态变化
- 尝试该命令的不同参数选项,对比输出结果的差异
- 模拟一个需要使用该命令的实际场景,完整走一遍操作流程
延伸阅读
沿着同一主题继续深入: