庖丁解牛

前面的这些东东我在第一篇里也大概的讲过一些,但是今天我们想不但要开动这辆叫“Git”的跑车,还想看看它里面有些什么样的零件,是怎么构成的。

OK,我们来看看“test_proj”项目里的“Git目录”的结构:

$cd test_proj/.git

$ ls | more

branches/ # 新版的Git已经不再使用这个目录,所以大家看到它 #一般会是空的

COMMIT_EDITMSG # 保存着上一次提交时的注释信息

config # 项目的配置信息

description # 项目的描述信息

HEAD # 项目当前在哪个分支的信息

hooks/ # 默认的“hooks” 脚本文件

index # 索引文件,git add 后把要添加的项暂存到这里

info/ # 里面有一个exclude文件,指定本项目要忽略的文件 #,看一下这里

logs/ # 各个refs的历史信息

objects/ # 这个目录非常重要,里面存储都是Git的数据对象

# 包括:提交(commits), 树对象(trees),二进制对象 #(blobs),标签对象(tags)。

#不明白没有关系,后面会讲的。

refs/ # 标识着你的每个分支指向哪个提交(commit)。

我先用git log命令来看一下这个Git项目里有哪些提交:

$ git log

commit 58b53cfe12a9625865159b6fcf2738b2f6774844

Author: liuhui998

Date: Sat Feb 19 18:10:08 2011 +0800

project init

大家可以看到目前只有一个提交(commit)对象,而它的名字就是:”58b53cfe12a9625865159b6fcf2738b2f6774844”。这个名字就是对象内容的一个SHA签名串值,只要对象里面的内容不同,那么我们就可以认为对象的名字不会相同,反之也成立。我在使用时一般不用把这个40个字符输全,只要把前面的5~8个字符输完就可以(前提是和其它的对象名不冲突)。为了方便表示,在不影响表达的情况下,我会只写SHA串值的前6个字符。

我们可以用git cat-file来看一下这个提交里的内容是什么:

$ git cat-file -p 58b53c

tree 2bb9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13

author liuhui998 1298110208 +0800

committer liuhui998 1298110208 +0800

project init

大家可以看到:提交“58b53c” 是引用一个名为“2bb9f0”的树对象(tree)。一个树对象(tree)可以引用一个或多个二进制对象(blob), 每个二进制对象都对应一个文件。 更进一步, 树对象也可以引用其他的树对象,从而构成一个目录层次结构。我们再看一下这个树对象(tree)里面有什么东东:

$ git cat-file -p 2bb9f0

100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme.txt

不难看出,2bb9f0”这个树对象(tree)包括了了一个二进制对象(blob),对应于我们在前面创建的那个叫 ”readme.txt”的文件。现在我们来看看这个”blob”里的数据是不是和前面的提交的内容一致:

$ git cat-file -p 2d832d

hello,world

哈哈,熟悉的“hello,world”又回来了。

想不想看看提交对象、树对象和二进制对象是怎么在”Git目录“中存储的;没有问题,执行下面的命令,看看”.git/objects”目录里的内容:

$ find .git/objects

.git/objects

.git/objects/2b

.git/objects/2b/b9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13

.git/objects/2d

.git/objects/2d/832d9044c698081e59c322d5a2a459da546469

.git/objects/58

.git/objects/58/b53cfe12a9625865159b6fcf2738b2f6774844

.git/objects/info

.git/objects/pack

如果大家仔细看上面命令执行结果中的粗体字,所有的对象都使用SHA签名串值作为索引存储在”.git/objects”目录之下;SHA串的前两个字符作为目录名,后面的38个字符作为文件名。

这些文件的内容其实是压缩的数据外加一个标注类型和长度的头。类型可以是提交对象(commit)、二进制对象(blob)、 树对象(tree)或者标签对象(tag)。


相关内容