我正在将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回购中看到更新的提交。
答案 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/master
从git 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/head
和refs/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并不是真正的聪明......嗯,你知道。 : - )