如何将缺失的分支添加到克隆的存储库的克隆中?

时间:2017-07-11 11:42:22

标签: git git-clone

git clone和git clone --mirror完全不同:

标准git clone可用作工作空间。 原产地已知的一组分支可供检查和处理。

镜像更像是备份。您不能将其直接用作工作区。

现在假设您克隆已经克隆的存储库 根据这个问题:Git cloning a repository that is already a clone

生成的存储库(clone2)只包含已在第一个克隆(clone1)中使用的分支。但是,clone1仍然知道原点的分支。有没有办法将clone1已知的分支添加到clone2而不将(原始)原点设置为远程?

如果不清楚,我们有:

repo1:

  • BRANCH1
  • BRANCH2
  • 店3
  • branch4

clone1 = git clone repo1.git:

  • branch1 - 签出
  • branch2 - 之前签出
  • branch3 - 未签出但可以随时
  • branch4 - 未检出但可以随时

clone2 = git clone clone1.git:

  • branch1 - 签出
  • branch2 - 未检出但可以随时

clone2似乎不知道branch3或branch4,因此无法检查它们。 我们如何从clone1获取该信息?

实际上这里有两个问题:

  • 我们如何获取有关从clone1到clone2的一个分支的信息?
  • 我们如何获取有关从clone1到clone2的所有可能分支的信息?

我相信,当repo1离线时,branch3和branch4可用于clone1。

有几个用例:

  • repo1不可用,我们希望重新创建它 (如果您知道从clone1重新创建repo1的方法,则可获得奖励积分)
  • repo1暂时无法使用,我们希望在不同的分支机构工作 从已经克隆了repo1的人那里获取信息。
  • 测试一些涉及repo hacking的更改,然后再将它们推送到共享仓库(repo1)。

我认为它应该没有区别,但我使用本地文件而不是URL来测试它。所以clone2实际上是通过git clone /local/path/.git

制作的

更新

我最初没有注意到并且报告的并发症: git branch -r 在clone2上应该按照答案中的建议将clone1上的分支列为 origin / branch3 origin / branch4 。但是,对于这个特殊的回购,它没有。我不知道为什么。

这个回购可能有些特别之处包括:

  • 使用.git / refs / replace

用git pull origin'refs / replace / *:refs / replace / *'拉取替换件没有区别。

还有其他建议吗?

我已经确定了git branch -r工作的repos和它不能工作的repos之间的重要区别。

clone1和clone2都应该使用(/path/to/clone1/.git/packed-refs)等行列出.git / packed-refs中的遥控器:

2c3c761fbac82556c2178cb28a4e728360093e67 refs/remotes/origin/branch1

由于某些原因,受影响的存储库上的clone2没有.git / packed-refs中的所有条目。

我检查了一些提交ID,其中packed-ref文件(在clone2中)引用了克隆存储库packed-ref(clone2),但有些则没有。 我们似乎既失去了又获得了分支!

如果我通过实验方式将packed-ref文件从clone1复制到clone2,则分支显示在

git branch -r
下,可以检出它们但会导致头状态分离。

这是'受影响'回购的git配置。

>cat .git/config
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = /path/to/clone1/.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "develop"]
    remote = origin
    merge = refs/heads/develop

