如何将裸仓库分支推送到另一个远程仓库?

8
我使用分散式工作流(中心+分支)。偶尔,我会想要通过最新的更改快进我的所有远程分支到它们对应的中央代码库的分支上。
我创建了中央代码库的第二个克隆版本,只是一个裸版本。使用单个git push命令,是否可以将所有分支推送到分支上?我知道通配符可以用于推送,但我无法使其起作用。例如,我尝试过这个命令(我的裸仓库有两个远程仓库,'upstream'和'origin'; origin指向我的分支,upstream是中央代码库):
git push origin refs/remotes/upstream/*:refs/heads/*

我仍然觉得git的refspec很困惑。具体来说,我不确定命名空间是用来做什么的。 我假设所有远程分支都存储在refs/heads/*下。


FYI,git push origin refs/remotes/upstream/*:refs/heads/* 应该可以工作。你是否忘记先从 upstream 仓库获取了?此外,你不需要一个本地的裸仓库来进行这个推送,你也可以从非裸仓库中进行。 - user456814
我和其他几个人撤销了这个问题的删除,因为据我所知它并不是一个完全相同的重复问题,而且我花时间回答了它:P 如果你想再次删除它,我会放手不管,但如果我的答案解决了你的问题或者对你有帮助,请考虑接受和/或点赞它。 - user456814
1个回答

8

只需使用

git push <fork> --all

将所有分支参考推送到 .git/refs/heads/ 下的其他远程仓库。

文档

来自git push的 git-scm 文档(截取相关选项):

git push [--all | --mirror | --tags] [<repository> [<refspec>...]]

--all

Instead of naming each ref to push, specifies that all refs under refs/heads/ be pushed.

您原本的命令应该可以工作

顺便提一下,您原本的命令:

git push origin refs/remotes/upstream/*:refs/heads/*

应该也能正常工作,所以我不确定在您的情况下出了什么问题。

Refspecs解释

根据您的说法,

我仍然觉得git的refspec很难理解。具体来说,我不确定命名空间是用来做什么的。我假设所有远程分支都存储在refs/heads/*下面。

那么这就是形式为refspecs的交易:

<source>:<destination>
  1. All Git repos share the same reference directory structure under their .git/refs/ directory.

    • Every repo stores local branches (relative to itself) under refs/heads/.

    • Every repo stores remote-tracking branches (relative to itself) under refs/remotes/<remote>/.

    • Other references can also be stored under refs/, including, but not limited to, refs/tags/, but I won't go into details about those. You can also create your own reference directories under refs/; GitHub, for example, stores pull requests on remotes under refs/pulls/<request-number>/.

  2. References on each side of the colon : are relative to the repo represented by that side of the refspec. Pretend that each side of the colon is prepended with the repo on that side.

    For illustration purposes, I'll add [source]/ and [destination]/ to the refspec examples below, even though that that's not actually the correct syntax for them.

    So, for example, if you wanted to push your local branches to a remote, you need to push them to the remote's local branches. You can use a refspec like this:

    git push <remote> [source]/refs/heads/*:[destination]/refs/heads/*
    

    In the above case, you can also omit the :refs/heads/*, since omitting :<destination> causes Git to replace that side with the same references used on the <source> side:

    git push <remote> refs/heads/*
    

    Now lets say that you wanted to push your local remote-tracking branches to a special "namespaced" folder on your remote called refs/special/. Then you use the following:

    git push <remote> \
    [source]/refs/remotes/<pick-a-remote>/*:[destination]/refs/special/*
    

我最初删除了我的问题,因为我没有问出“正确”的问题(在我看来)。我尽可能快地这样做是为了避免浪费任何人的时间。话虽如此,git push <fork> --all不会起作用,对吗?因为我相信它要求我将所有上游分支作为本地分支检出。 - void.pointer
@RobertDailey 没错,但正如我所指出的,你原始的引用规范应该在那种情况下起作用。 - user456814
@RobertDailey 实际上,你试图推送的仓库是裸仓库吗?因为如果是的话,所有分支都位于 refs/head/ 下,这种情况下 git push --all 是可以工作的 - user456814
抱歉造成困惑 :-) ... 我是在考虑一个非 bare 的仓库(这是我日常工作的方式)。我克隆一个 bare 仓库的唯一原因是为了将其与我的 fork 同步。但既然你说我尝试做的初始推送应该可以实现,那就太好了。我的问题不完整的部分是我想要删除 fork 上已经在上游移除的分支。但是 git 不知道 origin 上的分支是否是我推送的独特分支还是对于上游来说是孤立的。所以这部分我需要手动操作。 - void.pointer
我不知道为什么我的初始推送没有起作用,但现在它可以工作了。我想可能是我在做某些事情时没有意识到自己做错了。但现在它可以工作了。感谢您的帮助,特别是喜欢您对refspec的解释。官方的refspec文档没有解释您所概述的一些细节! - void.pointer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接