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

Phi*_*ley 45 git workflow git-clone

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. 
Run Code Online (Sandbox Code Playgroud)

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

对于某些项目工作流程,我需要将最新的提交从单个分支传递给编码器,然后让它们能够push(快进)开发到主服务器.这部分是为了安全,知识产权保护和回购规模,部分是为了减少大回购会给天真编码员带来的困惑.是否有允许这样的git工作流程?


更新:根据Karl Bielefeldt的回答,git checkout --orphan应该是正确的答案.但是仍然需要将该分支单独"克隆"给新用户,并且能够有效地推送它.

手册页指出:

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

创建一个名为<new_branch>,启动 <start_point> 并切换到它的新孤立分支.在这个新分支上进行的第一次提交将没有父项,它将成为与所有其他分支和提交完全断开的新历史的根.

调整索引和工作树,就像之前运行一样git checkout <start_point>.这允许您启动一个新的历史记录,记录一组类似于<start_point>通过轻松运行git commit -a以进行根提交的路径.

当您想要从提交中发布树而不公开其完整历史记录时,这可能很有用.您可能希望这样做以发布项目的开源分支,该分支的当前树是"干净的",但其完整历史记录包含专有或其他受阻的代码.

如果要启动记录一组完全不同的路径的断开连接的历史记录<start_point>,则应通过git rm -rf .从工作树的顶层运行创建孤立分支后立即清除索引和工作树.之后,您将准备好准备新文件,重新填充工作树,从其他地方复制它们,提取tarball等.

VonC与Junio评论的链接很有意思.我认为手册应该在这种情况下提供指导,并允许正确的命令[例如clone <branch> --options]只提取回购的相关部分.显然,push通过在历史记录底部设置一些链接提交和SHA1来锁定repo匹配,可以提高成功的可能性.


更新Git 1.9.0:发布说明2014年2月14日.

"从以前被禁止的浅克隆存储库中获取,主要是因为所涉及的代码路径没有经过仔细审查,我们也没有打扰支持这种用法.这个版本试图允许以更加可控的方式从一个浅层克隆的存储库中转移对象(即接收器变成了一个截断历史的浅存储库)."

这对浅层克隆人来说是个好消息.接下来 - 可能是狭窄的克隆.

Von*_*onC 22

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

不是规则或多或少像:

如果您的浅存储库的历史记录延伸时间不够长而另一个存储库在截断的历史记录之前分叉,那么您无法计算共同的祖先并且无法推出.

更新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
Run Code Online (Sandbox Code Playgroud)

这里S是你在浅水库有提交,R是存在于接收推式资源库中的提交.
由于您的历史记录很浅,因此两个存储库都没有" X为了保持收件人存储库的历史记录完整而需要存在的提交"; 接收者开始时并不浅薄,我们不想让它变浅.

如果你前一段时间浅克隆,没有工作,而另一侧的进展与对方沟通,如果对方的进展包括:倒带和历史的重建,你会看到一个类似的拓扑结构.当您浅深地克隆深度为1时,上图中
最左边的' S'可能是分支的尖端,从那时起,远程端可能已经丢弃了最前面的三个提交,并重建了它的历史,导致最右边的' R'.
在这种情况下,推送到遥控器HEAD将失败.


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

如果我要对此说些什么......

  • 我认为"不支持"是提供足够信息的简洁方法,但它只适用于聪明人.

  • 不是每个人都聪明; 有些人自己尝试一下,看到这个操作似乎适用于他们有限数量的试验,并且可以得出结论它大部分时间都可以工作.
    他们祝贺自己的情报"大部分时间",而非"永远".
    当他们看到它不起作用时,他们会感到不安,即使他们已被警告过.


有关浅层克隆更新过程的更多信息,请参阅" 如何更新git浅层克隆? ".


Kar*_*ldt 9

是否有允许这样的git工作流程?

是的,它是作为补丁发送补丁. git format-patch是专门为此而设计的.如果你想谷歌了解更多细节,它被称为"看门人"工作流程.很难相信一个组织关注"安全和知识产权保护",因为你的组织还没有使用类似的东西,一个人或一个小组负责审查"不受信任"的变化,然后再进入真正的构建.


根据您的评论,我现在可以更好地了解您的要求.我建议你创建一个孤儿分支(参见git checkout --orphan),从你希望你的开发者开始.仅将该分支克隆到这些开发人员可访问的不同存储库,并让它们从该存储库正常克隆,推送和拉取.

然后当你需要将他们的更改重新集成到官方受保护的存储库时,只需拉动他们的分支,制作它的副本,git branch这样你就不会覆盖原来的孤儿(如果你想稍后重复这个过程),那么重新复制副本到您的原始分支点,并合并或正常的任何.历史将看起来像他们直接从您的受保护仓库工作.

它比平常更复杂,但这是额外隔离的代价.