.gitの中身を見てみる3(git commit)つづき

### お詫び

[こちら](https://qiita.com/advent-calendar/2024/lizhi05853-git)のアドベントカレンダーの5日目として登録していたこちらの記事ですが、手違いで[4日目](https://qiita.com/lizhi05853/items/75c4e9b93a428da11bc3)と全く同じ内容を投稿していたため取り下げます。

いいねとストックをしてくださった方には申し訳ございません。

5日目の記事は改めて[こちら](https://qiita.com/lizhi05853/items/f3cca143d3bc6c543eff)に投稿し直しております。

--- 

Gitでバージョン管理されたプロジェクトを扱うと、必ず `.git` というディレクトリがあります。

このディレクトリを使ってGitがバージョン管理をしているらしい、ということはなんとなく知っています。でも、具体的になにが入っていて、どう管理されているんだろう？

このアドベントカレンダーは、そんな疑問からGitを深堀りしていきます。

# `.git` の中身を見てみる3(`git commit`)

では次に、コミットするとどうなるのか確認してみます。
(ディレクトリバックアップのログは割愛)

```bash
$ git status # コミット前のステータス確認
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   a.txt

$ git commit -m 'commit test' # コミット実行
[main (root-commit) e452a0a] commit test
 Committer: user <user@machine>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 file changed, 1 insertion(+)
 create mode 100644 a.txt
$ git status # コミット後のステータス確認
On branch main
nothing to commit, working tree clean
$ 
```

コミット前後で差分を取ってみます。

```
$ diff -r .git ../git-study-before-commit/.git
.git のみに存在: COMMIT_EDITMSG
バイナリーファイル .git/index と../git-study-before-commit/.git/index は異なります
.git のみに存在: logs
.git/objects のみに存在: 58
.git/objects のみに存在: e4
.git/refs/heads のみに存在: main
$ 
```

差分が6つでてきました。
それぞれ確認します。

## 差分1(.git/COMMIT_EDITMSG)

```bash
$ ls -l .git/COMMIT_EDITMSG
-rw-r--r-- 1 user group 12 12月  4 23:14 .git/COMMIT_EDITMSG
$ cat .git/COMMIT_EDITMSG
commit test
$ 
```

コミットメッセージがそのまま入っていました。

## 差分2(.git/index)

`index` ファイルの中身はバイナリなので、以前と同様に `git ls-files` コマンドを使っていきます。

https://qiita.com/lizhi05853/items/ff68bc6376bde1c25d7c#%E5%B7%AE%E5%88%861gitindex

コミット前
```bash
$ git ls-files --stage
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0       a.txt
$ 
```

コミット後
```bash
$ git ls-files --stage
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0       a.txt
$ 
```

差分がない…。
これは別途調べたいと思います。


## 差分3(.git/logs)

`.git/logs` はディレクトリだったので、 `ls -lR`で確認します。

```bash
$ ls -lR .git/logs
.git/logs:
合計 4
-rw-r--r-- 1 user group 157 12月  4 23:14 HEAD
drwxr-xr-x 1 user group  10 12月  4 23:14 refs

.git/logs/refs:
合計 0
drwxr-xr-x 1 user group 8 12月  4 23:14 heads

.git/logs/refs/heads:
合計 4
-rw-r--r-- 1 user group 157 12月  4 23:14 main
$ 
```

下記2つのファイルがあるようです。

- .git/logs/HEAD 
- .git/logs/refs/heads/main 

```
$ cat .git/logs/HEAD 
0000000000000000000000000000000000000000 e452a0a52250236a24d1f63dd7e7fbb84d6e55c5 user <user@machine> 1733321663 +0900     commit (initial): commit test
$ cat .git/logs/refs/heads/main 
0000000000000000000000000000000000000000 e452a0a52250236a24d1f63dd7e7fbb84d6e55c5 user <user@machine> 1733321663 +0900     commit (initial): commit test
$ diff .git/logs/HEAD  .git/logs/refs/heads/main 
$ 
```

中身を見ると、同じ文言が入っていました。
コミットが1つしかないからってことでしょうか？
複数回コミットしたらどうなるのかが気になります。

## 差分4,5(.git/objects/58, .git/objects/e4)

オブジェクトファイルを2つ同時に確認します。
オブジェクトファイルもバイナリなので、 `git cat-file` コマンドを利用します。

https://qiita.com/lizhi05853/items/ff68bc6376bde1c25d7c#%E5%B7%AE%E5%88%862gitobjectse6

まず、ハッシュ値全体を確認します。

```bash
$ ls -lR .git/objects/58
.git/objects/58:
合計 4
-r--r--r-- 1 user group 52 12月  4 23:14 c608a3fa830548019591fc45f307554ca9a57f
$ ls -lR .git/objects/e4
.git/objects/e4:
合計 4
-r--r--r-- 1 user group 117 12月  4 23:14 52a0a52250236a24d1f63dd7e7fbb84d6e55c5
$ 
```

### `58c608a3fa830548019591fc45f307554ca9a57f`

```bash
$ git cat-file -t 58c608a3fa830548019591fc45f307554ca9a57f
tree
$ git cat-file -p 58c608a3fa830548019591fc45f307554ca9a57f
100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4    a.txt
$
```

`git cat-file -t [ハッシュ値]` コマンドは、指定したハッシュ値が示すオブジェクトのタイプを確認できます。
タイプについては別途投稿します。

`git cat-file -p [ハッシュ値]` コマンドでは、 `git ls-files --stage` の結果と似た結果が表示されました。

(再掲)
```bash
$ git ls-files --stage
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0       a.txt
$ 
```

### `e452a0a52250236a24d1f63dd7e7fbb84d6e55c5`

```bash
$ git cat-file -t e452a0a52250236a24d1f63dd7e7fbb84d6e55c5
commit
$ git cat-file -p e452a0a52250236a24d1f63dd7e7fbb84d6e55c5
tree 58c608a3fa830548019591fc45f307554ca9a57f
author user <user@machine> 1733321663 +0900
committer user <user@machine> 1733321663 +0900

commit test
$ 
```


`e452a0a52250236a24d1f63dd7e7fbb84d6e55c5` のほうは、ログっぽいです。

## 差分6(.git/refs/heads/main)

```bash
$ ls -l .git/refs/heads/main
-rw-r--r-- 1 user group 41 12月  4 23:14 .git/refs/heads/main
$ cat .git/refs/heads/main
e452a0a52250236a24d1f63dd7e7fbb84d6e55c5
$ 
```

またハッシュ値が出てきました。
これは、今回新しく作成されたオブジェクトファイルと同じハッシュ値ですね。
関連があるようです。

本日はここまで。

# 参考書籍・参考資料

- エンジニアのためのGitの教科書［上級編］ Git内部の仕組みを理解する
    - https://amzn.asia/d/2PJeklb
- git 公式ドキュメント
    - https://git-scm.com/book/ja/v2