用于抓取所有远程跟踪分支的[https://git.wiki.kernel.org/index.php|standard指令]即使对于损坏的回购也是如此:

git clone --mirror original-repo.git /path/cloned-directory/.git          
cd /path/cloned-directory
git config --bool core.bare false
git checkout anybranch

所以即使是破损的回购也有几种解决方法。

4 个答案:

答案 0 :(得分:1)

在我看来,您正在查看具有--mirror和没有{克隆号}的克隆的非常不同的典型用例,并让您认为它们根本不同。实际上,它们只是一般情况下常用的特殊情况。

这主要是暂时的,但我认为如果你研究git概念,着眼于真正理解上述陈述,那么其余部分也可能更清楚。

所以:在clone1中,"知识"其他分支的形式是远程分支引用(refs/remotes/origin/branch3,...)。签出的分支还有" local" branch refs(refs/heads/branch1,...)。克隆中使用的默认refspec(无论是镜像还是其他)都设置为fetch refs/heads/*。 (不同之处在于mirror将其本地映射为refs/heads/*,而#34;常规"克隆默认将它们映射到refs/remotes/origin/*。)

您可以在clone2中设置refspec - 通过设置,或在特定fetchpull的参数中 - 从{{读取refs/remotes/origin/*引用1}}。但是有一些问题要考虑。

首先,如果你要从clone1映射本地和远程引用,那么你需要在clone1中为它们提供不同的命名空间。也就是说,clone2中的refs/heads/masterclone1中的refs/remotes/origin/master不同,并且它们可能在任何给定时间引用不同的提交;所以他们不能两个映射到clone1中的相同名称。

其次,clone2的知识 - 例如 - clone2,在这一点上是间接的。 "我最后一次与branch3交谈,它告诉我上次与clone1通话时,repo1处于提交branch3。"从马的口中获取XYZ"的知识可能更有意义。您可以在branch3上添加repo1作为第二个遥控器。

是否通过添加clone2作为来源,或使用非默认的refspec来复制来自repo1的信息,最终在clone1中您将拥有该信息。多个远程引用对应于某些分支名称(例如clone2refs/remotes/origin/branch3)。这意味着可能并不总是清楚哪个分支应该被视为"上游"当地的refs/remotes/repo1/branch3。您可以通过配置和/或通过特定refs/heads/branch3push命令的参数来管理它,告诉他们您打算在该实例中将其作为上游。

将所有内容翻译成特定命令实际上取决于您要完成的任务;有太多的可能性将它们列出来并解释当你使用它们中的任何一个时。如果您需要这种详细程度,我建议fetchgit configgit fetchgit push的文档可以作为开始的地方。

答案 1 :(得分:0)

Git可以有多个远程连接。它不像一些其他类似系统那样限于单个主存储库。您可以使用以下命令将repo1添加为另一个远程存储库:

git remote add repo1 /path/to/your/original/complete/repository

然后你可以像往常那样得到你的分支:

git fetch repo1 branch3
git fetch repo1 branch4

如果您愿意,稍后可以结帐以进行处理:

git checkout branch4

答案 2 :(得分:0)

首先:您只能看到repo1git fetch上的git pull视图。

repo1中的所有分支都将存储在origin的{​​{1}}下。

您可以使用以下代码列出这些分支:clone1

答案 3 :(得分:0)

这应该是一个评论,但我需要格式化,我不能在评论中做(并且已经再次罗嗦了:-))。

除了Mark Adelsberger's answer(这是正确的和赞成的,你应该阅读它),我认为,有一个关键是理解这一点,这是通过你的措辞的这一点揭示的:

  

branch3 - 没有签出[在clone1上],但可以随时

关键是在这种状态下, branch3不存在

这是我在其他答案中所说的内容,并将重复:远程跟踪分支不是分支。它是远程跟踪分支名称:一个名称,如origin/branch3,是一个缩写形式的全名,以refs/remotes/开头(与分支名称相比,如branch3这是一个以refs/heads/)开头的缩写形式的全名。

(事实上,"分支"并不总是"分支",在Git中,由于Git作者和重复使用不同相同单词的习惯意义 - 这是公平的,也是一直用英语发生的,这是我们得到puns的一种方式。另见What exactly do we mean by "branch"?在这种特殊情况下,我们的意思是"分支& #34;是分支名称,即全名以refs/heads/开头的引用。)

当您要求git checkout签出不存在的分支时,例如branch3,Git将扫描您的所有远程跟踪分支名称。如果只有一个"类似于" branch3正确地,git checkout创建一个,使用远程跟踪分支名称来派生新分支的初始哈希ID值。

对于存储库中存在的分支名称,该存储库必须具有其全名以refs/heads/开头的引用。第二次斜线后出现的是分支的名称。要列出某个存储库中的所有引用,请运行git for-each-ref,其默认输出是每个引用的列表,其哈希ID以及该哈希标识的Git对象的类型。

当你做一个克隆时,你告诉你的Git - 制作克隆的那个 - 如何操纵它从另一个Git获得的引用。这是--mirror所做的关键:它说使用他们的引用来制作我的引用,而根本没有任何更改。普通克隆不会这样做,因为一旦你< em>做这样做,当你从另一个Git重新获取时,你有一个问题:你已经完全被它奴役了;您在自己的副本中更改的任何引用,您将其值替换为其值并返回到纯副本。