6.3 思考:为什么不用顺序的数字来表示提交

到目前为止所进行的提交都是顺序提交,这可能会让您产生这么一个想法,为什么Git的提交不依据提交顺序对提交进行编号呢?可以把第一次提交定义为提交1,依次递增。尤其是对于拥有像Subversion等集中式版本控制系统使用经验的用户而言,更会有这样的体会和想法。

集中式版本控制系统因为只有一个集中式的版本库,所以可以很容易地实现依次递增的全局唯一的提交号,像Subversion就是如此。Git作为分布式版本控制系统,开发可以是非线性的,每个人都可以通过克隆版本库的方式工作在不同的本地版本库当中,在本地做的提交可以通过版本库之间的交互(推送和拉回操作)而互相分发,如果提交采用本地唯一的数字编号,在提交分发的时候会不可避免地造成冲突。这就要求提交的编号不能仅仅是本地局部有效,而是要“全球唯一”。Git的提交通过SHA1哈希值作为提交ID,的确做到了“全球唯一”。

Mercurial(Hg)是另外一个著名的分布式版本控制系统,它的提交ID非常有趣:同时使用了顺序的数字编号和“全球唯一”的SHA1哈希值。但实际上顺序的数字编号只是本地有效,对于克隆版本库来说没有意义,只有SHA1哈希值才是通用的编号。下面来看一个Hg的示例:


$hg log—limit 2

修改集:3009:2f1a3a7e8eb0

标签:tip

用户:Daniel Neuhuser<dasdasich@gmail.com>

日期:Wed Dec 01 23:13:31 2010+0100

摘要:"Fixed"the CombinedHTMLDiff test

修改集:3008:2fd3302ca7e5

用户:Daniel Neuhuser<dasdasich@gmail.com>

日期:Wed Dec 01 22:54:54 2010+0100

摘要:#559 Add 'html_permalink_text' confval


Hg的设计使得在本地使用版本库更为方便,但是要在Git中做类似实现却很难,这是因为Git相比Hg拥有真正的分支管理功能。在Git中会存在当前分支中看不到的其他分支的提交,如何管理提交编号十分复杂。

幸好Git提供了很多方法可以方便地访问Git库中的对象:

采用部分的SHA1哈希值。不必把40位的哈希值写全,只采用开头的部分(4位以上),只要不与现有的其他哈希值冲突即可。

使用master代表分支master中最新的提交,也可以使用全称refs/heads/master或heads/master。

使用HEAD代表版本库中最近的一次提交。

符号^可以用于指代父提交。例如:

〇HEAD^代表版本库中的上一次提交,即最近一次提交的父提交。

〇HEAD^^则代表HEAD^的父提交。

对于一个提交有多个父提交,可以在符号^后面用数字表示是第几个父提交。例如:

〇a573106^2的含义是提交a573106的多个父提交中的第二个父提交。

〇HEAD^1相当于HEAD^,含义是HEAD的多个父提交中的第一个父提交。

〇HEAD^^2的含义是HEAD^(HEAD父提交)的多个父提交中的第二个父提交。

符号~<n>也可以用于指代祖先提交。例如:

a573106~5即相当于a573106^^^^^。

提交所对应的树对象,可以用类似如下的语法访问:


a573106^{tree}


某一次提交对应的文件对象,可以用如下的语法访问:


a573106:path/to/file


暂存区中的文件对象,可以用如下的语法访问:


:path/to/file


您可以使用git rev-parse命令在本地版本库中练习一下:


$git rev-parse HEAD

e695606fc5e31b2ff9038a48a3d363f4c21a3d86

$git cat-file-p e695

tree f58da9a820e3fd9d84ab2ca2f1b467ac265038f9

parent a0c641e92b10d8bcca1ed1bf84ca80340fdefee6

author Jiang Xin<jiangxin@ossxp.com>1291022581+0800

committer Jiang Xin<jiangxin@ossxp.com>1291022581+0800

which version checked in?

$git cat-file-p e695^

tree 190d840dd3d8fa319bdec6b8112b0957be7ee769

parent 9e8a761ff9dd343a1380032884f488a2422c495a

author Jiang Xin<jiangxin@ossxp.com>1290999606+0800

committer Jiang Xin<jiangxin@ossxp.com>1290999606+0800

who does commit?

$git rev-parse e695^{tree}

f58da9a820e3fd9d84ab2ca2f1b467ac265038f9

$git rev-parse e695^^{tree}

190d840dd3d8fa319bdec6b8112b0957be7ee769


在本篇的第11.4.1小节中,还会讲解更多访问Git对象的技巧,例如使用tag和日期来访问版本库对象。