为什么我不能从浅层克隆中推出? [英] Why can't I push from a shallow clone?

查看:130
本文介绍了为什么我不能从浅层克隆中推出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

git clone --depth 命令选项说明

   - 深度<深度> 
创建一个历史截断为指定修订版数的浅表副本。
浅层存储库有许多限制
(不能从中克隆或获取,也不能从中推入)
,但如果您只关注最近的历史一个历史悠久的大型项目,
,并希望发送修补程序作为补丁。

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



对于某些项目工作流程,我需要将最新的提交从单个分支传递给编码员,然后让他们能够将他们(快进)的开发推送到主服务器。部分原因在于安全性,知识产权保护和回购规模,部分原因是为了减少大回购会给初级编码者带来的困惑。是否有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 来进行根提交。



当您想从提交
发布树时,这会很有用而不会暴露其完整的历史。您可能想要这样做
发布一个项目的开源分支,其当前树是
clean,但其完整历史记录包含专有或其他
编码的代码位。 p>

如果您想开始一个断开连接的历史记录,记录一组完全不同于< start_point> ,然后
,您应该通过运行 git rm -rf。创建
orphan分支后清除索引和工作树>从
工作树的顶层。之后,您将准备好准备新文件,
重新填充工作树,从其他地方复制它们,
提取tarball等。


VonC与Junio评论的链接非常有趣。我认为手册应该提供这种情况下的指导,并允许正确的命令[例如克隆<分支> --options ]来提取回购的相关部分。显然, push 成功的概率通过在历史记录的底部提供一些链接的提交和SHA1来增加,这将锁定回购匹配。






更新Git 1.9.0:发布注释14年2月14日。



一个曾经被禁止使用的浅拷贝存储库,
主要是因为涉及的代码路径没有仔细审查
,而且我们也没有打算支持这种使用方式,该版本尝试
允许将对象转移出在
更受控制的方式(即接收者变成一个浅储藏库
,截断历史记录)。



这很好消息为浅层克隆人。
下一个 - 可能会缩小克隆。

解决方案

正如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




其中 S 是您在浅仓库中的提交,并且 R 是存储库中存在的提交接受你的推送。

因为你的历史很浅,所以这两个存储库都没有' X ',它们是为了保留历史而需要存在的提交的收件人信息库完整;收件人一开始并不浅,而且我们也不想让它变浅。



如果您前段时间浅显地克隆过,没有与对方沟通,另一方进展,如果对方的进展包括倒带< / strong>,则重建历史,你会看到一个类似的拓扑结构。

上图中最左边的' S '可能是分支的尖端你很深地克隆了深度为1的数据,从那以后,远端可能丢弃了最上面的三个提交,并重建了它的历史记录,导致最右边的' R '。 b $ b在这种情况下,推送到远程的 HEAD 将失败。






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



如果我不得不在这方面说些什么......



  • 我认为不被支持是一种提供足够信息的简洁方式,但它只适用于智能人群。


  • 并非每个人都是聪明的;有些人会自己尝试一下,看看操作似乎适用于他们有限数量的试验,并且会得出结论大部分时间都可以使用。

    他们祝贺他们自己大部分时间的情报,而不是永远。

    当他们发现它不起作用时,即使他们已被警告,他们也会感到不安。








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


The git clone --depth command option says

--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. 

Why do shallow clones have this limitation? Why is it a patches only workflow?

For some project workflows I need to pass just the latest commit from a single branch to a coder, and then have them be able to push their (fast forward) developments to the main server. This partly for security, IP protection and repo size, and partly to reduce the confusion that a big repo would bring to a naive coder. Is there a git workflow that allows this?


Update: Based on Karl Bielefeldt's answer the git checkout --orphan should be the right answer. But one still needs to 'clone' that branch alone to the new user, and be able to push it effectively.

The man page states:

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

Create a new orphan branch, named <new_branch>, started from <start_point> and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.

The index and the working tree are adjusted as if you had previously run git checkout <start_point>. This allows you to start a new history that records a set of paths similar to <start_point> by easily running git commit -a to make the root commit.

This can be useful when you want to publish the tree from a commit without exposing its full history. You might want to do this to publish an open source branch of a project whose current tree is "clean", but whose full history contains proprietary or otherwise encumbered bits of code.

If you want to start a disconnected history that records a set of paths that is totally different from the one of <start_point>, then you should clear the index and the working tree right after creating the orphan branch by running git rm -rf . from the top level of the working tree. Afterwards you will be ready to prepare your new files, repopulating the working tree, by copying them from elsewhere, extracting a tarball, etc.

VonC's link to Junio's comments is interesting. I think the manual should provide the guidance in this case, and allow the right command [e.g. clone <branch> --options] to extract just the relevant part of the repo. Obviously the probability of push success is increased by having a few linked commits and SHA1s at the bottom of the history that will lock down the repo matching.


Update Git 1.9.0 : release notes 14 Feb '14.

"Fetching from a shallowly-cloned repository used to be forbidden, primarily because the codepaths involved were not carefully vetted and we did not bother supporting such usage. This release attempts to allow object transfer out of a shallowly-cloned repository in a more controlled way (i.e. the receiver becomes a shallow repository with a truncated history)."

This is good news for the shallow cloners. Next - Narrow clones possibly.

解决方案

As Junio C. Hamano (main Git maintainer) puts it:

Isn't the rule more or less like:

If your shallow repository's history does not extend long enough and the other repository forked before your truncated history, wyou cannot compute the common ancestor and you cannot push out.

Update 2014: see "Is git clone --depth 1 (shallow clone) more useful than it makes out?": that limitation will be lifted with Git 1.9!

Update 2015: with Git 2.5+, you will even be able to fetch a single commit. See "Pull a specific commit from a remote git repository"


Original answer (August 2011):

Actually, come to think of it, it is a lot stronger than "cannot compute the common".

The history may look like this:

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

where S are the commits you have in your shallow repository, and R are the commits that exist in the repository that receives your push.
Because your history is shallow, neither repository has 'X' that are the commits that need to exist in order to keep the history of recipient repository complete; the recipient is not shallow to begin with, and we do not want to make it shallow.

If you cloned shallowly some time ago, worked without communicating with the other side while the other side progressed, AND if the other side's progress included a rewind & rebuild of the history, you would see a similar topology.
The leftmost 'S' in the above picture might have been the tip of the branch when you shallowly cloned with depth 1, and since then the remote end may have discarded topmost three commits and have rebuilt its history that leads to the rightmost 'R'.
In such a case pushing to the remote's HEAD will fail.


So it could work in some case, but it is not supported:

If I have to say something on this...

  • I think "is not supported" is a succinct way to give good enough information, but it would only work for intelligent people.

  • Not everybody is intelligent; some try it out themselves, see that the operation seems to work for their limited number of trials, and would conclude it would work most of the time.
    And they congratulate their own intelligence for saying "most of the time", not "always".
    And they get upset when they see it does not work, even though they have been warned.


For more on the shallow clone update process, see "How to update a git shallow clone?".

这篇关于为什么我不能从浅层克隆中推出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