我该如何从多个远程位置拉取/推送代码?

864

简述: 是否有一种方法可以让 git 仓库推送和拉取多个远程仓库的列表(而不是单个的“origin”)?

详述: 我经常遇到这样的情况:在多台电脑上开发应用程序,网络连接方式也不同——比如在运输中使用笔记本电脑,在某个位置使用计算机“A”,在另一个位置使用计算机“B”。此外,笔记本电脑可能只与“A”或“B”之一连接,并且有时两者都连接。

我想做的是让 git 总是从它当前可以连接到的所有电脑上 “pull” 并 “push”,这样更容易从一台机器跳转到另一台机器并继续无缝工作。


49
对于新访客的说明(截至2016年):目前正确的方法是使用一流的git功能,包含在malvineous的下面的答案中,被认可的答案是不正确的。 - ELLIOTTCABLE
我发现提供在此处的答案非常详细和概括。 - Gangula
17个回答

862

手动操作已不再必要,使用现代版本的git即可!请参阅Malvineous的解决方案,如下所示

以下是复制的内容:

git remote set-url origin --push --add <a remote>
git remote set-url origin --push --add <another remote>

Translated answer:

这是我使用了相当长一段时间并且由Linus Torvalds在git邮件列表上建议的,没有带来不良后果的东西。

araqnid的解决方案是将代码推送到您的存储库中的适当方法...但是当您像我一样有多个等效的官方上游(我将一些更重要的项目克隆到私有上游、GitHub和Codaset),每天将更改推送到每个源可能会很麻烦。

长话短说,逐个使用git remote add添加所有远程仓库...然后使用git config -e添加一个合并的远程。假设您具有此存储库config:

