show 与 git 对象

git 对象

Git 主要有四种对象:tag 对象,Commit 对象, tree 对象以及 blob 对象。

可以通过 git cat-file -p 获取某个对象的具体内容


对象存储

对象存储

Git 在生成每个对象时,都会同时保存一个头信息。以 blob 对象为例,其头信息格式为:

blob #{content.length}\0

然后将头信息与文件内容进行连接,使用 sha1 算法,生成文件 sha-1 值。最后将连接后的内容通过 zlib 压缩并写入到 sha-1 值指定的文件中。

这样一个完整的对象存储并完成。

对于 tree 与 commit 对象来说,与 blob 类似,只是将头信息中的 blob 换成 tree 或 commit。

由于头信息中带有对象的标识,所以很容易判断出当前 sha-1 值对应的文件是哪种类型的对象。


commit 对象

该对象会包含一个指向暂存快照的指针,还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象。如:

$ git cat-file -p c5c9b731fcb7e0969af26c19c90ba1b52aa06887
tree 0a89f850cf3fa163f458cc592d5a692a282402b2
parent ff17ef396f2b7d81c6ee74a6aa6f3950a990dca7
author global  1519653379 +0800
committer global  1519653379 +0800

c2

其中的 tree 指的是内容快照的指针,parent 指向的是父结点。author 与 commiter 分别为作者和提交者。最后的 "c2" 是提交时的信息。


blob 对象

Git 中每一个文件都是一个 blob 对象。

注意:一个 blob 对象只包含文件的内容,不包含文件名。而文件名的保存就需要 tree 对象。


tree 对象

Git 会将每一个文件夹转成 tree 对象

  1. 提交时,Git 会为整个项目建一个 tree 对象,Commit 对象中的 tree 属性就是指向该 tree 对象

  2. tree 对象中不但包含了文件名,还包括了该文件的模式。如 100644表明这是一个普通文件;100755 表示一个可执行文件;120000 表示一个符号链接。

  3. 一个 tree 对象包含了一条或多条树对象记录(tree entry),每条记录含有一个指向 blob 对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息。

    比如某个文件夹下有两个文件与一个子文件夹(假设该文件夹下只有一个文件),那么父文件夹对象的 tree 对象中将包含两个 blob 对象以及一个 tree 对象,该 tree 对象中只包含一个 blob 对象。

$ git show 9828073f61ecec6e4f3806d9c99a10a482da41e3
tree 9828073f61ecec6e4f3806d9c99a10a482da41e3

a.txt
ee
test/

$ git cat-file -p 8bdb01d84c5ad6456acb4d8df8d82a0db5214972
100644 blob ee1a8365ec2baa3e5a97cb6e44d8d8b5c553fb30    a.txt
100644 blob 3019cb577dc13af92ae57eb63f275018593c1aa5    test.html

通过 git show 获取指定的 tree 对象的信息。其返回结果说明当前 tree 对象下有两个文件以及一个文件夹(文件夹后加 / 用于与文件区分)。

通过 cat-file 命令列出另一个 tree 对象下的各个文件信息。


操作

我们可以用分支名,HEAD,标签等都是指代 commit 对象。

  1. 使用 ~n 形式指向当前结点的第 n 代祖先。如:HEAD~1 表示 HEAD 结点的父结点;HEAD~3 表示 HEAD 的曾祖(父结点的结点的父结点)结点。

  2. 使用 ^{tree} 指向当前结点对应的 tree 对象。如 tra~3^{tree} 表示获取 tra 的曾祖结点指向的 tree 对象。

    $ git show tra~3^{tree}
    tree tra~3^{tree}
    
    a.txt
    test.html
    

    列出了指定 tree 对象中的文件结构。


tag 对象

建立一个带附注的标签,Git 会创建一个 tag 对象。它包含一个标签创建者信息、一个日期、一段注释信息,以及一个指针。

tag 对象的内容非常类似于 commit 对象。主要的区别在于,tag 对象通常指向一个提交对象,而不是一个 tree 对象

当创建一个不带附注的普通标签时,Git 不会创建一个 tag 对象,只会将该标签指向一个固定的 commit 对象。

$ cat .git/refs/tags/t1
6fdae52278c5294f4b9a81350f1486c72ab0245f
$ git cat-file -t 6fdae52278c5294f4b9a81350f1486c72ab0245f
commit

$ cat .git/refs/tags/taaa 
505e33243a8e5d0d8de1d474f0ff51510f6f2904
$ git cat-file -t 505e33243a8e5d0d8de1d474f0ff51510f6f2904
tag
$ git cat-file -p 505e33243a8e5d0d8de1d474f0ff51510f6f2904
object 2bd8fdaa5cd67cb98460fd39d13b14ecdaf154ea
type commit
tag taaa
tagger global  1520867341 +0800

tag msg

上述命令中,第一个获取的是一个普通标签,其指向的对象类型为 commit,其指向一个 commit 对象。

第二个标签是一个带附注的标签,其指向的是一个 tag 对象。tag 对象中包含 object 指针,其指向的是一个 commit 对象。执行 git cat-file -t taaa 命令时,输出的是 “tag",表明该标签指向的是一个 tag 对象。


show

用于查看各种对象的内容。如 commit 对象,blob 对象,tree 对象,tag 对象等。

文件内容

show 命令可以查看 某个版本的某个文件的内容

  1. 指定版本时,会显示指定版本的指定文件的内容。

    $ git show HEAD~:a.txt  > ~/Desktop/a.txt
    

    上述命令会将 HEAD~ 版本中的 a.txt 文件导出到桌面上的 a.txt 中。

  2. 如果未指定版本时,表示导出暂存区中的指定文件。

    $ git show :0:b.txt
    

    表示查看暂存区中 b.txt 的内容,其前面的 0 表示 b.txt 所处的状态。

    如果因为合并时发生冲突导致暂存区中有多个 b.txt 文件,在使用 show 获取时需要修改文件所处的状态。1 表示合并的两个分支的共同的最近的祖先结点中的 b.txt 的内容;2 表示当前分支;3 表示被合并的分支。

    其实,上述两个写法只是获取对应 blob 对象的 sha1 值的简写形式。其实质依旧是 show blob

你可能感兴趣的:(show 与 git 对象)