.git の気になる部分

Gitの中身 を読んで、改めて .git の中身のうち簡単な部分だけ自分も手を動かして調べてみた。
この投稿自体は非常にわかりやすく、しかも完結に Git の仕組みを説明してくれているのでぜひ興味があれば読んでみてほしい。

早速いろいろと調べた過程をメモ的に書いていく。
基本的には git cat-file というサブコマンドをいろんなオブジェクトに対して実行していくだけである。

$ git cat-file -t e51ca0d0b8c5b6e02473228bbf876ba000932e96
blob

$ git cat-file -p e51ca0d0b8c5b6e02473228bbf876ba000932e96
Hello Git

※ 上記の例は、Gitの中身 より引用

前提

このブログのリポジトリ (リポジトリ自体は private になっている) の直近の数コミットを見ていこうと思う
ディレクトリ構造は以下のような形 (今回見るコミットに関係のある部分だけ抜粋している)

.
├── content
│   ├── me.md
│   ├── other.md
│   └── posts
│       ├── 2020-12-13.md
│       ├...
│       ├── 2024-12-31.md
│       └── 2025-03-03.md
└── static
    └── images
        ├── W_Framework.png
        ├....
        ├── sample_git_truck.png
        ├....
        └── writing_effective_use_cases.jpg

歴史を1つずつ見ていく

以下の直近3コミットを対象に見ていこうと思う
流れとしては、以下

git log の状態も参考程度に記載しておく

$ git log --name-status

...

commit bf0c16a
Author: omuomugin <[email protected]>
Date:   Mon Mar 3 17:42:19 2025 +0900

    add talk

M       content/other.md

commit 521fdd9
Author: omuomugin <[email protected]>
Date:   Mon Mar 3 14:27:29 2025 +0900

    post for 2025-03-03

A       content/posts/2025-03-03.md
A       static/images/sample_git_truck.png

commit 82c23f3
Author: omuomugin <[email protected]>
Date:   Wed Jan 1 00:52:13 2025 +0900

    2024-12-31.md を更新

M       content/posts/2024-12-31.md

...

82c23f3

content/posts/2024-12-31.md を編集しているコミット

$ git cat-file -t 82c23f3 # 型を見る
commit

$ git cat-file -p 82c23f3 # 内容を見る
tree 766be4a2307429193fac56f82f7a5477e94795d5
...

というように見ていったものをディレクトリとマッピングすると以下のようになる
わかりやすさのために <type:hash> という形でそれぞれのディレクトリやファイルにオブジェクトをマッピングしている

. <tree:766be4a2307429193fac56f82f7a5477e94795d5>
├── content <tree:4f6d254583aec335aaac933f5ee06bc308e64a07>
│   ├── me.md <blob:df02a3fff4c1848a1f6e0ac9d4d384d20d19368b>
│   ├── other.md <blob:7e22de699de8181ebb3e76773bb56d3ce0d8b44b>
│   └── posts <tree:e7965b6a4758b435622d82c04c6ca51b6e57e437>
│       ├── 2020-12-13.md <blob:efdb82ba98869fabbb56f9fd904cdc50b0c78e06>
│       ├...
│       └── 2024-12-31.md <blob:5ae330b60f00133d36a20751dc159c2cbc320229>
└── static <tree:ef09d0dcfa534c4ea1ec1deb62c954011685a232>
    └── images <tree:c624578e812e72d8159aa5a7f6d4552bf83fc998>
        ├── W_Framework.png <blob:a6b282ad18cc7b626f7e31543ef24f06a3ef3552>
        ├....
        └── writing_effective_use_cases.jpg <blob:6e709b1061494a531a8de9ce266cba6e442b0810>

521fdd9

content/posts/2025-03-03.md, static/images/sample_git_truck.png を追加しているコミット

82c23f3 からの diff を見ていく

$ git cat-file -t 521fdd9 # 型を見る
commit

$ git cat-file -p 521fdd9 # 内容を見る
tree 5ceb545e57aeb0b70a9828da4af2ef185e274961 # 当然 hash が異なる
...