[remote "GitHub"]
    url = git@github.com:elliottcable/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/GitHub/*
[branch "Master"]
    remote = GitHub
    merge = refs/heads/Master
[remote "Codaset"]
    url = git@codaset.com:elliottcable/paws-o.git
    fetch = +refs/heads/*:refs/remotes/Codaset/*
[remote "Paws"]
    url = git@github.com:Paws/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/Paws/*

…来为"Paws""Codaset"创建一个合并的远程,我可以在所有这些之后添加以下内容:

[remote "Origin"]
    url = git@github.com:Paws/Paws.o.git
    url = git@codaset.com:elliottcable/paws-o.git

一旦我完成这个步骤,当我执行git push Origin Master时,它会依次推送到Paws/MasterCodaset/Master,使生活变得更加轻松。

5
以防万一,确认在1.7.12.4版本上使用具有2个URL的遥控器仍然可以完成工作。谢谢。 - foobar
27
我将名为“origin”的远程仓库改名为“all”,以使其语义略微更清晰。 - ErichBSchulz
3
请参考 @Malvineous 的回答,下面有更正确的内容。现在 git 命令行原生支持此功能,使用 git remote set-url ... --add 即可。 - ELLIOTTCABLE
1
请注意,这在镜像存储库后非常有用,如此处所述:https://help.github.com/articles/duplicating-a-repository/ - Ben Orozco
2
我不是传统意义上的人。我的第一台UNIX机器是一台Mac,那里的大写主目录永远伤害了我。这只是我的个人做法,与问题无关。;) - ELLIOTTCABLE
显示剩余8条评论

578
您可以使用 git remote 命令配置多个远程存储库:
git remote add alt alt-machine:/path/to/repo

要从所有配置的远程仓库获取并更新跟踪分支,但不合并到 HEAD 中,请执行以下操作:

git remote update

如果当前没有连接到远程之一,它将会超时或抛出错误,并继续进行下一个操作。您将需要手动从获取的存储库中合并,或者根据您希望如何组织收集更改来进行挑选。

要从alt获取主分支并将其拉入当前头部,请执行以下操作:

git pull alt master

实际上,git pull 几乎就是 git pull origin HEAD 的简写(实际上它会查看配置文件来确定这一点,但你可以明白我的意思)。

如果要推送更新,则必须手动对每个存储库执行此操作。
我认为,推送是针对中央仓库工作流程设计的。


所以你的意思是,“git remote add foo ssh://foo.bar/baz”创建了一个简写形式,但我仍然需要用“git pull”循环遍历它们,或者用“git merge”循环遍历它们(在“git remove update”之后的语法是什么?)这个简写名称也适用于“git push”吗?也就是说,我不能“git push foo”等(循环)吗?谢谢。 - Zorzella
10
"git pull"基本上是执行"git fetch"之后跟着执行"git merge"。"git remote update"代表为你执行一系列的"git fetch"调用。剩下需要做的就是执行"git merge"。你可以运行"git merge origin/master",它将把远程仓库origin的master分支合并到当前的代码上。虽然"git pull origin master"也会完成相同的操作,但它会先进行一次fetch(如果你已经执行了"git remote update"且没有更多内容更新时,这个fetch操作就是多余的)。是的,你可以通过运行"git push foo"将所有匹配的分支推送到名为"foo"的远程仓库中。 - araqnid
2
显然,您也可以为多个存储库进行单个推送,请查看此答案以获取更多详细信息https://dev59.com/O2Yq5IYBdhLWcg3wridD - manei_cc

307

自从 Git 1.8(2012年10月)起,您可以通过命令行执行此操作:

git remote set-url origin --push --add user1@repo1
git remote set-url origin --push --add user2@repo2
git remote -v

那么 git push 将会推送到 user1@repo1,然后再推送到 user2@repo2。


27
我强烈反对采用这种解决方案。我们公司曾使用过它,在一个存储库中遇到了钩子失败的严重问题,而在另一个存储库中则没有。此后,变更集只存在于一个存储库中。 - Michael Schmeißer
7
你可能能在推送时看到错误信息,解决问题后再次推送以使所有内容回到干净的状态。 - Malvineous
9
问题在于修复已被拒绝的推送需要更改已经推送到其他代码库的提交记录。如果在修复之前有人已经基于这些提交记录进行了工作,那么情况就会变得非常棘手,这在我们公司就是这种情况。 - Michael Schmeißer
16
啊,是的,这可能会变得棘手。不过对我来说,这似乎意味着需要重新设计钩子。通常情况下,一个推送失败并不会破坏Git,因此引入一个新的故障点(还会防止您使用Git的一个好功能)可能不是最佳解决方案。当然,我说这话是不知道您的要求是什么... - Malvineous
7
不行。自从我写下我的问题后,我阅读了其他网站的帖子,然后测试了一下这个东西。通过阅读其他帖子,我怀疑只有第一行被使用。我刚刚进行了测试:确实,只有第一行的URL被git fetch检查。(鉴于此,如果没有--push,我不明白git remote set-url --add的目的是什么。) - imz -- Ivan Zakharyaschev
显示剩余7条评论

34

我在我的~/.bashrc文件中添加了以下别名:

alias pushall='for i in `git remote`; do git push $i; done;'
alias pullall='for i in `git remote`; do git pull $i; done;'

6
太棒了!我最终设置了一个Git别名:git config alias.pushall '!for i in git remote; do git push $i; done;' - Ciro Santilli OurBigBook.com
我认为我更喜欢使用别名解决方案而不是创建一个新的远程。另请参阅https://dev59.com/iJ3ha4cB1Zd3GeqPY7tw#41372952 - donquixote
1
小建议的调整:alias pushall='for i in \git remote`; do echo "Pushing to " $i; git push $i; done;'` - Scott C Wilson

27

您可以使用以下命令添加远程:

git remote add a urla
git remote add b urlb

然后要更新所有的仓库,请执行以下操作:

git remote update

17
  1. 从第一个URL克隆:
git clone git@github.com:myuser/myrepo.git
  1. 审核当前远程访问情况:
$ git remote -v
origin  git@github.com:myuser/myrepo.git (fetch)
origin  git@github.com:myuser/myrepo.git (push)
  1. 添加第二个远程仓库origin:
git remote set-url --add origin git@bitbucket.org:myuser/myrepo.git
  1. 确认两个远程 push 的列表是否都列出:
$ git remote -v
origin  git@github.com:myuser/myrepo.git (fetch)
origin  git@github.com:myuser/myrepo.git (push)
origin  git@bitbucket.org:myuser/myrepo.git (push)

$ git config --local --get-regexp ^remote\..+\.url$
remote.origin.url git@github.com:myuser/myrepo.git
remote.origin.url git@bitbucket.org:myuser/myrepo.git
  1. 按顺序将内容推送到所有的URL:
git push
删除远程分支:

要删除一个远程分支:

git remote set-url --delete origin git@bitbucket.org:myuser/myrepo.git

15

这里是我的示例,它在.gitconfig别名部分内包含了bash脚本。

[alias]
        pushall = "!f(){ for i in `git remote`; do git push $i; done; };f"

14

2023年更新

如果您想同时推送多个远程仓库,您可能已经足够了解Git。在git中,我们将远程仓库称为远程仓库。将更改推送到远程仓库是正常开发周期的一部分。

有时候,您可能需要将更改推送到多个远程仓库,比如GitHub、bitbucket等。为此,您可以按照以下说明操作:

列出您现有的远程仓库

您可以使用以下命令列出所有可用的远程仓库。

git remote -v

假设您尚未配置任何其他远程(remote)。您可以通过使用git remote进行配置。

git remote add  remote_name  remote_url

示例:

git remote add github https//github.com/path/to/repo

通常情况下,我们通过默认的远程名称 origin 推送更改,例如 git push origin。您可以配置多个远程并为它们命名。这样,您就可以通过引用该名称将更改推送到所有这些远程。
您可以使用 git remote 或 git config 命令或编辑配置文件添加多个远程。
由于 Git 可以分组多个远程,因此您可以按照以下任何一种方式配置多个远程以同时推送(无需全部)。
使用 git remote 添加远程
您可以使用 git remote 将多个远程 URL 设置为单个远程。
如果您还没有名为“all”的远程,请使用 git remote add 创建它,然后使用 git remote set-url --add 为现有远程添加新的 URL。
git remote add all <remote URL>

那么。
git remote set-url  --add  all  <another remote URL>

你可以使用git remote -v交叉检查添加的新远程。

(或者)

使用git config将多个远程分组

git config命令用于配置git参数。它将根据给定的输入编辑.git/config文件。

git config --add remote.all.url  https//domain.com/repo.git
git config --add remote.all.url  ssh://user@host/repos/repo.git

注意:没有--add选项,该命令将替换现有的远程URL。您可以在.git/config中验证更新后的配置。

(或者)

如果您了解配置格式,请编辑文件.git/config以添加远程和多个远程URL。

现在,您可以通过引用具有多个远程URL分配的远程名称来同时推送多个远程操作。

git push all master

你可以使用正式的bash语法而不用将它们分组,始终向多个远程存储库推送。

git push server master && git push github master

8
我在.git配置文件中,为远程仓库“origin”添加了两个独立的pushurl。当我运行git push origin "branchName"时,它会通过每个URL推送。不确定是否有更简单的方法来完成此操作,但这对我来说可以同时将代码推送到Github源代码和My.visualStudio源代码。
[remote "origin"]
  url = "Main Repo URL"
  fetch = +refs/heads/*:refs/remotes/origin/*
  pushurl = "repo1 URL"
  pushurl = "reop2 URl"

6

我想要在VSO/TFS上工作,然后在就绪时向GitHub公开发布。最初的存储库是在私有VSO中创建的。当需要添加到GitHub时,我执行了以下操作:

git remote add mygithubrepo https://github.com/jhealy/kinect2.git
git push -f mygithubrepo master

非常顺利的工作...

作为一种理智检查方式,可以通过执行“git remote -v”来列出与项目相关联的存储库。

C:\dev\kinect\vso-repo-k2work\FaceNSkinWPF>git remote -v
githubrepo      https://github.com/jhealy/kinect2.git (fetch)
githubrepo      https://github.com/jhealy/kinect2.git (push)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (fetch)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (push)

这是一种简单的方法,对我有用...希望能帮到其他人。


5
不带理由地运行git push -f,例如git push失败或确切知道自己在做什么,是一个不好的想法并且可能会造成伤害。这也没有回答问题,但是如何添加第二个远程仓库。 - Kalle Richter

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