🏹

Gitコマンド入門::Gitオブジェクト(cat-file,tree)第五十一回

2021/03/18に公開

みなさんこんにちは! 前回のBLOBに続いて、今回は、Treeを学習していきますね! まあ~ Gitを学習した始めたころから、Working Tree とか、ブランチを切ったりして、その枝別れのイメージを、木に例えてTreeだとか? いたるところで、このTreeって単語が出て来ましたけど、結局のところですね。Treeそのものは、複数のオブジェクトを、まとめる為の入れ物、つまり箱みたいなものです。ただ、その箱の中に、そのまた先の箱の情報も保存できるので、それが繋がりイメージを想像させるので、全体像としては、木という表現なのでしょう。でも、繰り返して言いますが、ただのオブジェクトを複数記述してまとめる為のファイルであり、普段、私たちが利用している、ファイル管理のエクスプローラーであり、OSのファイルフォルダーシステムですね。

こちらは「第十回」で使った。木のアイコン!

前回の記事はこちらから!

https://zenn.dev/shiozumi/articles/462cb3430dfa19

git本家本元の情報はこちらから!

https://git-scm.com/book/ja/v2

今日の課題も前回同様、ここを参考にします!

https://git-scm.com/book/ja/v2/Gitの内側-Gitオブジェクト

git update-index --add --cacheinfo

それでは早速、git add コマンドと同じ動作をする、git update-index で、ステージング環境を作成してみましょう!

find .git/objects -type f ハッシュ値を確認

$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
.git/objects/7c/8de0324fd9993d95c716ef054cf6445410f7b4
.git/objects/a3/d9bcc0c12de6bf2d5fd5628cadb13307437e42
.git/objects/50/d97d23f92d7a4c52a992daa8655472551c0a44

// 前回作成したファイルは、4つでしたね。

ハッシュ値のデーターと、ファイル名は、以下のように紐づけします!

  1. README.md --> 50/d97~
  2. test_content.txt --> d6/704~
  3. version_1_0.txt --> 7c/8de~
  4. version_2_0.txt --> a3/d9bc~

ggit cat-file -p で、再確認!

git cat-file -p 50d97
ということで、ファイル名のハッシュ値は、~ 以下、中略

$ git cat-file -p d6704
test content

$ git cat-file -p 7c8de
version 1.0

$ git cat-file -p a3d9b
version 2.0

git update-index --add --cacheinfo

$ git update-index --add --cacheinfo 100644 \
50d97d23f92d7a4c52a992daa8655472551c0a44 README.md

$ git update-index --add --cacheinfo 100644 \
d670460b4b4aece5915caf5c68d12f560a9fe3e4 test_content.txt

$ git update-index --add --cacheinfo 100644 \
7c8de0324fd9993d95c716ef054cf6445410f7b4 version_1_0.txt

$ git update-index --add --cacheinfo 100644 \
a3d9bcc0c12de6bf2d5fd5628cadb13307437e42 version_2_0.txt

git write-tree で、TREEオブジェクト作成!

$ git write-tree
869487db702cd020150dc37b4370d42ac1d8efa8

$ git cat-file -t 869487db702cd020150dc37b4370d42ac1d8efa8
tree
// tree オブジェクトが出来ました!

早速、git cat-file -p で中身を確認!

git cat-file -p 869487db702cd020150dc37b4370d42ac1d8efa8

100644 blob 50d97d23f92d7a4c52a992daa8655472551c0a44    README.md
100644 blob d670460b4b4aece5915caf5c68d12f560a9fe3e4    test_content.txt
100644 blob 7c8de0324fd9993d95c716ef054cf6445410f7b4    version_1_0.txt
100644 blob a3d9bcc0c12de6bf2d5fd5628cadb13307437e42    version_2_0.txt

$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
.git/objects/7c/8de0324fd9993d95c716ef054cf6445410f7b4
.git/objects/a3/d9bcc0c12de6bf2d5fd5628cadb13307437e42
.git/objects/50/d97d23f92d7a4c52a992daa8655472551c0a44
.git/objects/86/9487db702cd020150dc37b4370d42ac1d8efa8
// そして、tree も同じように、ハッシュ値で保存されていますね!

ここまでの操作で、git add コマンドで、ステージングエリアに、4つのファイルを登録した状態と同じことが再現できましたね!

そして、私の大好きな、16進数のdump!(苦笑)

