使用 git cat-file 与 Git 进行一点友好互动
这篇文章是PONOS Advent Calendar 2022的第13天的文章。
昨天,@iixd_pog讨论了Unity界面的管理应该使用Scene还是Prefab。
首先
在这篇文章中,我将介绍git cat-file命令。此外,我还希望能够解释一下Git对象是什么,同时也兼顾使用方法的解释。
就我个人而言,通过尝试这个命令,我感觉对Git的理解更加深入了。如果能对大家与Git相处更加融洽提供一点帮助,我会非常开心。
动作确认使用的存储库
這是我在寫文章時使用的示範性存儲庫。
若能够克隆这个,我认为你可以直接试用其中包括的哈希值等等。
什么是git cat-file?
获取-git-文件
这是Git的一个子命令。
它用于显示Git对象的类型和内容。
基本用法
git cat-file <type> <object>
可以指定要显示的Git对象类型和对象ID来使用。
但是,由于后面要讲到的 -p 选项太方便了,所以可能不经常使用。
方便的选择
有很多选项可供选择,但我认为最常用的是-p。
如果加上-p选项,它会执行所谓的“Pretty-print”,也就是进行美观打印的操作。
git cat-file -p <object>
自动识别所指定对象的类型,并以易读的方式呈现。
无需指定,这样更直观。
今后的文章中,我们将专注使用这个选项。
Git对象的类型
Git是一种非常方便的版本控制系统,但它的内部是由Git对象构成的。
而且,Git对象大致可以分为四种类型。
参考:Git的内部 – Git对象
-
- コミットオブジェクト
-
- ツリーオブジェクト
-
- ブロブオブジェクト(データオブジェクト)
- タグオブジェクト
让我们实际尝试一下每个命令有什么用途和包含什么信息。
提交对象
提交对象是一个存储提交信息的对象,正如其名称所示。
通过使用`cat-file`命令查看文件内容,结果如下所示。
$ git cat-file -p a00d
tree 21eeb2e86fbafc30830ecf25dc242d5c5ceaa954
parent 069dec119f2b6c4398b25149cedaa0efa84755fb
author honeniq <honeniq@gmail.com> 1670912169 +0900
committer honeniq <honeniq@gmail.com> 1670912169 +0900
Add fuga
然后,当使用git-show或git-log显示提交时。
$ git log -n 1 a00d
commit a00d1945c41dde9675dda8cfe22380e276a8f04c
Author: honeniq <honeniq@gmail.com>
Date: Tue Dec 13 15:16:09 2022 +0900
Add fuga
尽管书写格式有一些细微的差异,但基本上会出现相同的信息。
从commit对象的内容来看,可以说它就是commit本身。
不同之处在于,通过cat-file显示的地方可能会包含tree和parent的信息。
tree指的是此提交所引用的树对象,parent指的是前一个提交对象(父提交)。
对象树
接下来让我们来看一下树对象的内容。
以下是某个树形对象的内容。
$ git cat-file -p bdf3
100644 blob 5a58749fdda4388f0bf1040383e7e480ec6be8f5 hoge.txt
040000 tree 1695cfed85647375865ac1f9394c94a1707272a5 lib
# アクセス権 種類 ハッシュ値 ファイル名
树对象中包含了该树中所包含对象的信息。这类似于文件系统中的目录和树、文件和Blob之间的对应关系。
在树中可能还有更多的子树,如果这样一直重复下去,就会形成复杂的树结构。
# リポジトリルートのツリーオブジェクト
$ git cat-file -p bdf3
100644 blob 5a58749fdda4388f0bf1040383e7e480ec6be8f5 hoge.txt
040000 tree 1695cfed85647375865ac1f9394c94a1707272a5 lib
# lib/ のツリーオブジェクト
$ git cat-file -p 1695
100644 blob 9128c3eb56a3547e2cca631042366bf0f37abe67 fuga.txt
100644 blob 0ef7e93778bbdf711c34afb388a40bf3c74e34c9 piyo.txt
看目录文件的状态是这样的。
$ tree -L 2
.
├── hoge.txt
└── lib
├── fuga.txt
└── piyo.txt
可以看出,与树对象记录的信息相一致。
数据对象
接下来是数据对象。
从刚才的树对象中……
# lib/ のツリーオブジェクト
$ git cat-file -p 1695
100644 blob 9128c3eb56a3547e2cca631042366bf0f37abe67 fuga.txt
100644 blob 0ef7e93778bbdf711c34afb388a40bf3c74e34c9 piyo.txt
让我们来检查一下 fuga.txt 的 blob 对象。
$ git cat-file -p 9128
fuga
$ cat lib/fuga.txt
fuga
中的信息显示出来了。和用cat命令看到的信息一致。
似乎Blob对象中含有文件的实际内容。
此外,Blob对象除了内容以外没有任何其他信息,因此属性信息,如文件名,似乎是从Tree对象中获取的。
此外,文件的创建日期和所有者信息既不在Tree中也不在Blob中,所以Git似乎没有管理它们。
标签对象
最后是标签对象。
实际上,Git的标签有两种不同的类型,根据创建标签时是否有注释而有所不同。
不带评注(轻量标签)
如果没有评论,标签只是指向特定提交对象的引用。
$ cat .git/refs/tags/v1.0-light
3685f753ac86b6500e240b796b48fdf643fc354c
$ git cat-file -p 3685
tree bdf3d7065da23ab84acc446c1415aca5a0667129
parent 78a2d49ba8c32b9ed674e6d93cffaa3c0a2c6135
author honeniq <honeniq@gmail.com> 1670914612 +0900
committer honeniq <honeniq@gmail.com> 1670914612 +0900
# タグが指しているのは特定のコミット
$ git log -n 1
commit 3685f753ac86b6500e240b796b48fdf643fc354c (HEAD -> main, tag: v1.0-light, tag: v1.0, origin/main)
Author: honeniq <honeniq@gmail.com>
Date: Tue Dec 13 15:56:52 2022 +0900
Fix hoge
留言已收到
如果添加了注释并创建了标签,将会生成标签对象。
$ cat .git/refs/tags/v1.0
ea6446acfb62c0d0e6f68d6b60f3169c710cafff
$ git cat-file -p ea64
object 3685f753ac86b6500e240b796b48fdf643fc354c
type commit
tag v1.0
tagger honeniq <honeniq@gmail.com> 1670925496 +0900
tag v1.0
如果没有备注,标签直接指向3685…的提交对象,但这次指向的是标签对象。总之,标签对象中也指向着3685…,同时还可以存储备注等信息。
仔细看,还包含了类型的信息呢。
实际上,标签也可以附加在除了提交之外的其他对象上。
$ git tag -a super-important-file -m 'super important file hoge.txt!!' 5a58
$ cat .git/refs/tags/super-important-file
92f5585cb92aab5f30507b829f83f2f84b6d286b
$ git cat-file -p 92f5
object 5a58749fdda4388f0bf1040383e7e480ec6be8f5
type blob
tag super-important-file
tagger honeniq <honeniq@gmail.com> 1670926708 +0900
super important file hoge.txt!!
可以为所有Git对象添加标签。例如,在Git源代码仓库中,维护者可以将自己的GPG公钥添加为blob对象,并为该对象添加标签。
参考:《深入Git – Git引用》
我不知道。这对我来说很有益呢。
总结
我对Git重新感到惊叹,它通过组合许多简单的组件来运行。我觉得自己比以前稍微懂了一点,将来还会继续方便地使用它。
明天是@ackyla先生。