Dev Study
← 解説「コミットハッシュとtreeの対応 — スナップショットと親への参照」に戻る

サンプルコードで身につける: コミットハッシュとtreeの対応 — スナップショットと親への参照

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1実際のコミットの中身を見る

commitオブジェクトはただの数行のテキストです。1つ目のコミットには parent 行がなく、2つ目には前のコミットを指す parent 行が付いていることを、実際の出力で確認してください。

# 最初のコミット
$ git cat-file -p 3a72bb1
tree b4b9a853c3ffc746b9f0ce42ad8216540e74206e
author Tanaka <tanaka@example.com> 1700000000 +0900
committer Tanaka <tanaka@example.com> 1700000000 +0900

初期コミット
                       ↑ parent 行がない = 履歴の起点

# 2つ目のコミット
$ git cat-file -p dd2818b
tree 68bd1e3558ff34e67e1301c8eefbbaac3f8aa842
parent 3a72bb1be654931c3afba45c654a7ee444e09206   ← 1つ前を指している
author Tanaka <tanaka@example.com> 1700000100 +0900
committer Tanaka <tanaka@example.com> 1700000100 +0900

READMEに使い方を追加

2コミットのIDを自分で計算して一致させる

commitも「テキストにヘッダを付けてSHA-1」です。実機のコミットと同じ内容を組み立てると、同じハッシュ 3a72bb1… が出ます。ここまで来ると、Gitに魔法が無いことが分かります。

Python

3履歴を親でたどる = git log がしていること

git log は魔法ではなく、HEADから parent を1つずつ辿っているだけです。実際のリポジトリのコミットを使って、その動きを再現します。矢印が必ず「新しい→古い」の一方向であることを確認してください。

Python

4最新のハッシュ1つで履歴全体が確定する

コミットのハッシュは親のハッシュを含んで計算され、その親もさらに親を含んでいます。だから過去を1つ書き換えると、それ以降すべてのハッシュが変わります。実際に途中を改ざんして連鎖を観察します。

Python

5同じ内容でも作者や時刻が違えば別のコミット

「同じファイル内容ならコミットも同じ」ではありません。treeが同じでも、時刻・作者・メッセージ・親が違えばIDは変わります。cherry-pickで同じ変更を持ってきてもハッシュが変わる理由がこれです。

Python