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を追加。
[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の関係を把握。
- 適当なファイルを作成しコミット。コミット時に表示されるハッシュ値を先ほどの
git cat-file -p
コマンドの引数として指定。するとtreeのハッシュ値が表示される。 - 次に、treeのハッシュ値を引数に
git cat-file -p
コマンドで確認。blobのハッシュ値が表示される。 - 最後に、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名に篤く御礼申し上げます。