Git Internals

提交对象、父提交与提交说明教程

说明提交对象如何把 tree、父提交和说明文本连接成历史图。

适合谁看
  • 想建立稳定 Git 心智模型的学习者
  • 经常遇到历史、引用、恢复问题的开发者
前置知识
  • 会看基础命令输出
  • 知道提交、分支、HEAD 这些名词
常见风险
  • 只背底层术语却不连接到实际命令
  • 把对象、引用、工作区混成一层理解

学完这篇你会掌握什么

  • 理解 提交对象、父提交与提交说明教程 的核心作用和适用场景
  • 掌握 提交对象、父提交与提交说明教程 的基本用法和常用参数
  • 说明提交对象如何把 tree、父提交和说明文本连接成历史图。
  • 理解 1. 提交对象里至少有什么 相关的概念
  • 掌握 2. 为什么父提交很关键 相关的操作
  • 知道在什么场景下使用该命令,什么场景下避免使用

先想一个问题

你每天都在用 Git 命令,但偶尔会遇到一些 '奇怪' 的行为——比如明明没改文件却被提示有改动,或者 rebase 时突然多了预期之外的冲突。你想理解 Git 底层是怎么工作的。

一句话理解

commit 对象不是“写一句提交说明”那么简单,它真正做的是把一次项目快照、父子关系和元数据固定成历史节点。

1. 提交对象里至少有什么

提交如何通过父提交链接成历史每个 commit 对象包含指向 tree 的引用、一个或多个父提交、作者和提交者信息,以及提交说明。父提交是历史图的关键链接。
普通提交(一个父节点)
ABCD
HEAD 指向: main
Merge 提交(两个父节点)
ABCM
BEF
Rebase 后提交(新 ID 的提交链)
ABCE'F'
HEAD 指向: feature

一个 commit 对象通常会包含:

  • 指向当前快照根 tree 的信息
  • 一个或多个父提交
  • author / committer 信息
  • 提交说明

所以 commit 的价值是把“内容状态”和“历史位置”同时固定下来。

2. 为什么父提交很关键

如果没有 parent,Git 就无法表达历史图。

父提交关系决定了:

  • 当前提交是从哪里接出来的
  • merge commit 为什么会有多个父节点
  • rebase 为什么会生成新的提交对象

你看到的日志线条、分支汇合、祖先关系,本质上都依赖 parent 字段。

3. 提交说明为什么不是附属品

提交说明不仅是给人看的文字,它也是 commit 对象内容的一部分。

这意味着:

  • 只改提交说明,提交对象就变了
  • 对象一变,提交 ID 也会变

所以 amend message 不是“只改了备注”,而是生成了新的 commit 对象。

4. 为什么 commit ID 会变

因为 commit 对象里保存的不只是 tree,还包括 parent 和 message。

只要以下任一项变化:

  • 当前 tree 不同
  • parent 不同
  • message 不同
  • 作者信息不同

commit 对象就不再是同一个对象,ID 也就跟着变化。

5. merge commit 和普通提交有何不同

普通提交大多只有一个父提交。
merge commit 往往有两个父提交。

这意味着 merge commit 不只是“有新的内容状态”,它还在历史结构上明确记录了“两条线在这里汇合”。

6. 为什么这能帮助你理解 rebase

rebase 之所以被称为“改写历史”,不是因为它偷偷改了旧提交,而是因为:

  • 新基底变了
  • parent 关系变了
  • 因而必须生成新的 commit 对象

这就是为什么 rebase 后同样内容的提交,ID 也会不一样。

7. 从 commit 对象角度重新看常见操作

git commit

新增一个 commit 对象,并让当前分支引用移动到它。

git commit --amend

不是给原提交“补充说明”,而是重新生成一个新的 commit 对象来替换当前位置。

git merge

通常会新增一个有多个父提交的 commit。

常见误区

commit 主要就是一段 message

不是。message 只是 commit 对象里最容易被人直接看到的一部分。

amend 不算改写历史

从对象模型上看,算。因为新的 commit 对象已经不是原来那个了。

merge commit 只是把代码合进来

还不止。它也把“两边历史在这里汇合”的结构写进了图里。

一个最值得记住的结论

commit 不是日志条目,而是一个把快照、父链和说明一起固定下来的历史节点。

给你的练习

  1. 在一个测试仓库中练习该命令的基本用法,观察执行前后的状态变化
  2. 尝试该命令的不同参数选项,对比输出结果的差异
  3. 模拟一个需要使用该命令的实际场景,完整走一遍操作流程

延伸阅读

沿着同一主题继续深入: