目前已有两个答案(在我写这篇文章的时候,现在有更多)虽然说得没错,但并没有真正回答“为什么”的问题。当然,“为什么”这个问题确实很难回答,除了 Git 各个部分的作者之外没有人能够回答(即使 Git 的两位经常贡献者给出不同的答案又怎样呢?)。
不过,考虑到 Git 的“哲学”,一般来说,各种传输协议都是通过命名一个“参考对象”来工作的。如果他们提供了一个 SHA-1,那么它就是“该参考对象的 SHA-1”。对于没有直接访问存储库(例如命令行)的人,内置命令中没有任何一个命令允许使用 ID 引用提交。我能找到的与此最接近的“原因”是这段
git upload-archive 文档中的代码:
“安全性:为了保护已从历史记录中删除但可能尚未被修剪的对象的隐私,git-upload-archive 避免为那些不可从存储库的 refs 中到达的提交和树提供服务。但由于计算对象可达性是计算密集型的,因此 git-upload-archive 实现了一组更严格但易于检查的规则……”
然而,它继续说道:
“如果配置选项 uploadArchive.allowUnreachable 设置为 true,则会忽略这些规则,并且客户端可以使用任意 sha1 表达式。如果您不关心不可到达对象的隐私或者您的对象数据库已经可以通过非智能 HTTP 访问公开,请使用此选项。”
这非常有趣,因为git clone首先获取所有可到达的对象,然后您的本地克隆可以轻松地按 SHA-1 ID 检出提交(如果需要,创建一个指向该 ID 的本地分支名称,或者只需将您的克隆保持在“游离 HEAD”模式下)。
鉴于这两个交叉的问题,我认为目前的真正答案是“没有人关心添加它”。:) 隐私论点是合理的,但是Git并没有理由不能在克隆之后通过 ID 检出提交,就像可以使用 git clone -b… 告诉 Git 检出除 master 以外的某些分支一样。唯一的缺点是允许 -b sha1,Git 无法事先检查(在克隆过程开始之前)是否会收到 sha1。它可以检查参考名称,因为那些名称与它们的分支提示或其他 SHA-1 值一起传输,所以 git clone -b nonexistentbranch ssh://... 会快速终止并且不会创建副本:
fatal: Remote branch nonexistentbranch not found in upstream origin
fatal: The remote end hung up unexpectedly
如果
-b
允许使用ID,那么你会获得整个克隆库,然后它会告诉你:"哦,天啊,抱歉,无法检出该ID,我会让你保持在主分支上"或其他情况。(这与破损的子模块现在发生的事情差不多)。
虽然
git upload-archive
现在执行了这个“隐私”规则,但这并不总是这样(它在1.7.8.1版本中引入);许多(大部分?)git-web服务器,包括Git本身分发的服务器,允许按任意ID查看。这可能是为什么
upload-archive
之后几年添加了
allowUnreachable
(但请注意,在1.7.8之后2.0.0之前发布的Git版本没有放松规则的方法)。因此,虽然这个“安全性”想法是有效的,但在其未强制执行的时期(1.7.8.1之前)也存在过。
有许多方法可以从Git存储库中“泄漏”似乎是私有数据的信息。Git 2.11.1将推出一个新文件
Documentation/transfer-data-leaks,而Git 2.11.0添加了一些内部功能(请参见
提交722ff7f87等内容)以立即丢弃推送但未被接受的对象。这些对象最终将被垃圾收集,但在此期间它们仍然会暴露出来。
实际上,默认情况下
git clone
会创建一个本地检出与远程的
HEAD
引用相对应的分支。通常那是
master
。