如何从多个远程位置拉/推?

短:有没有办法让git repo推送和从远程仓库列表中提取(而不是单个“源”)?

长:当我在多台计算机上开发应用程序时,我经常会遇到这样的情况,这些计算机具有不同的连接性——例如,一台笔记本电脑在传输过程中,一台计算机“A”在某个位置,另一台计算机“B”在另一台计算机上。此外,笔记本电脑可能只与“A”或“B”连接,有时两者兼而有之。

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

382414 次浏览

你需要一个脚本来循环它们。Git不提供“全部推送”。理论上你可以在多个线程中进行推送,但本机方法不可用。

获取更复杂,我建议线性地执行此操作。

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

您可以使用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 a urlagit remote add b urlb

然后更新所有repos做:

git remote update

不再需要手动执行此操作,使用git的现代版本!请参阅Mal vine o us的解决方案,下面

转载于此:

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

原答复:

这是我已经使用了很长一段时间而没有不良后果的东西,由Linus Torvalds在git邮件列表上提出。

araqnid的解决方案是将代码带到您的存储库的正确解决方案……但是,当您像我一样拥有多个等效的权威上游时(我将我的一些更关键的项目克隆到私有上游,GitHub和Codaset),每天将更改推送到每个项目可能会很痛苦。

长话短说,单独git remote add所有遥控器……然后git config -e并添加一个合并的遥控器。假设您有这个存储库config

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

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

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

一旦我这样做了,当我git push Origin Master时,它将按顺序推到Paws/MasterCodaset/Master,使生活更容易一点。

我将这些别名添加到我的~/. 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;'

我冒昧地从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 ## orgit-pushall

如果您没有为git-Pullall提供任何分支参数,那么从非默认远程数据库的拉取将失败;保持此行为不变,因为它类似于git。

从git 1.8(2012年10月)开始,您可以从命令行执行此操作:

git remote set-url origin --push --add user1@repo1git remote set-url origin --push --add user2@repo2git remote -v

然后git push将推送到user1@repo1,然后推送到user2@repo2。

这是我在.gitconfig别名部分中使用bash脚本的示例

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

对于更新遥控器(即pull情况),事情变得更容易了。

Linus的声明

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

艾略特的回答中的git邮件列表处引用的条目不再为真。

git fetch在过去的某个地方学习了--all参数,允许一次性获取所有遥控器。

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

添加新的远程

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

获取多个位置的表单

git fetch --all

推送到位置

git push -u upstream/dev

我想在VSO/TFS中工作,然后准备好后公开推送到GitHub。在私有VSO中创建的初始存储库。当需要添加到GitHub时,我做了:

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

像冠军一样工作…

对于健全性检查,发出“git远程-v”以列出与项目关联的存储库。

C:\dev\kinect\vso-repo-k2work\FaceNSkinWPF>git remote -vgithubrepo      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)

简单的方法,为我工作…希望这能帮助别人。

我添加了两个单独的pushurl到远程“源”在. git cong文件中。当我运行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"

添加all远程变得有点乏味,因为您必须在您使用的每台机器上进行设置。

此外,提供的bashgit别名都假设您将推送到所有远程。(例如:我在GitHub和GitLab上维护了一个sshag的分支。我添加了上游远程,但我没有权限推送它。)

这是一个git别名,它只推送到包含@的推送URL的远程数据库。

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

使用以下命令将别名添加到全局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推送

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

gitpushall

并且代码将更新到所有远程,包括原始远程。

  1. 从第一个URL克隆:
git clone git@github.com:myuser/myrepo.git
  1. 查看当前遥控器:
$ git remote -vorigin  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 -vorigin  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.gitremote.origin.url git@bitbucket.org:myuser/myrepo.git
  1. 按顺序推送到所有URL:
git push

要删除远程:

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

2022年更新

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

有时,您可能需要将更改推送到多个遥控器,如GitHub、bit桶等。为此,您可以按照给定的说明进行操作。

列出您现有的遥控器

您可以使用以下命令列出所有可用的遥控器。

git remote -v

假设您还没有配置任何(其他)远程。您可以使用git远程执行此操作。

git remote add  remote_name  remote_url

示例:

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

通常,我们通过默认来源寻址远程名称来推送更改,例如git push origin。您可以配置对多个遥控器进行分组并为它们命名。因此,您通过引用该名称推送到所有这些遥控器。

