まるノート

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

【Git】今までの「.git」の状態を調べてみた。の記事について補足

今までの記事からの続き。

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

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

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

git addgit commitを実行することで「.git」内で起きたことを淡々と書きましたが、
少し書ききれなった点を補足したいと思います。


ブランチについて

ブランチの概念図

git addgit commitによって「object」フォルダ内に下記の3つのファイルが生成されることは何度も書きましたが、

  • blobオブジェクト
  • treeオブジェクト
  • commitオブジェクト

図に表すと以下のような形になります。
(かえって分かりづらかったらすみません…。自分の検証結果から判断するとこのようになるはずなのです。)

図の矢印は各オブジェクトが何のファイルを指しているか、を表しています。 例えば1回目のコミットで生成されたtree オブジェクト「401ce7dbd55d28ea49c1c2f1c1439eb7d2b92427」は 「802992c4220de19a90767f3000a79a31b98d0df7」を指す、といった感じです。

$ git cat-file -p 401ce7dbd55d28ea49c1c2f1c1439eb7d2b92427
100644 blob 802992c4220de19a90767f3000a79a31b98d0df7    test.txt


2回目以降のcommitオブジェクトが親のcommitオブジェクトを指しているため、commitの前後関係が記録され、 履歴を追うことができる、というのがGitの基本的な考え方で、
このような概念図をコミットツリーとかブランチとか呼んでいます。

よくGitの解説などでは以下のような図が登場しますが、
これは git commit によってtreeオブジェクトが次々増えてゆくことを表していたのです。

そして枝が分岐していることについてはご存知の方も多いと思いますが、 複数人で並列で作業を行う場合や、開発用・本番用で変更内容をそれぞれ分けたい場合など に作成した、別のブランチを表しているということになります。
※ブランチの作成については後日記載すると思います。


master ブランチ

これまで特に触れませんでしたが、始めのgit initによって「.git」を生成した直後に、
「(master)」という表記が追加されていることに気がつくと思います。

これは、git commit によってどのブランチに対してtreeオブジェクトを追加するか、
を表していて、標準のブランチ名を「master」と呼んでいるのです。
※2021年から標準ブランチ名は「main」変わったらしいです。


ところで、最新のコミットによって生成されたtree オブジェクトやcommitオブジェクトがどれか、 というのをGitはどのように判断しているのでしょうか。
「object」フォルダ内を全て確認して、子のcommitオブジェクトが存在しないものを見つければ判断することは一応可能です。

実は「.git」直下の「HEAD」及び「refs」内の内容から判断することができます。

まずは「HEAD」を確認すると以下のように「refs」配下が参照されています。

$ cat .git/HEAD
ref: refs/heads/master


次に「refs/heads/master」を確認すると、

$ cat .git/refs/heads/master
43a146ad20bb21818c3e7384b37400975ec1713d


この「43a146ad20bb21818c3e7384b37400975ec1713d」というのは2回目のgit commitで生成されたcommitオブジェクトになります。 つまりコミットの度に最新のcommit オブジェクトの内容に上書きするので、ここから最新のコミット情報を得ることができるわけです。

以前の記事で少し触れた「index」と合わせて、「.git」直下にある以下のファイルの役割としては、

  • 「index」:最新のgit addで生成されたblobオブジェクトやファイルのパスを指す。
    → 次のコミット対象がわかる。
  • 「HEAD」:最新のgit commitで生成されたcommitオブジェクトを指す。
    → 最新のコミット情報がわかる。

ということになります。

スナップショット

最後に、Gitで保存されるのはソースコードのスナップショットである。
ということに触れようと思います。
1回目と2回目のgit addで生成したblobオブジェクトには、 どちらにもその時の「test.txt」の内容が圧縮されて保存されていました。

要するにGitはソースコードの差分を管理しているのではなく、 ステージに追加した情報をまるごと圧縮して記録しているのです。

これがGitはソースコードをスナップショットで管理している、という意味になります。
とてもシンプルでわかりやすいです。こちらの方が、前のバージョンに戻したりある時点の情報を確認するのが用意であることは感覚的にもわかりやすいのではないでしょうか。


おわりに

冒頭に記載したリンクの記事にて、おおよそ「.git」内で起こることについて検証することができ、主な内容はそちらに記載をしたのですが、 ブランチについて少し図で整理しようと思いったことと、「HEAD」やスナップショットのことなど触れられなかった点について補足させて頂きました。

これまでの記事でGitの基礎の基礎、基本的な概念は大分触れられたのではないかと思います。 まだまだブランチの作成やリモートリポジトリの活用や基本的な操作コマンドのことなど、
試して記事にしたいことはたくさんあります、今後とも色々書いてゆきたいと思います。