まるノート

備忘録も兼ねて、様々なお役立ち情報をまとめています。

【Git】.git の仕組みや変化を調べてみた ③(git add ~ git commit をもう一度実行したらどうなるか)

はじめに

前々回の記事で、git initgit addコマンドを実行し「.git」で何が起こるかを確認しました。
結果としてはblobオブジェクトの生成と「index」ファイルの更新が行われます。

【Git】.git の仕組みや変化を調べてみた ①(git init から git add まで実行) - まるノート


次に以下の記事ではgit commitコマンドにより、
「objects」配下にtreeオブジェクトとcommitオブジェクトが生成されることを確認しました。

【Git】.git の仕組みや変化を調べてみた ②(git commit を実行) - まるノート

今回、これらの内容について更に掘り下げてふれて見たいと思います。


git add をもう一度実行

blobオブジェクト

ステージに追加した時に起きていることを更に詳しく知るため、まずは「test.txt」を更新し、
その後再度git addしてみます。

// ファイルに追加を行う。
$ echo 'HogeHoge' >> test.txt
$ cat test.txt
Hello world
HogeHoge

// 再度ステージに追加する。
$ git add test.txt


すると今後は「19」というフォルダが出来ています。

「19」フォルダの中は以下の通り。

git cat-file -pコマンドを実行すると、、、

$ git cat-file -p 19c282a236721a3177460394a8180ad15dc4a7f8
Hello world
HogeHoge


追記した内容「hogehoge」と前回から記述済みの「Hello world」が両方とも保存されています。

git addによって生成されるのはblobオブジェクトと呼ばれるものでした。

つまり「test.txt」の最新状態は、都度blobオブジェクトとして追加されてゆくということになります


index

今度は「.git」直下の「index」を確認します。

$ git ls-files --stage
100644 19c282a236721a3177460394a8180ad15dc4a7f8 0       test.txt


こちらは今回生成されたblobオブジェクトのハッシュ値に更新されています。
ちなみに前回git addした時の「index」の内容は以下でした。

$ git ls-files --stage
100644 802992c4220de19a90767f3000a79a31b98d0df7 0       test.txt


以上、git addによって下記の内容を改めて確認することが出来ました。

  • 「test.txt」の最新状態のblobオブジェクトが都度追加される。
  • 「index」は更新される。


git commit をもう一度実行

続けてgit commitを行うとどうなるのか、試してみます。

$ git commit -m "second commit"
[master 43a146a] second commit
 1 file changed, 1 insertion(+)


1度目のコミットと同じように「objects」フォルダ配下にtreeオブジェクトとcommitオブジェクトが追加されました。

追加された「43」配下

追加された「b1」配下


tree オブジェクト

まずは「b1」フォルダの内容をgit cat-file -pコマンドで確認してみます。

$ git cat-file -p b107719f52b0c5bf4c3ea3c17093b6aba2fd6775
100644 blob 19c282a236721a3177460394a8180ad15dc4a7f8    test.txt


2度目のgit addコマンドで追加されたblobオブジェクトの内容「19c282a236721a3177460394a8180ad15dc4a7f8」が記載されています。
これはtreeオブジェクトと呼ばれるものでした。


commit オブジェクト

今度は「43」フォルダの内容をgit cat-file -pコマンドで確認してみます。

$ git cat-file -p 43a146ad20bb21818c3e7384b37400975ec1713d
tree b107719f52b0c5bf4c3ea3c17093b6aba2fd6775
parent d6e1f7eb272690a4e0f0eaa1de2fd92c6f11c1e7
author Hogetaro <Hogetaro@yahoo.co.jp> 1654081683 +0900
committer Hogetaro <Hogetaro@yahoo.co.jp> 1654081683 +0900

second commit


「tree b107719f52b0c5bf4c3ea3c17093b6aba2fd6775」は今回のコミットで追加されたtreeオブジェクトを指していて、
「parent d6e1f7eb272690a4e0f0eaa1de2fd92c6f11c1e7」前回のコミットで追加されたcommitオブジェクトを指しています。

ちなみに1度目のcommitオブジェクトは以下の通りです。

$ git cat-file -p d6e1f7eb272690a4e0f0eaa1de2fd92c6f11c1e7
tree 401ce7dbd55d28ea49c1c2f1c1439eb7d2b92427
author Hogetaro <Hogetaro@yahoo.co.jp> 1653910407 +0900
committer Hogetaro <Hogetaro@yahoo.co.jp> 1653910407 +0900

first commit


上記を踏まえると、

  • treeオブジェクトはgit addで追加された最新のblobオブジェクトを指している。
  • commitオブジェクトはgit commitで追加された最新のtreeオブジェクトと、親のcommitオブジェクトを指している。 ことがわかります。


まとめ

長くなりましたが、今までの内容をまとめます。

git add を実行すると起こること
  • blobオブジェクトが「objects」フォルダ内に生成される。
  • 追加・更新したファイルのパスなどの情報は「index」に上書きされる。


git commit を実行すると起こること
  • tree オブジェクトが生成される。
    (最新のgit addで生成されたblobオブジェクトを指す)
  • commitオブジェクトが生成される。
    (最新のtreeオブジェクトと、親のcommitオブジェクトを指す)

上記はコミットを行う度に生成され、各commitオブジェクトには全て親のcommitオブジェクト(前回のコミット実行時の参照)が含まれるため、コミットツリーのような概念を形成することが出来ます。


以上、少しずつコミットツリーなどの概念が具体的にイメージできるようになってきたのではないでしょうか。

内容は結構複雑なので、記事の内容に間違いがあるようでしたらご指摘頂きたいです。
最後までご覧頂きありがとうございました。