无法从镜像中获取

时间:2014-08-05 13:19:19

标签: git version-control mirror

我正在将git存储库从Github迁移到本地Atlassian Stash服务器。当我正在研究基础设施时,开发人员仍在与Github合作,我的目的是将他们的工作从Github反映到Stash,直到我与Stash一起生活。

无论如何,我按如下方式设置了我的本地镜像:

git clone --mirror https://github.com/myorg/myrepo.git myrepo-mirror
cd myrepo-mirror
git remote set-url --push origin nowhere.com # prevent accidental pushes to origin
git remote add stash https://stash/myproj/myrepo.git # set "stash" remote for pushing

然后我会定期(通过cron)获取并推送:

git fetch -p origin
git push --mirror stash

然而,它在git fetch失败了。我收到以下错误:

  

致命:refs / remotes / origin / master跟踪refs / heads / master和   参/遥控器/来源/主   意外的命令流结束

我运行git branch -r,看起来很正常。所以我跑git ls-remote origin,我看到了平常,这两个奇怪的(我认为)家伙在底部:

 7e438ee97be8c7cbd8012c3c96b60e3ff8cb3c2c       refs/remotes/origin/HEAD
 7e438ee97be8c7cbd8012c3c96b60e3ff8cb3c2c       refs/remotes/origin/master

我认为最后一个是问题,但我不确定,或者如何解决它。我也跑了git config --get-all remote.origin.fetch并看到:

+refs/pull/*/head:refs/remotes/origin/pr/*
+refs/heads/*:refs/remotes/origin/*
+refs/*:refs/*

但是,我不确定是否或如何修复。

完全披露

我之前尝试镜像似乎工作得很好,但我在测试哪个基本上强制推动原点过时的工作副本(是的,我知道)时不小心git push --mirror。我试图通过转到我最近获取的CI服务器并重新创建所有分支来重建,然后镜像推回到github以使一切恢复正常。这可能是这些奇怪的参考问题开始的地方。

除了

我还尝试git clone --bare url,然后执行我的git fetch -p origin && git push --mirror stash,它说它正在运行,但我从未在我的Stash回购中看到更新的提交。

1 个答案:

答案 0 :(得分:1)

有趣。我很好奇,如果你重复这一步:

git clone --mirror https://github.com/myorg/myrepo.git myrepo-mirror

使用新的副本,并在完成后立即cd进入新克隆并重复此操作:

git config --get-all remote.origin.fetch

你会得到相同的三条refspec线吗?如果是这样,git clone --mirror出现了问题。如果没有,其他的东西就搞砸了。

现在,问题本身。问题在于这三条fetch行:

+refs/pull/*/head:refs/remotes/origin/pr/*
+refs/heads/*:refs/remotes/origin/*
+refs/*:refs/*

第一个告诉git fetch,从origin获取后,如果“他们”(远程)有分支refs/pull/master/head,那么你的git应该将其重命名为{{1} }}。 refs/remotes/origin/pr/master表示“强制”,即使您已经拥有+,请将其替换为新的refs/remotes/origin/pr/master SHA-1。

第二个告诉refs/pull/master/head,从git fetch获取后,如果他们有origin,那么你的git应该将其重命名为refs/heads/master(这是正常的) ,非refs/remotes/origin/master设置)。和以前一样,设置“强制”;您的--mirror将被新的SHA-1覆盖。

第三个告诉refs/remotes/origin/mastergit fetch获取后,如果他们有origin,你的git应该使用新的SHA-1覆盖你自己的refs/heads/master;如果他们有refs/heads/master,您的git应该覆盖您自己的refs/pull/master/head

所以,你运行refs/pull/master/head,结果是gosh,他们有一个git fetch。 (多么令人惊讶......不是!)所以你的git应该是:

  • 将其重命名为refs/heads/master
  • 不,等等,将其重命名为refs/remotes/origin/master

这是你的refs/heads/master因错误而停止的地方:它必须只挑选这两个中的一个,就像两个干草堆中间的谚语驴一样,它只是冻结而去死。 1

(如果有fetch,您的git会被告知要将其重命名为refs/pull/master/headrefs/remotes/origin/pr/master。这也会失败。但是{{1失败足以阻止事情。)

解决方法在于决定是否需要真正的镜像。如果是,请删除refs/pull/master/head行以外的所有内容。然后,您的git会在refs/heads/master+refs/*:refs/*上将所有git fetch引用转换为您自己的引用,名称完全相同。 (并添加git remote update让你的git丢弃你身边不再存在的引用。这就是你一直在做的事情,所以我想你真的想要一面真正的镜子。)

(请注意,所有这一切都特定于远程refs/*。如果/当您运行--prune对名为origin的远程执行镜像式推送时,这完全独立于名为git push --mirror stash的远程的stash配置。fetch您实际上是使用自动修剪将origin refspec设置为--mirror,所以这就像拥有push远程提取,将远程配置设置为提取镜像。)


1 如果你用真正的驴子尝试这个,他只会吃两个干草堆。这只是表明git并不是真正的聪明......嗯,你知道。 : - )