Gitオブジェクト是什么东西?
相对于svn,git确实在同一远程存储库下比较时更快。
由于我对git还了解不多,我决定现在去了解一下,然后我发现git是用快照来管理的。因为不需要像svn一样逐步累积差异,所以我认为git很快。
如果考虑到快照的保存,为什么Git仓库不会变得庞大呢?我也产生了这个疑问,但我明白这是通过Git对象的结构来巧妙处理的,所以为了整理自己的思路,我写了这篇文章。
Git对象的类型
-
- 4種類のオブジェクトが存在する
- SHA-1ハッシュによる識別
Blob对象
-
- ファイルに相当するオブジェクトで、ファイルの中身がzlibで圧縮されている。ファイル名は管理外。
-
- ファイルの中身にblob <ファイルサイズ>\0をつけたSHA-1ハッシュ値。
-
- つまり、 ファイルの中身が同じであれば、同じオブジェクトとなる。
git addしたときに生成する
我會試一試
- 以下4ファイルの構成で試してみます
│ readme.txt ファイルの中身:hogehoge
│ sample.txt ファイルの中身:this is sample
├─subA
│ aaa.txt ファイルの中身:Hello aaa
└─subB
bbb.txt ファイルの中身:hogehoge
git add .で4ファイルをaddした結果、.git/objectsは以下となりました
.git/objects/48/f685c5179595c9edbcfb5ebcc1beafac716857
.git/objects/64/e3d0eb4f3c190bf547221f28a364c49b9df77e
.git/objects/6f/27b4832a80eaa3123c0d1c256c41cd1835b33d
-
- ここで4ファイルのハッシュ値を計算してみます。
-
- blob <ファイルサイズ>\0 <ファイルの中身>をsha-1計算します
blobオブジェクトのハッシュと一致していることが確認できます
ファイルが異なっていても、中身が同じであればblobオブジェクトは共通なことが確認できます
$ (echo -en 'blob 8\0';cat readme.txt) | shasum
48f685c5179595c9edbcfb5ebcc1beafac716857 *-
$ (echo -en 'blob 14\0';cat sample.txt) | shasum
64e3d0eb4f3c190bf547221f28a364c49b9df77e *-
$ (echo -en 'blob 9\0';cat subA/aaa.txt) | shasum
6f27b4832a80eaa3123c0d1c256c41cd1835b33d *-
$ (echo -en 'blob 8\0';cat subB/bbb.txt) | shasum
48f685c5179595c9edbcfb5ebcc1beafac716857 *-
-
- 次にこのblobオブジェクトを確認します。git cat-file <オプション> <gitオブジェクト>
- -pオプションを使うと、中身が見れました。
$ git cat-file -p 48f68
hogehoge
$ git cat-file -p 64e3d
this is sample
$ git cat-file -p 6f27b
Hello aaa
树对象和提交对象
-
- treeオブジェクト
git commitしたときに生成される
ディレクトリに相当
ディレクトリごとに生成される
commitオブジェクト
git commitしたときに生成される
親のcommitを参照している
作成者や日付、コミットメッセージが格納されている
尝试一下
git commit -m “test commit”した結果、.git/objectsは4つ増えていました
.git/objects/06/4bee06635089f2c96c653c71c24e01fe78bbf7
.git/objects/27/7f73e22786e4adfab6ec27ca1aa1baf9187e8d
.git/objects/80/dcb15ab2823857535ee6123204c0aa167ce938
.git/objects/f5/abca5b5cc24cf60e3d72ac4efeb7cb723bcf7a
- このうち3つめはcommitオブジェクトで、残りがtreeオブジェクトのようです
$ git cat-file -t 064be
tree
$ git cat-file -t 277f7
tree
$ git cat-file -t 80dcb
commit
$ git cat-file -t f5abc
tree
-
- treeオブジェクトの中身を見てみます
- treeオブジェクトが、ディレクトリごとに生成されていることが分かります
$ git cat-file -p 064be
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 readme.txt
100644 blob 64e3d0eb4f3c190bf547221f28a364c49b9df77e sample.txt
040000 tree 277f73e22786e4adfab6ec27ca1aa1baf9187e8d subA
040000 tree f5abca5b5cc24cf60e3d72ac4efeb7cb723bcf7a subB
$ git cat-file -p 277f7
100644 blob 6f27b4832a80eaa3123c0d1c256c41cd1835b33d aaa.txt
$ git cat-file -p f5abc
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 bbb.txt
-
- commitオブジェクトの中身を見ます
ルートのtreeオブジェクトの存在が確認できます
コミットしたユーザー、タイムスタンプやコミットメッセージが確認できます
$ git cat-file -p 80dcb
tree 064bee06635089f2c96c653c71c24e01fe78bbf7
author hoge <hoge@hoge.com> 1660563865 +0900
committer hoge <hoge@hoge.com> 1660563865 +0900
test commit

