从多个远程位置拉/推


743

简短的说:有没有办法将git repo推送到远程仓库(而不是单个“来源”)列表并从中提取?

漫长的时候:当我在多台计算机上开发具有不同连接性的应用程序时经常遇到这种情况–例如在运输中的便携式计算机,在特定位置的计算机“ A”和另一台计算机“ B”而在另一个。此外,笔记本电脑可能仅与“ A”或“ B”(有时有时两者)具有连接。

我想让git始终从其当前可以连接的所有计算机“拉”和“推”到它,因此从一台机器跳到另一台机器并继续无缝地工作更容易。


39
自2016年起为新访客提供的注意事项:malvineous回答中git包含受一流功能认可的当前正确方法。接受的答案不正确。
ELLIOTTCABLE

@Zorzella:您能对此进行更新吗,这有点令人困惑。
ntninja '19

Answers:


503

您可以使用以下git remote命令配置多个远程存储库:

git remote add alt alt-machine:/path/to/repo

要从所有已配置的遥控器获取并更新跟踪分支,但不合并到中HEAD,请执行以下操作:

git remote update

如果当前未连接到任何一个遥控器,它将花费一些时间或抛出错误,然后继续下一个。您必须从获取的存储库或中手动进行合并cherry-pick,具体取决于您希望如何组织收集更改。

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

git pull alt master

所以实际上git pull几乎是简写git pull origin HEAD(实际上,它会在配置文件中确定以确定它,但是您知道了)。

对于推送更新,您必须手动对每个存储库执行此操作。
我认为,在设计推送时要考虑到中央存储库的工作流程。


所以你说的是“ git remote add foo ssh://foo.bar/baz”创建了一个简写形式,但是我仍然需要用“ git pull”来遍历它们,或者用“ git pull”来遍历它们。合并”(“ git remove更新”后,这里的语法是什么?)这个速记名称也不适用于“ git push”吗?即我不能“ git push foo”等(循环)吗?谢谢
Zorzella

8
“ git pull”基本上是“ git fetch”,后面是“ git merge”。“ git remote update”只是为您执行了一堆“ g​​it fetch”调用。因此剩下要做的就是“ git merge”位。您可以说“ git merge origin / master”,它将把原始版本的master合并到您当前的HEAD中。“ git pull origin master”执行相同的操作,尽管它将首先进行获取(并且,如果您已经进行过git remote update,则无需进行其他获取,因此是多余的)。是的,您可以说“ git push foo”,它将所有匹配的分支推送到名为“ foo”的远程目录。
araqnid,2009年

IIUC,您不能将其推送到正常工作的存储库中(毕竟,您可能会推送不兼容/未使用/不需要的更改)。我们必须推送到裸露的存储库中,并且仅在提取时才接收更新。因此,该解决方案要求每台机器上都有一个可用的裸仓库?
joeytwiddle

2
显然,你也可以有几个回购单一推,检查这个答案详细信息stackoverflow.com/questions/14290113/...
manei_cc

797

对于现代版本的,不再需要手动执行此操作git!看到下面的 Malvineous解决方案。

转载于此:

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

原始答案:

我已经使用了很长一段时间,并且没有不良后果,这是git邮件列表中的 Linus Torvalds建议的

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顺序,使生活变得更轻松。


104
git config -e.git/config在您的首选编辑器中打开文件。
理查德

3
以防万一。确认具有2个URL的遥控器仍然可以在1.7.12.4上完成工作。谢谢。
foob​​ar 2012年

26
我将“起源”远程命名为“ all”,以使其语义更
简洁

1
@JamesWomack在下面看到@Malvineous的答案。现在这是“更正确的”,因为git的命令行使用本身就支持git remote set-url ... --add
ELLIOTTCABLE

1
根据[branch "Master"]设置remote = Origingit pull将使用两个遥控器。
Bengt 2014年

264

从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。


19
我强烈建议您不要使用此解决方案。我们在公司中使用过它,并在钩子在一个存储库中失败而在另一个存储库中失败时遇到了严重麻烦。然后,变更集仅存在于一个存储库中。
MichaelSchmeißer2013年

4
@MichaelSchmeißer:大概在推送时可以看到错误消息,解决问题,然后再次推送以使一切恢复到干净状态?
Malvineous

7
问题在于,修复被拒绝的推送会涉及更改已经推送到另一个仓库的提交。因此,如果某人在固定这些承诺之前就已经根据这些承诺进行工作,那么事情就会变得非常讨厌,在我们的办公室中就是这种情况。
MichaelSchmeißer2013年

