← Gitの内部構造から理解する コース
4. コミットハッシュとtreeの対応 — スナップショットと親への参照
blobとtreeで「ある時点のディレクトリ全体」を表せるようになりました。commitは、そのスナップショット1つに、誰がいつ何のために作ったかというメタデータと、直前のコミットへの参照を添えたものです。
① commitオブジェクトの中身は数行のテキスト
tree 7ed5c15d…この時点のディレクトリ全体を指す(必ず1つ)
parent 0978f6e0…直前のコミットを指す
author / committer名前・メールアドレス・タイムスタンプ
(空行) + コミットメッセージ
- ・commitはこのテキスト全体のSHA-1で識別される
- ・最初のコミットには parent 行がない(履歴の起点)
- ・マージコミットは parent 行を2つ持つ
commitが持つtreeは1つだけです。「このコミットの時点でのファイル全体の姿」がその1つのtreeで完全に決まります。
② 履歴は「親をたどる連結リスト」になっている
commit C(最新)parent → B
parent をたどる
commit Bparent → A
parent をたどる
commit A(最初)parent 行なし = 終端
- ・矢印は必ず「新しい → 古い」の向き。子から親は辿れるが、逆は辿れない
- ・親を持たないコミットに到達したら、そこが履歴の始まり
- ・マージがあると分岐が合流するので、正確には有向非巡回グラフ(DAG)になる
git log が過去へさかのぼれるのは、この parent の鎖をたどっているからです。「未来のコミット一覧」が存在しないのも、矢印が片方向だからです。
③ コミットハッシュは履歴全体を封じ込めている
commit C のハッシュ
計算に含まれるもの
tree のハッシュ= 全ファイルの中身
parent のハッシュ= それ以前の全履歴
作者・日時・メッセージ
- ・親のハッシュはさらにその親のハッシュを含んでいる(再帰的)
- ・つまり最新のコミットハッシュ1つで、履歴全体が確定する
- ・過去のコミットを1文字でも書き換えると、それ以降すべてのハッシュが変わる
この構造をハッシュチェーンと呼びます。後の rebase のレッスンで「なぜ履歴を書き換えるとハッシュが総取り替えになるのか」が、ここから直接説明できます。
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