まるノート

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

【Git】git add ~ git commit を再度実行し「.git」の状態を調べてみた。

はじめに

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

【Git】git init ~ git add を実行し「.git」の状態を調べてみた。 - まるノート

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

【Git】git commit を実行し「.git」の状態を調べてみた。 - まるノート

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


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


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

つまり、git add を実行する度に、「test.txt」の最新状態が「objects」に追加されることになります。


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度目のコミットと同じように、treeオブジェクトとcommitオブジェクトが追加されたと考えられます。
「objects」フォルダ配下は以下の通りになりました。

追加された「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 を実行する度に起こること

最新のgit addで生成されたblobオブジェクトを指すtree オブジェクトが生成される。
同じくgit commitを実行することで、git commitで追加された最新のtreeオブジェクトと、親のcommitオブジェクトを指すcommitオブジェクトが生成される。

つまり、commitオブジェクトは、どのtreeオブジェクトが最新か、また一つ前のtreeオブジェクトは何か、といった順番を記録する役割があり、 treeオブジェクトは最新のblobオブジェクトを指すことで、ステージに追加・更新されたファイルの最新状態がどれか、を記録する役割があるということになります。

ステージに追加する、ということは具体的には、追加・更新したファイルのblobオブジェクトを生成すること。
コミットするということは、treeオブジェクトを生成し、treeオブジェクト及び親commitオブジェクトを指すcomiitオブジェクトと合わせて、コミットツリーのような概念を形成するということを表しています。

うまく伝わりましたでしょうか。 今までの検証によって、
具体的に「.git」」内で起こっていたことを知ることで、なんとか自分はコミットツリーの概念図などを見てモヤモヤしていた気持ちは解消されたかなあと思っています。