😊

Gitリポジトリの中身を詳細に調べてみた

2023/06/19に公開

どのようにファイルが管理されているのか

普段何気なしに使用しているGitがどのようにファイルを管理しているのか気になったのでgit cat-fileコマンドを使用して確認してみました。

git cat-fileコマンド

公式リファレンス

Gitオブジェクトの内容、サイズ、情報を与えてくれるコマンドです。
今回は、Gitオブジェクトの 内容 を見たいのでgit cat-file -p <object>を使用していきます。

ファイルのみ

まずはあるファイルがコミットされた時の状態を確認してみましょう。

$ tree
.
└── first.txt

$ git log
commit 46c087d7cd021948bb1dafaf89bcae28dbdb4a75 (HEAD -> main)
Author: xxxxxxxx
Date:   Sun Jun 18 23:56:28 2023 +0900

    first commit

first.txtのみがコミットされた状態です。
ここでコミットオブジェクトの中身を見てみましょう。

$ git cat-file -p 46c087d7cd021948bb1dafaf89bcae28dbdb4a75
tree 59b06a677ad85669b18550663b7b666b01e9affa
author xxxxxxxx
committer xxxxxxxx 1687100188 +0900

first commit

tree 59b06a677ad85669b18550663b7b666b01e9affaという情報が出力されましたが、これはこのコミットがどのようなディレクトリ構造を持っているかを教えてくれるオブジェクト(ツリーオブジェクト)となります。では、またオブジェクトの中身を見てみましょう。

$ git cat-file -p 59b06a677ad85669b18550663b7b666b01e9affa
100644 blob 9c59e24b8393179a5d712de4f990178df5734d99    first.txt

first.txtというコミットしたファイルの名前が出てきましたね。さらに、blobという文字列が見えると思いますが、これはブロブオブジェクト、つまり、ディレクトリではなくファイルであることを示してみます。では、同じくオブジェクトの中身を見てみましょう。

$ git cat-file -p 9c59e24b8393179a5d712de4f990178df5734d99
first

オブジェクトファイルの中身を見ると、ファイルの中身を出力してくれます。
今までの結果を図で表してみると以下のようになります。
Shape Painterを使用させていただきました。

ディレクトリとファイル

ファイルひとつだけではつまらないので、ディレクトリとその配下にファイルを作成してみましょう。

$ tree
.
├── first.txt
└── second
    └── second.txt

$ git log
commit 899109fa34a32597c5ef884719e104f46561cb29 (HEAD -> main)
Author: xxxxxxxx
Date:   Mon Jun 19 00:28:53 2023 +0900

    second commit

commit 46c087d7cd021948bb1dafaf89bcae28dbdb4a75
Author: xxxxxxxx
Date:   Sun Jun 18 23:56:28 2023 +0900

    first commit

コミットオブジェクトの中身にツリーオブジェクトが存在するまでは同じためコマンドの結果は省きます。
ツリーオブジェクトの中身を見てみまましょう。

$ git cat-file -p 67551e9fa4d9474ccc1c9a44dbc2b5c1bfaa4aff
100644 blob 9c59e24b8393179a5d712de4f990178df5734d99    first.txt
040000 tree 43dd725f48c270fd09057f8a7d92f446cf05e40e    second

first.txtが存在するのは同じですが、secondというツリーオブジェクトが存在します。これは、このコミットではsecondフォルダが存在するということを示しています。それぞれのオブジェクトの結果の出力は省略し最終結果のみを図で表してみます。

オブジェクトファイル一覧

色々なオブジェクトを見てきたがそれらは全て.git/objectsに管理されている。

$ tree .git/objects
├── 43
│   └── dd725f48c270fd09057f8a7d92f446cf05e40e
├── 46
│   └── c087d7cd021948bb1dafaf89bcae28dbdb4a75
├── 59
│   └── b06a677ad85669b18550663b7b666b01e9affa
├── 67
│   └── 551e9fa4d9474ccc1c9a44dbc2b5c1bfaa4aff
├── 89
│   └── 9109fa34a32597c5ef884719e104f46561cb29
├── 9c
│   └── 59e24b8393179a5d712de4f990178df5734d99
├── e0
│   └── 19be006cf33489e2d0177a3837a2384eddebc5
├── info
└── pack

例えば9c59e24b8393179a5d712de4f990178df5734d99というオブジェクトファイルは

├── 9c
    └── 59e24b8393179a5d712de4f990178df5734d99

に相当する。
さて、オブジェクトファイルのファイル名、中身はどのように決められているのかについてはGitオブジェクトを参照していただければと思います。

まとめ

通常のディレクトリ構造はディレクトリとファイルで構成されていますが、それぞれがGitリポジトリの文脈では「ツリーオブジェクト」、「ブロブオブジェクト」として管理されていることがわかりました。

Discussion