Gitの内部の動きを知ろう　～その２～

### [目次](https://qiita.com/as-chapa/items/246b03c671bd798d50a8)

# 今回の確認内容
[その１](https://qiita.com/as-chapa/items/58eadd4f56ad3a17a8c8)で作ったリポジトリに対して、さらにファイルを追加してcommitまで実施します。すでにあるファイルへの変更も実施してみます。

## git add
初期状態のおさらいです。前回ファイルをひとつ追加してcommitまでしたことで以下のようになっています。

```
$ tree -a
.
├── .git
│   ├── COMMIT_EDITMSG
│   ├── HEAD
│   ├── branches
│   ├── config
│   ├── description
│   ├── hooks
│   │   ├── applypatch-msg.sample
│   │   ├── commit-msg.sample
│   │   ├── fsmonitor-watchman.sample
│   │   ├── post-update.sample
│   │   ├── pre-applypatch.sample
│   │   ├── pre-commit.sample
│   │   ├── pre-push.sample
│   │   ├── pre-rebase.sample
│   │   ├── pre-receive.sample
│   │   ├── prepare-commit-msg.sample
│   │   └── update.sample
│   ├── index
│   ├── info
│   │   └── exclude
│   ├── logs
│   │   ├── HEAD
│   │   └── refs
│   │       └── heads
│   │           └── master
│   ├── objects
│   │   ├── 04
│   │   │   └── fc877e35cb6c9bd038084d6b0fa8eae043884d
│   │   ├── 17
│   │   │   └── e88b45fdb1b3e8831df0c209204f290d6ca614
│   │   ├── af
│   │   │   └── 5626b4a114abcb82d63db7c8082c3c4756e51b
│   │   ├── info
│   │   └── pack
│   └── refs
│       ├── heads
│       │   └── master
│       └── tags
└── l_helloworld.txt

16 directories, 24 files
```
では早速ファイルを追加してみます。

```
$ echo "create new one" > l_createnewone.txt
$ echo "Hello, world!" > l_helloworld2.txt
$ ls
l_createnewone.txt  l_helloworld.txt  l_helloworld2.txt
```
前回作った「l_helloworld.txt」と同じ内容で「l_helloworld2.txt」を作りました。
この状態でインデックスにファイルを追加します。

```
.
├── .git
│   ├── objects
│   │   ├── b4
│   │   │   └── c191b61e50e6416dfa68f3042973539b2655f5
```

2つのファイルを追加したはずなのになぜかobjectsには1つのファイルしか追加されていません。gitはblobオブジェクトのハッシュ値はファイルの内容で決まっています。「l_helloworld2.txt」は「l_helloworld.txt」と全く同じ内容だったので、新しくオブジェクトが作られていません。
新しく作られたb4c191b61e50e6416dfa68f3042973539b2655f5の中身を見てみます。

```
$ git cat-file -p b4c191b61e50e6416dfa68f3042973539b2655f5
create new one
```

ついでに「l_helloworld.txt」の中身を書き換えてからcommitしてみます。

```
$ cat l_helloworld.txt
Hello, world!
Add new line
$ git add .
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   l_createnewone.txt
        modified:   l_helloworld.txt
        new file:   l_helloworld2.txt
```
差分は以下の通りです。

```
.
├── .git
│   ├── objects
│   │   ├── 56
│   │   │   └── 2f17cd3ece43f0d38e93ace1048baec07beeda
```

中身を確認します。

```
$ git cat-file -p 562f17cd3ece43f0d38e93ace1048baec07beeda
Hello, world!
Add new line
```
内容が書き換わったので、新たなハッシュ値としてオブジェクトが追加されました。

## git commit
では、コミットしてみます。

```
$ git commit -m "2nd commit. add and modify"
[master 2deb1b0] 2nd commit. add and modify
 3 files changed, 3 insertions(+)
 create mode 100644 l_createnewone.txt
 create mode 100644 l_helloworld2.txt
```

オブジェクトの変更点を確認します。

```
├── .git
│   ├── objects
│   │   ├── 2d
│   │   │   └── eb1b0751cbfeffdc75683b2f61e476ef970640
│   │   ├── e6
│   │   │   └── c5d9e73c33771f1878aa6edc1a5df1939e6351
```

```
$ git cat-file -t 2deb1b0751cbfeffdc75683b2f61e476ef970640
commit
$ git cat-file -p 2deb1b0751cbfeffdc75683b2f61e476ef970640
tree e6c5d9e73c33771f1878aa6edc1a5df1939e6351
parent 17e88b45fdb1b3e8831df0c209204f290d6ca614
author Chapa <hoge@hoge.com> 1581171878 +0900
committer Chapa <hoge@hoge.com> 1581171878 +0900

2nd commit. add and modify
$ git cat-file -t e6c5d9e73c33771f1878aa6edc1a5df1939e6351
tree
$ git cat-file -p e6c5d9e73c33771f1878aa6edc1a5df1939e6351
100644 blob b4c191b61e50e6416dfa68f3042973539b2655f5    l_createnewone.txt
100644 blob 562f17cd3ece43f0d38e93ace1048baec07beeda    l_helloworld.txt
100644 blob af5626b4a114abcb82d63db7c8082c3c4756e51b    l_helloworld2.txt
```

今回のcommitで複数のblobオブジェクトが紐づいていることがわかりました。
また「parent 17e88b45fdb1b3e8831df0c209204f290d6ca614」から親となるcommitオブジェクトとの紐づけがされていることもわかります。

# 今回のおさらい
今回は、すでにcommitがされているリポジトリに対して、ファイルの追加・変更を実施したうえでインデックスへの追加、リポジトリへのcommitを実施しました。
ファイルの内容からハッシュ値が作られること、2回目のcommitオブジェクトには、親となるcommitオブジェクトのハッシュ値が記載されていることがわかりました。