9
是的,这可能会很棘手。但是对我来说,似乎需要重新设计挂钩。失败的推送通常不会破坏git,因此引入新的故障点(这也会阻止您使用漂亮的git功能)可能不是最佳解决方案。当然,我这么说是不知道您的要求是什么……
Malvineous 2013年

3
否。自写问题以来,我已经阅读了其他网络帖子,然后测试了一下。通过阅读其他帖子,我怀疑仅使用第一行。我已经测试过:实际上,只有第一行的URL被检查git fetch。(鉴于此,我不明白的目的是什么git remote set-url --add可以没有--push。)
IMZ -伊万Zakharyaschev

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冠状病毒审查六四事件法轮功

我想我更喜欢别名解决方案,而不是创建新的遥控器。另请参见stackoverflow.com/questions/41372919/…–
donquixote

1
建议的小调整:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
斯科特C威尔逊,

25

您可以使用以下方法添加遥控器:

git remote add a urla
git remote add b urlb

然后更新所有存储库:

git remote update

15

这是我的.gitconfig别名部分内包含bash脚本的示例

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

7

我在.git congfig文件的远程“源”中添加了两个单独的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"

4

我自由地扩大了nona-urbiz 的答案;只需将其添加到您的〜/ .bashrc中即可:

git-pullall () { for RMT in $(git remote); do git pull -v $RMT $1; done; }    
alias git-pullall=git-pullall

git-pushall () { for RMT in $(git remote); do git push -v $RMT $1; done; }
alias git-pushall=git-pushall

用法:

git-pullall master

git-pushall master ## or
git-pushall

如果您不为git-pullall提供任何分支参数,那么从非默认远程服务器的拉取将失败;保留此行为,因为它类似于git。


3

您将需要一个脚本来遍历它们。Git没有提供“全部推送”功能。从理论上讲,您可以在多个线程中进行推送,但是本机方法不可用。

提取更为复杂,建议线性进行。

我认为,最好的答案是让所有人都有一次推/拉的机器,如果可能的话。


2
问题是,正如我所描述的,没有中央始终可用的框。如果我必须写一个循环的bash脚本,就这样吧,但分布式VC并不能在这里给我更多帮助,真是可笑...
Zorzella

2
被分发时,它假设并非每个人都可用,或不想被推到。它还涉及处于不同状态的不同存储库,以及其他人正在同时处理它们的假设。您从一组存储库中推入和拉出的顺序会影响不同存储库的状态,并且您必须进行多次传递才能真正同步它们。这就是为什么没有“拉/推全部”的原因。然后有冲突...;)
杰夫·费兰德

3

为了更新遥控器(例如,pull机箱),事情变得更容易了。

莱纳斯的声明

可悲的是,甚至没有任何方法可以用git别名来伪造它。

在该引用的条目Git的邮件列表elliottcable的回答不再是真实的。

git fetch--all在过去的某个地方了解到该参数,从而可以一次性获取所有遥控器。

如果没有全部请求,则可以使用该--multiple开关来指定多个遥控器或一组。


3

我想在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)

简单的方法,为我工作...希望这对某人有帮助。


4
git push -f无缘无故地奔跑,例如失败git push或不知道自己在做什么,这是一个坏主意,可能有害。这也没有回答问题,而是如何添加第二个遥控器。
卡尔·里希特

2

使用以下命令向全局gitconfig(/home/user/.gitconfig)添加一个别名。

git config --global alias.pushall '!f(){ for var in $(git remote show); do echo "pushing to $var"; git push $var; done; }; f'

提交代码后,我们会说

git推

默认情况下推送到原点。经过上面的别名,我们可以说

git pushall

并且代码将更新到所有遥控器,包括原始遥控器。


1

all由于必须在所使用的每台计算机上进行设置,因此添加遥控器会有些繁琐。

另外,bashgit 提供别名全部假定您将推送到所有遥控器。(例如:我sshag在GitHub和GitLab上保留了其中的一个分支。我添加了上游远程服务器,但我无权推送到它。)

这是一个git 别名,该别名仅使用包含的推送URL推送到远程服务器@

psall    = "!f() { \
    for R in $(git remote -v | awk '/@.*push/ { print $1 }'); do \
    git push $R $1; \
    done \
    }; f"

-3

添加新的遥控器

git remote add upstream https://github.com/example-org/example-repo.git

git remote -vv

从多个位置获取

git fetch --all

推送到位置

git push -u upstream/dev
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.