【问题标题】:Why Isn't There A Git Clone Specific Commit Option?为什么没有特定于 Git 克隆的提交选项?
【发布时间】:2014-11-25 22:20:09
【问题描述】:

鉴于recent question on SO,我想知道为什么git clone 中没有一个选项,这样新创建的分支的HEAD 指针将指向指定的提交?在上面所说的问题中,OP 正在尝试提供有关他的用户应该克隆的特定提交的说明。

请注意,这个问题与How To Clone To A Particular Version 使用reset 无关;但是关于为什么不存在

【问题讨论】:

    标签: git git-clone


    【解决方案1】:

    到目前为止,有两个答案(在我写这篇文章的时候,现在还有更多)他们所说的都是正确的,但并没有真正回答“为什么”的问题。当然,“为什么”这个问题真的很难回答,除了 Git 的各个部分的作者(即便如此,如果两个 Git 频繁的贡献者给出了两个不同的答案怎么办?)。

    尽管如此,考虑到 Git 的“哲学”,一般来说,各种传输协议都是通过命名 reference 来工作的。如果他们提供 SHA-1,则它是该引用的 SHA-1。对于尚未直接(例如,命令行)访问存储库的人,没有1 的内置命令允许通过 ID 引用提交。我能找到的最接近原因的事情——实际上是一个很好的理由2——是the git upload-archive documentation中的这一点:

    安全

    为了保护已删除对象的隐私 历史但可能尚未被修剪,git-upload-archive 避免 为无法从 存储库的参考。然而,因为计算对象可达性是 计算成本高, git-upload-archive 实现了更严格但 更易于检查的规则集 ...

    但是,它继续说:

    如果配置选项uploadArchive.allowUnreachable 为真,则这些 规则被忽略,客户端可以使用任意 sha1 表达式。这 如果您不关心无法访问的对象的隐私,这很有用, 或者,如果您的对象数据库已经可以通过以下方式公开访问 非智能http。

    这特别有趣,因为git clone 首先获取所有可访问的对象,之后您的本地克隆可以通过 SHA-1 ID 轻松检查提交(如果需要,可以创建一个指向该 ID 的本地分支名称,或者只是让你的克隆处于“分离 HEAD”模式)。

    鉴于这两个交叉流,我认为“为什么”的真正答案,在这一点上,是“没有人足够关心添加它”。 :-) 隐私参数是有效的,但没有理由git clone 在克隆后无法通过 ID 签出提交,就像可以告诉它签出 master3 与git clone -b ...。允许 -b <em>sha1</em> 的唯一缺点是 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,我会把你留在 master 上”管他呢。 (这或多或少是现在与破坏的子模块发生的情况。)


    1虽然git upload-archive 现在 强制执行此“隐私”规则,但情况并非总是如此(它是在版本 1.7.8.1 中引入的);许多(大多数?) git-web 服务器,包括与 Git 本身一起分发的服务器,允许通过任意 ID 进行查看。这可能就是为什么 allowUnreachable 在添加“仅按引用名称”代码几年后添加到 upload-archive 的原因(但请注意,1.7.8 和 2.0.0 之前的 Git 版本无法放松规则)。因此,虽然“安全”的想法是有效的,但有一段时间(1.7.8.1 之前)它没有被强制执行。

    2有多种方法可以将表面上的私有数据“泄露”出 Git 存储库。一个新文件Documentation/transfer-data-leaks 即将出现在 Git 2.11.1 中,而 Git 2.11.0 添加了一些内部功能(请参阅commit 722ff7f87 等)以立即删除已推送但未接受的对象。这样的对象最终会被垃圾回收,但这会使它们在持续时间内暴露出来。

    3实际上,默认情况下,git clone 会在本地签出它认为与远程的 HEAD 引用相关的分支。不过,通常那是master

    【讨论】:

    • github.com/git/git/blob/… 是合适的链接吗?
    • allowUnreachable 业务似乎相当新(Git 2.0+):github.com/git/git/commit/…
    • 并且(在该链接中嵌入的链接之后)在 1.7.8.1 中引入了对任意 SHA-1 的限制。
    • 所以... 2011-12-21:三年前。
    • @VonC:脚注 1 已编辑以包含版本,并调整有关日期的措辞。 (我仍然认为 git 1.6 之后的一切都是“新事物”,我记得在某些公司系统上被 1.5.x 卡住了......)
    【解决方案2】:

    正如其他答案所说,这通常不是什么大问题,但他们没有说明为什么您不能克隆特定的提交。答案是安全。

    如果你不小心推送了机密信息,然后强制推送了一个固定的历史,带有机密信息的提交仍然会存储在服务器上,直到服务器的 Git 的垃圾收集器发现不再需要它。如果哈希是已知的(例如它可能在日志中可用),恶意用户可能会请求不应该推送的特定提交,即使您能够验证当您强制推送固定历史时,没有人已经获取了这些提交。

    确保您只能从 ref 进行克隆,确保只有“可访问”的提交才会发送给客户端。

    【讨论】:

    • 什么可以阻止恶意用户推送指向该提交 ID 的新分支? (客户端可以愉快地创建一个指向服务器已经拥有的提交的新分支,而无需推送任何其他提交。)然后恶意用户可以克隆并获取机密提交。
    • @EdwardThomson 大概是恶意用户没有推送访问权限,但公平点。
    • 我认为这个想法是克隆操作将过滤掉那些不应该访问的提交?如果是这样,为什么不能通过向服务器发送所需的提交来在服务器上执行此操作,而不是浪费带宽和宝贵的时间(以及磁盘空间)?我目前正在绝望地看着一个 linux 内核克隆的进度指示器,我知道我想要的提交已经过去了......
    • 安全性在 git 的设计中并不是一个重点(否则他们会用来自 SHA2 家族的散列替换 SHA1)。 IE。安全性不能是主要原因(如果存在两个等效的设计替代方案,则可能是辅助原因,但具有和不具有哈希下载不是其他等效替代方案)。
    【解决方案3】:

    克隆 repo 是与 checkout 不同的操作。您不会“克隆特定的提交”。为方便起见,您可以克隆然后同时签出特定的预先存在的分支,因为这是大多数人想要的。如果这不能满足您的需求(您想要的特定 SHA 没有分支),只需使用或别名某种形式的

    git clone -n <some repo> && cd <some repo> && git checkout SHA
    

    【讨论】:

      【解决方案4】:

      如果您的特定提交被分支引用,您可以这样做:

      git clone -b yourBranch /url/of/the/repo
      

      克隆的 repo 将直接位于该分支引用的提交处。

      【讨论】:

      • 对。就我而言,我们要使用的 submodulesmaster 中的特定(较旧)提交相关联。
      • 你可以随时从旧的提交中创建一个分支 - git branch clone_me OLD_SHA
      • 别处建议的另一个解决方案是分叉,然后创建一个指向您想要的 SHA 的标签,然后使用 git 子模块来跟踪标记的 SHA。
      • @CMCDragonkai 我同意。我怀疑这是一种简单的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2022-09-29
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 2014-07-28
      • 2015-05-24
      • 2022-01-13
      • 1970-01-01
      相关资源
      最近更新 更多