Gitのオブジェクトについてのメモ

  • 11
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Git天空闘技場でGitのオブジェクトについて学びました。忘備録のためのメモ。

Gitのオブジェクトとは?種類は?

Gitはプロジェクトの状態をオブジェクトと呼ばれる形で記録する。オブジェクトはblob、tree、commit、tagの4種類。それぞれzlibで圧縮されSHA-1でハッシュ値が生成される。

  • blobはファイルに対応
  • treeはディレクトリに対応
  • commitは変更履歴に対応
  • tagはタグに対応

オブジェクトの確認方法は?

オブジェクトは次のコマンドで確認できる。

git cat-file -p object

-pオプションは「pretty-print object's content」。見やすく表示される。このコマンドはたくさん打つので、適宜~/.gitconfigにaliasを追加。

~/.gitconfig
[alias]
        cf = cat-file -p

オブジェクトの作られ方の確認

その1 git initして.gitの中を確認

git initコマンドでカレントディレクトリ内に.gitディレクトリができるが、この時点ではオブジェクトが入る.git/objectsや、ブランチが入る.git/refs/heads、タグが入る.git/refs/tagsは空っぽ。

その2 commitのハッシュ値からオブジェクトを辿る

下記手順でcommit => tree => blobの関係を把握。

  1. 適当なファイルを作成しコミット。コミット時に表示されるハッシュ値を先ほどのgit cat-file -pコマンドの引数として指定。するとtreeのハッシュ値が表示される。
  2. 次に、treeのハッシュ値を引数にgit cat-file -pコマンドで確認。blobのハッシュ値が表示される。
  3. 最後に、blobのハッシュ値を引数としてgit cat-file -pコマンド。1でコミットしたファイルの中身が表示される。

その3 .git/objectsディレクトリの変化

コミットをした時点で.git/objectsディレクトリの中身が変わる。オブジェクトのハッシュ値の最初の2桁のディレクトリが作成され、その中に上記で確認したcommit、tree、blobのハッシュ値があることが確認できる。

parentとは?

上記のリポジトリから適当なブランチを切り、そのブランチに移動して、作成していたファイルの中身を変更しコミット。commitのハッシュ値を確認すると、parentという項目があり、そのハッシュ値をgit cat-file -pコマンドで確認すると、直前のコミットであることがわかる。parentでコミットの繋がりが把握できる。

Gitのオブジェクトの観点から、mergeとは?

元のブランチに戻り、先ほど適当に切ったブランチをgit merge --ff-noでマージする。そして、マージしたcommitのハッシュ値をgit cat-file -pで確認。parentが2つあることが確認できる。mergeとはcommitオブジェクトにparentを2つ持たせることであるとわかる。

Gitのオブジェクトの観点から、rebaseとは?

Git天空闘技場ではrebaseの解説はなかったため、自分で確認。rebaseをしたコミットのハッシュ値をgit cat-file -pで確認すると、parentは1つのみ。もちろん、git logでログを表示しても、まとめられたコミットは表示されない。しかし、.git/objectsディレクトリには、rebaseでまとめられてしまったオブジェクトのハッシュ値が残っている。そのため、git reflogコマンドでrebaseでまとめる前のコミットを確認できる。

まとめ

Gitのオブジェクトが何たるかを踏まえた上でGitを見直すと、それぞれのコマンドが実際に何をしているか、内部の処理の詳細はわからないまでも、少なくとも想像はできるようになると思います。Gitのオブジェクトについて学習する場を設けてくださったGit天空闘技場の主催者3名に篤く御礼申し上げます。