您可以使用git Remote或git config命令或编辑配置文件来添加多个遥控器。

由于git可以对多个遥控器进行分组,因此您可以按照以下任何一种方法将多个遥控器配置为同时推送(不需要全部)。

使用git Remote添加遥控器

您可以使用git远程将多个远程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.gitgit 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

在最新版本的Git中,您可以为给定的远程添加多个pushurl。使用以下方法将两个pushurl添加到您的源:

git remote set-url --add --push origin git://original/repo.gitgit remote set-url --add --push origin git://another/repo.git

因此,当您推送到源时,它将推送到两个存储库。

更新1: Git1.8.0.1和1.8.1(可能还有其他版本)似乎有一个bug,导致--add在您第一次使用时替换原始URL,因此您需要使用相同的命令重新添加原始URL。做git远程-v应该会显示每个远程的当前URL。

更新2:Git维护者Junio C. Hamano解释了它的设计方式。执行git远程set-url--add--ush会为给定远程添加一个pushurl,这会覆盖推送的默认URL。但是,您可以为给定远程添加多个推送,然后允许您使用单个git推送推送到多个远程。您可以在下面验证此行为:

$ git clone git://original/repo.git$ git remote -vorigin  git://original/repo.git (fetch)origin  git://original/repo.git (push)$ git config -l | grep '^remote\.'remote.origin.url=git://original/repo.gitremote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

现在,如果你想使用单个命令推送到两个或多个存储库,你可以创建一个名为all的新远程(正如@Adam Nelson在评论中建议的那样),或者继续使用起源,尽管后者的名称对此目的的描述性较差。如果你仍然想使用起源,请跳过以下步骤,并在所有其他步骤中使用起源而不是所有。

因此,让我们添加一个名为all的新远程,稍后我们将在推送到多个存储库时引用它:

$ git remote add all git://original/repo.git$ git remote -vall git://original/repo.git (fetch)               <-- ADDEDall git://original/repo.git (push)                <-- ADDEDorigin  git://original/repo.git (fetch)origin  git://original/repo.git (push)$ git config -l | grep '^remote\.all'remote.all.url=git://original/repo.git            <-- ADDEDremote.all.fetch=+refs/heads/*:refs/remotes/all/* <-- ADDED

然后让我们向all远程添加一个pushurl,指向另一个存储库:

$ git remote set-url --add --push all git://another/repo.git$ git remote -vall git://original/repo.git (fetch)all git://another/repo.git (push)                 <-- CHANGEDorigin  git://original/repo.git (fetch)origin  git://original/repo.git (push)$ git config -l | grep '^remote\.all'remote.all.url=git://original/repo.gitremote.all.fetch=+refs/heads/*:refs/remotes/all/*remote.all.pushurl=git://another/repo.git         <-- ADDED

这里git远程-v显示了推送的新pushurl,因此如果您执行git推送所有master,它将仅将master分支推送到git://另一个/repo.git。这显示了pushurl如何覆盖默认url(remote.all.url)。

现在让我们添加另一个指向原始存储库的pushurl:

$ git remote set-url --add --push all git://original/repo.git$ git remote -vall git://original/repo.git (fetch)all git://another/repo.git (push)all git://original/repo.git (push)                <-- ADDEDorigin  git://original/repo.git (fetch)origin  git://original/repo.git (push)$ git config -l | grep '^remote\.all'remote.all.url=git://original/repo.gitremote.all.fetch=+refs/heads/*:refs/remotes/all/*remote.all.pushurl=git://another/repo.gitremote.all.pushurl=git://original/repo.git        <-- ADDED

你可以看到我们添加的两个pushurl都被保留了。现在一个git pushall master将主分支推送到git://另一个/repo.git和git://原始/repo.git.

重要注意:如果您的远程服务器有不同的规则(钩子)来接受/拒绝推送,一个远程服务器可能会接受它,而另一个远程服务器不接受它。因此,如果您希望它们具有完全相同的历史记录,您需要在本地修复您的提交以使它们被两个远程服务器都接受并再次推送,或者您可能最终只能通过重写历史记录(使用ush-f)来修复它,这可能会给已经从存储库中提取您之前的更改的人带来问题。