接下来的内容是以“之一~之十”的内容为基础的,内容将围绕对象数据库和索引文件展开,这是为了更好的理解git的工作机制和体系结构。
系列之十一将讲解“对象数据库(object database)”
1
为了讲清楚object database这个概念,我们先建立一个git仓库:
$ mkdir test-project
$ cd test-project
$ git init
$ echo ‘Hi,rocrocket’>file.txt
$ git add .
$ git commit -a -m “initial commit” //此处的-m选项表示“后面的参数是本次提交的历史记录”
$ echo ‘Hi,rocrocket!’>file.txt
$ git commit -a -m “add emphasis”
$ git log //使用log命令查看一下
Created commit d85012f: add emphasis 1 files changed, 1 insertions(+), 1 deletions(-) [rocrocket@wupengchong test-project]$ git log commit d85012f4d17a774c7286f4d7d022f022d3b90073 Author: rocrocket <wupengchong@gmail.com> Date: Fri Sep 26 10:58:15 2008 +0800
add emphasis
commit 241e0a4d2a5644f92737b7fba8b9eb19dcb0c345 Author: rocrocket <wupengchong@gmail.com> Date: Fri Sep 26 10:57:13 2008 +0800
initial commit
你可曾想过到底这些跟在commit字符串后面的一大长串(共40位)十六进制数字是干什么用的??
通过前十期的学习,我们知道这40位十六进制数是用来“标识一次commit”的名称。其实,这40位十六进制数是一个SHA1哈希数(Secure Hash Algorithm),它可以保证每次commit生成的名称都是唯一的且可以永远有效的。
2
执行下面命令:
[rocrocket@wupengchong test-project]$ git cat-file -t 241e //cat-file命令中-t选项表示列出相应ID的对象类型;241e是刚才commit后得出的SHA1码 commit //可以看到此ID对应的对象类型为一次commit [rocrocket@wupengchong test-project]$ git cat-file commit 241e //此处的commit表示要查询的是一个对象类型为commit的对象,后面给出此对象的ID
tree 9a327d5e3aa818b98ddaa7b5b369f5deb47dc9f6 author rocrocket <wupengchong@gmail.com> 1222397833 +0800 committer rocrocket <wupengchong@gmail.com> 1222397833 +0800
initial commit
你应该可以注意到命令输出结果中包含了tree,tree的ID表示了一个BLOB对象(二进制对象),此对象对应着一个文件或另一个tree。你可以使用ls-tree命令来查询关于这个tree的更详细信息:
[rocrocket@wupengchong test-project]$ git ls-tree 9a327
100644 blob 7d4e0fa616551318405e8309817bcfecb7224cff file.txt
我们可以看到9a327这棵树上包括了一个file.txt文件,其ID为7d4e0f
[rocrocket@wupengchong test-project]$ git cat-file -t 7d4e0f blob [rocrocket@wupengchong test-project]$ git cat-file blob 7d4e0f Hi,rocrocket
可以看到7d4e0f对应的对象的类型是blob,而其内容就是“Hi,rocrocket”
3
所有的对象信息都存储在.git/objects/目录下,使用find命令查看一下:
./objects ./objects/pack ./objects/24 ./objects/24/1e0a4d2a5644f92737b7fba8b9eb19dcb0c345 ./objects/fb ./objects/fb/4ec0f35525992eda56021f161f85f637837404 ./objects/d8 ./objects/d8/5012f4d17a774c7286f4d7d022f022d3b90073 ./objects/7d ./objects/7d/4e0fa616551318405e8309817bcfecb7224cff ./objects/9a ./objects/9a/327d5e3aa818b98ddaa7b5b369f5deb47dc9f6 ./objects/info ./objects/60 ./objects/60/be00dabc677b196938758ef41457cc17b77b70
这些对象都是被压缩过的,其类型可以是blob,tree,commit或tag。其中包括了对象长度、对象类型和对象的内容。
4
在.git目录下的HEAD文件比较特殊,查看.git/HEAD文件:
[rocrocket@wupengchong .git]$ cat HEAD ref: refs/heads/master [rocrocket@wupengchong .git]$ cd .. [rocrocket@wupengchong test-project]$ git branch * master
可以看到HEAD文件指示出当前所在的分支名称是master。其实更引起我们兴趣的是HEAD文件中所指示的这个路径“refs/heads/master”,我们随着HEAD的思路走下去:
[rocrocket@wupengchong test-project]$ cat .git/refs/heads/master d85012f4d17a774c7286f4d7d022f022d3b90073
这个文件的内容给出了一个对象ID,继续寻根溯源:
[rocrocket@wupengchong test-project]$ git cat-file -t d850 commit [rocrocket@wupengchong test-project]$ git cat-file commit d850 tree fb4ec0f35525992eda56021f161f85f637837404 parent 241e0a4d2a5644f92737b7fba8b9eb19dcb0c345 author rocrocket <wupengchong@gmail.com> 1222397895 +0800 committer rocrocket <wupengchong@gmail.com> 1222397895 +0800
add emphasis
谜底揭开了。HEAD所指向的原来是最后一次commit的信息,而且经测试可知parent指的是上一次commit的信息。
5
到目前为止,我们应该已经知道了对象数据库是如何管理历史记录的了:
- commit对象会指向一个tree对象,即在历史记录中当前结点的tree目录的镜像;也会指向父母(parent)commit,这是为了和之前的commit建立关联。
- tree对象用于显示一个目录的状态,tree对象中包含了blob对象和子目录对象。
- blob对象包含的是文件的数据。
- 每个分支的HEAD会存储在.git/refs/heads中。同时,当前所在分支的头部会存储在.git/HEAD中。
转载请注明:Git中国 » 【看日记学Git】之十一