正如我在评论中所说,这里的问题归结为线性化。如果您想要一个简单的递增计数来指定某个特定的提交,那么您必须有一个单一的源点来生成这个简单的递增计数。
在SVN中,有一个明显的地方可以做到这一点:所有提交都存储在主中央服务器上。为了进行新的提交,您需要调用中央服务器并说:进行新的提交。这要么成功并获得一个简单的递增数字,要么失败并且没有提交。
在Git中,没有指定的中央服务器。每个开发人员都会进行自己的提交。提交是在同行之间交换的。任何给定提交的全局唯一标识符都是其哈希值:Git保证没有两个提交具有相同的哈希值。1
缺乏单一的中央计数点会破坏自己制作简单修订计数的有用性,因为不同的存储库可以并且将具有相同数量的提交,而不包含相同的提交集。我可能有17个提交,其中2个与您的17个提交不同,因此如果我们合并我们的两个存储库,我们都会得到19个提交。(如果我将您的存储库与我的存储库合并,我将获得19个提交-从您那里获得的两个新提交以及我们已经共享的15个提交-而您仍然有17个提交:您必须仍然获取我拥有但您缺少的两个提交。)
但是,您可以使用您的想法:只需指定一个中央计数点:
“一种解决方案是维护一个翻译表,列出每个提交哈希并将其映射到修订号,但这使生活变得更加困难。”
如果您已经拥有一个中央服务器,那么这并不是那么困难。例如,如果任何发布构建都在“发布构建”系统上完成,并且发布构建系统具有Git存储库,则只需指定其存储库为中央计数点即可。
它维护着这个表格。计数可以是其存储库中提交的数量。2但这已经超出了我们的需求:计数可以简单地是表格中条目的数量;没有必要计算非构建版本。无论如何,从“计数”到“哈希”,或者反之亦然,都是通过查找或添加适当的条目到表格中来完成的。
这种简化计数的价值最多是可疑的。看看真正的软件发布,通常会标记一个“点版本”:Git版本2.8.4、Git版本2.9.0、Git版本2.10.1;Python 2.7.12、Python 3.4.5等等。7.3.12与7.4.0相比如何?它严格地“小于”,还是不是?使用Git构建发布时,可以使用这样的点版本进行标记。标签可以使用Git内置机制进行分发,每个人都可以在本地查找v7.3.12
并找到提交。如果您没有标签,则可能没有该版本:您必须从拥有标签的人那里使用git fetch
,可能还要使用--tags
。
标签实际上是这个中央映射表的分布式版本。但我们不是计算标签,而是直接使用它们的名称,这些名称的形式为vX
或vX.Y
或其他形式。
这些标签可以通过
git describe进行扩展,它允许您说“距离此固定标记有这么多次提交,加上一个唯一的验证器/定位器,以防分布式构建使相对计数失效。”请参见
Sébastien Dawans的答案。
1这个"保证"是通过一个简单的机制来保持的:如果两个提交具有相同的哈希值,Git就简单地拒绝相信第二个提交存在。它不会接受它,不会将其存储到存储库中,并且现有的哈希值“获胜”。对于任何给定的一对对象,这种情况发生的概率都非常小:2-N,其中N是哈希中的位数。由于Git使用SHA-1,它是160位,因此为2-160。
由于所谓的生日悖论或生日问题,随着对象数量的增加,概率迅速上升。然而,我们从一个如此小的基础开始,以至于在机会甚至达到未被检测到的存储介质损坏的机会水平之前,我们可以拥有数万亿个对象,也许多达1.7千万亿个左右。(这里使用“短刻度”名称;请参见https://en.wikipedia.org/wiki/Quadrillion)。
2如果您使用此方法(计算其存储库中提交的数量),则必须确保您从不删除任何提交,否则计数将下降,因此不会像升序函数一样运行。这是表条目计数可能更好的原因之一;或者您可以使用一个永远不会重置的单独计数器,在选择下一个数字时进行原子获取和递增。