Dev Study
← Gitの内部構造から理解する コース

3. treeオブジェクト — ディレクトリ構造をどう表すか

blobは中身しか持っていませんでした。「どのファイル名で、どの階層に置かれているか」を担当するのが tree です。treeは1つのディレクトリに対応します。

① treeは「名前 → ハッシュ」の対応表

a.txt と sub/ を含むディレクトリの tree
tree 9e88965…ルートディレクトリを表す
中身は2行のエントリ
100644 blob ce013625… a.txt通常ファイル
040000 tree 721eea74… subサブディレクトリ
  • ・各エントリは「モード / 型 / ハッシュ / 名前」の4つ組
  • ・100644 は通常ファイル、100755 は実行可能ファイル、40000 はディレクトリ
  • ・treeが別のtreeを指すことで、階層がいくらでも深くなれる

ファイル名はここに現れます。blobは「中身」、treeは「名前と構造」と、役割がはっきり分かれています。

② 入れ子のtreeでディレクトリ階層を作る

tree が tree を指す構造
tree(ルート)a.txt と sub を持つ
sub エントリが指す先
tree 721eea74…sub ディレクトリ
その中の b.txt エントリが指す先
blob cc628ccd…world の中身
  • ・ディレクトリ1つにつき tree が1つ対応する
  • ・葉(leaf)は必ず blob になる
  • ・ファイルシステムのディレクトリ構造がそのまま木構造になっている

treeも中身から計算されたハッシュを持ちます。中のファイルが1つでも変われば、そのtreeのハッシュも変わります。

③ 変わっていないディレクトリは使い回される

a.txt だけ編集して2回目のコミットをしたとき
1回目のルートtree 9e88965…
2回目のルートtree 7ed5c15d…
それぞれの sub エントリを見ると
どちらも tree 721eea74… を指しているsub の中身は変えていないので同じハッシュ
  • ・変更のないサブツリーは、新しいオブジェクトを作らずそのまま共有される
  • ・変わるのは「変更したファイルから根までの経路」だけ
  • ・巨大なリポジトリでもコミットが軽いのはこのため

毎回すべてをコピーしているように見えて、実際に増えるのは変更に関係する部分だけです。この構造を永続データ構造と呼びます。

サンプルコードで身につける(5本) →

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

公式ドキュメントで詳しく ↗