我会再试一次
echo -n “hogehoge” > sample.txtでsample.txtの中身を、readme.txtと合わせました
中身が同じなので、blobオブジェクトは作られないはず。実際にはこんなユースケースないと思いますが
echo -n “abcdefg” > abc.txtで新しいファイルを作ります
git add .しましたが、予想通りGitオブジェクトは1つしか増えていません
変更のないファイルはオブジェクトが作られないため、リポジトリ容量の肥大化を防いでいます
.git/objects/06/4bee06635089f2c96c653c71c24e01fe78bbf7
.git/objects/27/7f73e22786e4adfab6ec27ca1aa1baf9187e8d
.git/objects/48/f685c5179595c9edbcfb5ebcc1beafac716857
.git/objects/64/e3d0eb4f3c190bf547221f28a364c49b9df77e
.git/objects/6f/27b4832a80eaa3123c0d1c256c41cd1835b33d
.git/objects/80/dcb15ab2823857535ee6123204c0aa167ce938
.git/objects/dd/a6eb4b7b86af8aea969498003937b7c8aa46be これが増えました
.git/objects/f5/abca5b5cc24cf60e3d72ac4efeb7cb723bcf7a
- 増えたGitオブジェクトを確認します
$ git cat-file -t dda6e
blob
$ git cat-file -p dda6e
abcdefg
git commit -m “2nd commit”したら、2つ増えました
.git/objects/06/4bee06635089f2c96c653c71c24e01fe78bbf7
.git/objects/27/7f73e22786e4adfab6ec27ca1aa1baf9187e8d
.git/objects/48/f685c5179595c9edbcfb5ebcc1beafac716857
.git/objects/64/e3d0eb4f3c190bf547221f28a364c49b9df77e
.git/objects/6f/27b4832a80eaa3123c0d1c256c41cd1835b33d
.git/objects/72/d0fc47ed60e0f2abdfef26c9d48c2a0b56e3b0 これが増えた
.git/objects/80/dcb15ab2823857535ee6123204c0aa167ce938
.git/objects/a0/4d10c2f7ebd3490d126d88e5979b0c4913b865 これも増えた
.git/objects/dd/a6eb4b7b86af8aea969498003937b7c8aa46be
.git/objects/f5/abca5b5cc24cf60e3d72ac4efeb7cb723bcf7a
-
- 増えたGitオブジェクトを確認します
commitしたので、増えた1つは当然commitオブジェクトです
もう1つはルートディレクトリにファイルが増えたので、treeオブジェクトです
$ git cat-file -t 72d0f
commit
$ git cat-file -p 72d0f
tree a04d10c2f7ebd3490d126d88e5979b0c4913b865
parent 80dcb15ab2823857535ee6123204c0aa167ce938
author hoge <hoge@hoge.com> 1660572580 +0900
committer hoge <hoge@hoge.com> 1660572580 +0900
2nd commit
$ git cat-file -t a04d1
tree
$ git cat-file -p a04d1
100644 blob dda6eb4b7b86af8aea969498003937b7c8aa46be abc.txt
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 readme.txt
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 sample.txt
040000 tree 277f73e22786e4adfab6ec27ca1aa1baf9187e8d subA
040000 tree f5abca5b5cc24cf60e3d72ac4efeb7cb723bcf7a subB

$ git cat-file -p HEAD
tree a04d10c2f7ebd3490d126d88e5979b0c4913b865
parent 80dcb15ab2823857535ee6123204c0aa167ce938
author hoge <hoge@hoge.com> 1660572580 +0900
committer hoge <hoge@hoge.com> 1660572580 +0900
2nd commit
$ git cat-file -p HEAD~
tree 064bee06635089f2c96c653c71c24e01fe78bbf7
author hoge <hoge@hoge.com> 1660563865 +0900
committer korena hoge <hoge@hoge.com> 1660563865 +0900
test commit
$ git cat-file -p HEAD^{tree}
100644 blob dda6eb4b7b86af8aea969498003937b7c8aa46be abc.txt
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 readme.txt
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 sample.txt
040000 tree 277f73e22786e4adfab6ec27ca1aa1baf9187e8d subA
040000 tree f5abca5b5cc24cf60e3d72ac4efeb7cb723bcf7a subB
$ git ls-tree -r HEAD
100644 blob dda6eb4b7b86af8aea969498003937b7c8aa46be abc.txt
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 readme.txt
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 sample.txt
100644 blob 6f27b4832a80eaa3123c0d1c256c41cd1835b33d subA/aaa.txt
100644 blob 48f685c5179595c9edbcfb5ebcc1beafac716857 subB/bbb.txt
总结
我想,会不会变成这种感觉呢?如果有错误,请指正一下。
-
- Gitはスナップショットで管理しているため、チェンジセット管理のsvnよりも速い
-
- 変更がないファイルのblobオブジェクトは作られないため、リポジトリ容量の肥大化を防いでいる
- blobファイルは、zlibで圧縮されているので、ここでも容量削減に貢献している