为什么我不能从一个浅层克隆推出?

git clone --depth命令选项说

 --depth <depth> Create a shallow clone with a history truncated to the specified number of revisions. A shallow repository has a number of limitations (you cannot clone or fetch from it, nor push from nor into it), but is adequate if you are only interested in the recent history of a large project with a long history, and would want to send in fixes as patches. 

为什么浅层克隆有这个限制? 为什么它只是一个补丁程序工作stream?

对于某些项目工作stream程,我需要将最新的提交从单个分支传递给编码人员,然后让他们能够push他们(快进)的开发工作push送到主服务器。 这部分是为了安全性,知识产权保护和回购规模,部分是为了减less大回购会给初级编码者带来的困惑。 有没有一个git工作stream程,允许这个?


更新:根据卡尔比勒费尔德的答案git checkout --orphan应该是正确的答案。 但是仍然需要将该分支单独“克隆”给新用户,并能够有效地推送该分支。

手册页指出:

git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>] --orphan

创build一个名为<new_branch>的新的孤立分支,从<start_point>开始并切换到该分支。 在这个新的分支上做的第一次提交将没有父母,这将是一个新的历史与所有其他分支和提交完全断开的根源。

索引和工作树被调整,就像以前运行git checkout <start_point> 。 这使您可以通过轻松地运行git commit -a来启动一个新的历史logging来logging一组类似于<start_point>的path,以使根提交。

如果您想从提交中发布树而不公开其完整的历史logging,则可以使用此function。 您可能想要这样做来发布项目的开源分支,该分支的当前树是“干净”的,但是其完整历史logging包含专有代码或其他devise代码。

如果你想启动一个断开连接的历史logging,logging一组完全不同于<start_point>的path,那么你应该通过运行git rm -rf .创build孤立分支之后立即清除索引和工作树git rm -rf . 从工作树的顶层。 之后,您将准备好准备新文件,重新填充工作树,从别处复制它们,提取tarball等。

VonC与Junio评论的链接很有趣。 我认为手册应该提供这种情况下的指导,并允许正确的命令[例如clone <branch> --options ]来提取回购的相关部分。 显然, push成功的可能性是通过在历史底部提供一些链接的提交和SHA1来增加,这将locking回购匹配。


更新Git 1.9.0:发行说明14年2月14日。

“从一个曾经被禁止的浅拷贝仓库中获取数据,主要是因为所涉及的代码path没有经过仔细的审查,而且我们也没有打算支持这种使用方式,这个版本试图允许以一种更受控制的方式将对象转移出一个浅拷贝的仓库(即接收器变成一个具有截断历史的浅仓库)。“

对于浅层克隆人来说这是个好消息。 接下来 – 可能会缩小克隆。

正如Junio C. Hamano(主要的Git维护者) 所说 :

是不是规则或多或less像:

如果你的浅仓库的历史logging没有足够长的时间,而另一个仓库在你截断的历史logging之前分叉了,你不能计算共同的祖先,你不能推出。

更新2014年:请参阅“ git clone –depth 1(浅型克隆)比它更有用吗? ”:使用Git 1.9将取消该限制!

更新2015年:与Git 2.5 +,你甚至可以获取一个提交 。 请参阅“ 从远程git存储库中提取特定提交 ”


原文答案(2011年8月):

实际上,想一想,比“不能计算普通”要强很多。

历史可能是这样的:

  R---R---R / --R---R---X---X---S---S---S 

其中S是您在浅仓库中提交的提交, R是存储库中存在的提交。
因为你的历史很浅,所以两个版本库都没有“ X ”,它们是为了保持收件人信息库的历史logging而需要存在的提交; 收件人一开始就不浅,我们不想浅薄。

如果你在前段时间很浅的克隆,在另一侧进行时没有与对方进行沟通,而如果对方的进展包括历史的倒带和重build,则会看到类似的拓扑结构。
上图中最左边的' S '可能是当你用1深度克隆的时候分支的尖端,从那以后,远端可能丢弃了最上面的3个提交,并重build它的历史,导致最右边的' R ' 。
在这种情况下推送到远程的HEAD将失败。


所以它可以在某些情况下工作,但不支持:

如果我不得不说一些这个…

  • 我认为“不支持”是一种提供足够信息的简洁方式,但它只适用于聪明的人。

  • 不是每个人都很聪明。 有些人自己尝试一下,看到这个手术似乎只适用于他们有限数量的试验,并且会认为这个试验大部分时间都是有效的。
    他们祝贺自己的情报说“大部分时间”,而不是“总是”。
    即使他们已经受到警告,他们看到它不起作用,也感到不安。


有关浅克隆更新过程的更多信息,请参阅“ 如何更新git浅克隆? ”。

有没有一个git工作stream程,允许这个?

是的,这是发送修补程序作为补丁。 git format-patch是专门为了实现这个function而devise的。 这就是所谓的“看门人”工作stream程,如果你想谷歌的更多细节。 很难相信一个与“安全和知识产权保护”有关的组织,因为你们并没有使用类似的东西,一个人或一个小组负责审查“不可信”的变化,然后才把它们变成真正的构build。


根据你的评论,我现在有一个更好的想法你的要求。 我build议创build一个孤立的分支(请参阅git checkout –orphan ),无论您希望您的开发者启动哪一个点。 只将该分支克隆到可供这些开发人员访问的另一个存储库,并让他们克隆,推入,并正常从该回购。

然后,当你需要将他们的改变重新整合到官方的受保护的仓库时,只需要拉他们的分支,用git branch复制它,这样你不会覆盖原来的孤儿(如果你想稍后重复这个过程),然后rebase复制到你原来的分支点,并合并或任何正常的。 历史将看起来像他们从你的受保护的回购直接工作。

这比正常情况稍微复杂一些,但这是额外隔离所付出的代价。