$ xxd -g 4 .git/objects/86/9487db702cd020150dc37b4370d42ac1d8efa8
0000000: 78012b29 4a4d5530 34336730 34303033  x.+)JMU043g04003
0000010: 31510872 7574f175 d5cb4d61 08b859ab  1Q.rut.u..Ma..Y.
0000020: fc53b7ca 2768e5a4 5b2b5243 8a4265b8  .S..'h..[+RC.Be.
0000030: 5ca08a4a 528b4be2 93f3f34a 52f34af4  \..JR.K....JR.J.
0000040: 4a2a4a18 ae15b871 7b7bbd79 3a31667d  J*J....q{{.y:1f}
0000050: 4cc645fd 30aef98f 9f40d596 a5161567  L.E.0....@.....g
0000060: e6e7c51b c61b8095 d6f43e30 f2bf39d3  ..........>0..9.
0000070: 76ea71b1 f7ac3edf 5c4204be 6f41536a  v.q...>.\B..oASj
0000080: 0455baf8 e69e0307 759fedd7 8dbf9ad4  .U......u.......
0000090: b376a331 bb739d13 00deec43 c1        .v.1.s.....C.

// とにかく、なんか萌えてくる。仕事している感じになる!(笑)

では、お待たせ! git commit-tree

$ echo '1st' | git commit-tree 869487db702cd020150dc37b4370d42ac1d8efa8
a165f10863e4483609e87baa337a1dc748f47742

$ git cat-file -t a165f10863e4483609e87baa337a1dc748f47742
commit 
// blob,tree,に続いて、commit オブジェクトの完成!
// 新しいハッシュ値も出来て無事コミット完了!

$ git cat-file -p a165f10863e4483609e87baa337a1dc748f47742
tree 869487db702cd020150dc37b4370d42ac1d8efa8
author Makoto Shiozumi <shiozumi@esmile-hd.com> 1616037130 +0900
committer Makoto Shiozumi <shiozumi@esmile-hd.com> 1616037130 +0900

1st

// ファイルの中身は、いつもの、git log と同じですね!
// タイムスタンプ=1616037130
// ↓
// 日時(Tokyo)=2021/03/18 12:12:10
//

さあ、いかがでしょうか? tree オブジェクトの中に、blob オブジェクトを4つ入れて、それを、git commit-tree コマンドで実行すると、無事コミットすることが出来ましたね。

そして、出来上がったコミットの中身は、tree のハッシュ値、コミットしたユーザー情報、コメント分、タイムスタンプなどが入っていますね。

タイムスタンプを日付に変換してくれる、ツールサイトあります!(笑)
https://url-c.com/tc/

git log --stat でも確認!

$ git log --stat a165f10863e4483609e87baa337a1dc748f47742
commit a165f10863e4483609e87baa337a1dc748f47742
Author: Makoto Shiozumi <shiozumi@esmile-hd.com>
Date:   Thu Mar 18 12:12:10 2021 +0900

    1st

 README.md        | 2 ++
 test_content.txt | 1 +
 version_1_0.txt  | 1 +
 version_2_0.txt  | 1 +
 4 files changed, 5 insertions(+)

--stat オプションを付けると、コミットしたファイル一覧も見れますね!

git reset --hard でファイルのチェックアウト!

とうことで、git reset --hard ハッシュ値 で、実際にファイルをローカルのリポジトリーから取り出します!

$ git reset --hard a165f10863e4483609e87baa337a1dc748f47742
HEAD is now at a165f10 1st

$ ls -a
.  ..  .git  README.md  test_content.txt  version_1_0.txt  version_2_0.txt
// はい、無事、ファイルも取り出せました!

$ git branch -avv
* master a165f10 1st
// ローカルmasterブランチも、git reset で自動に作成してますね。

// では、最後にファイルを確認して!
// 今度は、cat ですね!
$ cat README.md
ということで、ファイル名のハッシュ値は、// 以下、中略~
$ cat test_content.txt
test content
$ cat version_1_0.txt
version 1.0
$ cat version_2_0.txt
version 2.0

$ find .git/objects -type f

.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
.git/objects/7c/8de0324fd9993d95c716ef054cf6445410f7b4
.git/objects/a3/d9bcc0c12de6bf2d5fd5628cadb13307437e42
.git/objects/50/d97d23f92d7a4c52a992daa8655472551c0a44
// 上記の4つは、blob オブジェクト

.git/objects/86/9487db702cd020150dc37b4370d42ac1d8efa8
// tree オブジェクト 上記のblob4つをファイル名付きで保存
// treeの中に、tree オブジェクトの保存も勿論可能!

.git/objects/a1/65f10863e4483609e87baa337a1dc748f47742
// commit オブジェクトは、上記のtreeオブジェクトと、
// 他の情報を保存(コメント、日付、作成者情報など)

今回のまとめ

さあ~ これで、gitデータ構造、Gitオブジェクトについての理解度も深まってきましたね。ほんとうは、これを最初にやるべきでした~~~(苦笑)そして次回は、Treeの中に、Treeを入れ後にしたりなど、もう少し複雑なTreeの状態に挑戦していきますね!

それでは、今回はここまで、お疲れ様でした!

https://zenn.dev/shiozumi/articles/79cd009e307074
https://twitter.com/esmile2013

Discussion