Open gh-liu opened 5 months ago
git的四种对象:文件对象(blob)、树对象(tree)、提交对象(commit)、标签对象(tag),本质上是一个文件,其文件名是一个哈希字符串。
# 生成哈希
git hash-object 文件路径
# 使用 -w 参数时,会将对象写入git对象数据库
git hash-object -w 文件路径
# 打印git对象中的内容
git cat-file -p 哈希
# 打印git对象的类型
git cat-file -t 哈希
用git代码仓库示例:
git clone https://github.com/git/git.git
cd git
通过 git log 查询到git的第一个 commit
的哈希是 e83c5163316f89bfbde7d9ab23ca2e25604af290
git cat-file -t e83c5163316f89bfbde7d9ab23ca2e25604af290
# 输出
commit
git cat-file -p e83c5163316f89bfbde7d9ab23ca2e25604af290
# 输出
tree 2b5bfdf7798569e0b59b16eb9602d5fa572d6038
author Linus Torvalds <torvalds@ppc970.osdl.org> 1112911993 -0700
committer Linus Torvalds <torvalds@ppc970.osdl.org> 1112911993 -0700
Initial revision of "git", the information manager from hell
从 commit 的内容中,可以看到指向的 tree
对象,哈希为2b5bfdf7798569e0b59b16eb9602d5fa572d6038
,和一些额外信息
git cat-file -t 2b5bfdf7798569e0b59b16eb9602d5fa572d6038
# 输出:
tree
git cat-file -p 2b5bfdf7798569e0b59b16eb9602d5fa572d6038
# 输出:
100644 blob a6bba79ba1f46a1bbf7773449c3bd2bb9bf48e8b Makefile
100644 blob 27577f76849c09d3405397244eb3d8ae1d11b0f3 README
100644 blob 98a32a9ad39883c6d05a000a68511d4b1ee2b3c7 cache.h
100644 blob 74a0a234dd346fff51c773aa57d82fc4b83a8557 cat-file.c
100644 blob 840307af0cfaab31555795ce7175d5e9c9f981a0 commit-tree.c
100644 blob 25dc13fe101b219f74007f3194b787dd99e863da init-db.c
100644 blob c924a6e0fc4c36bad6f23cb87ee59518c771f936 read-cache.c
100644 blob 1b47742d8cbc0d98903777758b7b519980e7499e read-tree.c
100644 blob b8522886a15db861508fb6d03d4d88d6de912a4b show-diff.c
100644 blob 5085a5cb53ee52e1886ff6d46c609bdb2fc6d6cd update-cache.c
100644 blob 921f981353229db0c56103a52609d35aff16f41b write-tree.c
可以看到 tree 对象内容为一系列的文件,包含文件权限、对象类型(blob文件类型、tree树类型)、文件对象哈希、文件名
git cat-file -t a6bba79ba1f46a1bbf7773449c3bd2bb9bf48e8b
# 输出:
blob
git cat-file -p 2b5bfdf7798569e0b59b16eb9602d5fa572d6038
# 输出:
CFLAGS=-g
CC=gcc
......省略文件中间内容
backup: clean
cd .. ; tar czvf dircache.tar.gz dir-cache
文件对象的内容,就是进行版本控制的文件的内容
还没有提到标签对象,以标签v1.0.0
为例:
git rev-parse v1.0.0
# 获取到哈希为:
# f665776185ad074b236c00751d666da7d1977dbe
git cat-file -t f665776185ad074b236c00751d666da7d1977dbe
# 输出:
tag
git cat-file -p f665776185ad074b236c00751d666da7d1977dbe
# 输出:
object c2f3bf071ee90b01f2d629921bb04c4f798f02fa
type commit
tag v1.0.0
tagger Junio C Hamano <junkio@cox.net> 1135152060 -0800
GIT 1.0.0
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQBDqOh7wMbZpPMRm5oRAg+OAJ90pNi/fq5rguVou1PSxx95PYCVeACfbnZM
nN/PlwOWKA3rW8EPmWO4BzE=
=TCRg
-----END PGP SIGNATURE-----
可以看到tag对象的内容为:指向的对象的哈希与类型、tag名、创建tag的人、还有签名
假设你有一个文件夹
projectName
,希望对这个文件夹进行版本管理,你可能想到的办法:projectName_Version2
然后,你会发现,不同版本之间的文件夹,比如
projectName_Version2
和projectName_Version3
之间的差异可能只有少数几个文件,而剩余的文件是相同的,所以你会希望:然后,你希望在每次复制文件夹的时候,添加一些额外信息,比如:为什么复制?复制的时间?谁复制的?
最后,你希望标记某个重要的复制节点,比如
projectName_Version12
。在上面的场景中,已经出现了
git
的四种对象:文件对象(blob)、树对象(tree)、提交对象(commit)、标签对象(tag)blob对象就是文件,tree对象就是文件夹,commit对象指向一棵树同时携带一些额外信息,tag对象指向一个commit对象同时携带一些额外信息。