以下の diff (ハイライトされている行が hash が変わった or 新規に追加された箇所) が示す通り、 blob オブジェクトに関しては変化がなければ新規には生成されないことがわかる

また、tree オブジェクト (ディレクトリに該当するオブジェクト) に関してはどうやら以下のような場合に新規に生成されていそうに見える

これについては、次のケースで具体見ていこうと思う

. <tree:5ceb545e57aeb0b70a9828da4af2ef185e274961>
├── content <tree:99481433a700e98d8ce32386c36e6bf85e524031>
│   ├── me.md <blob:df02a3fff4c1848a1f6e0ac9d4d384d20d19368b>
│   ├── other.md <blob:7e22de699de8181ebb3e76773bb56d3ce0d8b44b>
│   └── posts <tree:8583be520a6e4b238b02403c06e60460dff92c37>
│       ├── 2020-12-13.md <blob:efdb82ba98869fabbb56f9fd904cdc50b0c78e06>
│       ├...
│       ├── 2024-12-31.md <blob:5ae330b60f00133d36a20751dc159c2cbc320229>
│       └── 2025-03-03.md <blob:9fd96fd6c8aa6847d1f8390343e05d65d39b2efb>
└── static <tree:9246c18c3257fe7685e7c21d18d785e9e5e72446>
    └── images <tree:ab7f9ec4a39be9473f13a36381ef1b9500f513ca>
        ├── W_Framework.png <blob:a6b282ad18cc7b626f7e31543ef24f06a3ef3552>
        ├....
        ├── sample_git_truck.png <blob:94eb7be65b7c7f6a9343dcfd4b5c2561bfc3e4ae>
        ├....
        └── writing_effective_use_cases.jpg <blob:6e709b1061494a531a8de9ce266cba6e442b0810>

bf0c16a

content/other.md を編集しているコミットを見てみる

521fdd9 からの diff に注目する

$ git cat-file -t bf0c16a # 型を見る
commit

$ git cat-file -p bf0c16a # 内容を見る
tree 892832679b8739ef4cf55b430b9740a334eed25f # 当然 hash が異なる
...

/content/posts/static の tree オブジェクトが新規に作成されていないことからもわかるように「ディレクトリの中身に変更がある」場合に tree オブジェクトが新規に作成されていることになる。
(※ 本当は、 10.2 Git Internals - Git Objects とかで根拠となる仕様を見つけたかったが探すことができなかった)

. <tree:892832679b8739ef4cf55b430b9740a334eed25f>
├── content <tree:748a818ed4c2add747f05684b1f51b4c7f0a0854>
│   ├── me.md <blob:df02a3fff4c1848a1f6e0ac9d4d384d20d19368b>
│   ├── other.md <blob:db036ed1a69ab802f1336c76df93477def0f0802>
│   └── posts <tree:8583be520a6e4b238b02403c06e60460dff92c37>
│       ├── 2020-12-13.md <blob:efdb82ba98869fabbb56f9fd904cdc50b0c78e06>
│       ├...
│       ├── 2024-12-31.md <blob:5ae330b60f00133d36a20751dc159c2cbc320229>
│       └── 2025-03-03.md <blob:9fd96fd6c8aa6847d1f8390343e05d65d39b2efb>
└── static <tree:9246c18c3257fe7685e7c21d18d785e9e5e72446>
    └── images <tree:ab7f9ec4a39be9473f13a36381ef1b9500f513ca>
        ├── W_Framework.png <blob:a6b282ad18cc7b626f7e31543ef24f06a3ef3552>
        ├....
        ├── sample_git_truck.png <blob:94eb7be65b7c7f6a9343dcfd4b5c2561bfc3e4ae>
        ├....
        └── writing_effective_use_cases.jpg <blob:6e709b1061494a531a8de9ce266cba6e442b0810>

余談

ずっと積んでいるこのシリーズもいつかちゃんと読みたい (いつかの自分のお尻を叩くために書いておく)