The short: is there a way to have a git repo push to and pull from a list of remote repos (rather than a single "origin")?
The long: I often have a situation when I'm developing an app in multiple computers, with different connectivity – say a laptop while on transit, a computer "A" while I'm in a certain location, and another computer "B" while on another. Also, the laptop might have connectivity with only either "A" or "B", and sometimes both.
What I would like to is for git to always "pull" from and "push" to all the computers it can currently connect to, so it's easier to jump from one machine to the other and continue working seamlessly.
git
features, is included in malvineous's answer below. The accepted answer is incorrect.
Doing this manually is no longer necessary, with modern versions of git
! See Malvineous's solution, below.
Reproduced here:
git remote set-url origin --push --add <a remote>
git remote set-url origin --push --add <another remote>
Original answer:
This something I’ve been using for quite a while without bad consequences and suggested by Linus Torvalds on the git mailing list.
araqnid’s solution is the proper one for bringing code into your repository… but when you, like me, have multiple equivalent authoritative upstreams (I keep some of my more critical projects cloned to both a private upstream, GitHub, and Codaset), it can be a pain to push changes to each one, every day.
Long story short, git remote add
all of your remotes individually… and then git config -e
and add a merged‐remote. Assuming you have this repository 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/*
… to create a merged‐remote for "Paws"
and "Codaset"
, I can add the following after all of those:
[remote "Origin"]
url = git@github.com:Paws/Paws.o.git
url = git@codaset.com:elliottcable/paws-o.git
Once I’ve done this, when I git push Origin Master
, it will push to both Paws/Master
and Codaset/Master
sequentially, making life a little easier.
You can configure multiple remote repositories with the git remote
command:
git remote add alt alt-machine:/path/to/repo
To fetch from all the configured remotes and update tracking branches, but not merge into HEAD
, do:
git remote update
If it's not currently connected to one of the remotes, it will take time out or throw an error, and go on to the next. You'll have to manually merge from the fetched repositories, or cherry-pick
, depending on how you want to organize collecting changes.
To fetch the master branch from alt and pull it into your current head, do:
git pull alt master
So in fact git pull
is almost shorthand for git pull origin HEAD
(actually it looks in the config file to determine this, but you get the idea).
For pushing updates, you have to do that to each repo manually. A push was, I think, designed with the central-repository workflow in mind.
Since git 1.8 (October 2012) you are able to do this from the command line:
git remote set-url origin --push --add user1@repo1
git remote set-url origin --push --add user2@repo2
git remote -v
Then git push
will push to user1@repo1, then push to user2@repo2.
git fetch
. (Given this, I don't understand what the purpose of git remote set-url --add
can be without --push
.)
I added these aliases to my ~/.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;'
git config alias.pushall '!for i in
git remote; do git push $i; done;'
alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
You can add remotes with:
git remote add a urla
git remote add b urlb
Then to update all the repos do:
git remote update
Here is my example with bash script inside .gitconfig
alias section
[alias]
pushall = "!f(){ for i in `git remote`; do git push $i; done; };f"
This answer is different from the prior answers because it avoids the needless and asymmetric use of the --push
option in the set-url
command of git remote. In this way, both URLs are symmetric in their configuration. For skeptics, the git config as shown by cat ./.git/config
looks different with versus without this option.
Clone from the first URL:
git clone git@github.com:myuser/myrepo.git
Review the current remote:
$ git remote -v
origin git@github.com:myuser/myrepo.git (fetch)
origin git@github.com:myuser/myrepo.git (push)
Add the second remote:
git remote set-url --add origin git@gitlab.com:myuser/myrepo.git
Confirm that both remotes are listed for push:
$ git remote -v
origin git@github.com:myuser/myrepo.git (fetch)
origin git@github.com:myuser/myrepo.git (push)
origin git@gitlab.com:myuser/myrepo.git (push)
$ git config --local --get-regexp ^remote\..+\.url$
remote.origin.url git@github.com:myuser/myrepo.git
remote.origin.url git@gitlab.com:myuser/myrepo.git
Push to all URLs in sequence:
git push
To delete a remote:
git remote set-url --delete origin git@gitlab.com:myuser/myrepo.git
I added two separate pushurl to the remote "origin" in the .git congfig file. When I run git push origin "branchName"
Then it will run through and push to each url. Not sure if there is an easier way to accomplish this but this works for myself to push to Github source code and to push to My.visualStudio source code at the same time.
[remote "origin"]
url = "Main Repo URL"
fetch = +refs/heads/*:refs/remotes/origin/*
pushurl = "repo1 URL"
pushurl = "reop2 URl"
I wanted to work in VSO/TFS, then push publicly to GitHub when ready. Initial repo created in private VSO. When it came time to add to GitHub I did:
git remote add mygithubrepo https://github.com/jhealy/kinect2.git
git push -f mygithubrepo master
Worked like a champ...
For a sanity check, issue "git remote -v" to list the repositories associated with a project.
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)
Simple way, worked for me... Hope this helps someone.
git push -f
without a reason, e.g. failure of git push
or knowing exactly what one is doing, is a bad a idea an potentially harmful. This also doesn't answer the question, but how to add a second remote.
I took the liberty to expand the answer from nona-urbiz; just add this to your ~/.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
Usage:
git-pullall master
git-pushall master ## or
git-pushall
If you do not provide any branch argument for git-pullall then the pull from non-default remotes will fail; left this behavior as it is, since it's analogous to git.
Well, if you are looking for a way to push multiple remotes simultaneously, you might be aware of git well enough. We call remote repositories as remotes in git. Pushing changes to remotes would be part of usually development cycle.
Sometimes, you may need to push changes to multiple remotes like GitHub, bitbucket, etc. To do so, you can follow the given instructions.
List your existing remotes
You can list all available remotes using the following command.
git remote -v
Suppose you don’t have already any(other) remote configured. You can do this by using the git remote.
git remote add remote_name remote_url
Example:
git remote add github https//github.com/path/to/repo
Usually, we push changes by addressing remote name by default origin something like git push origin
. You can configure group multiple remotes and give it a name. So you push to all those remotes by referring to that name.
You can add multiple remotes by using git remote or git config commands or editing the config file.
As git can group multiple remotes, you can follow any of the following ways to configure multiple remotes to push simultaneously(no need all).
Add remotes using git remote
You can set multiple remote URLs to a single remote using git remote.
If you don’t have a remote named 'all' already, create it using git remote add
then use git remote set-url –add
to add a new URL to the existing remote.
git remote add all <remote URL>
Then
git remote set-url -–add all <another remote URL>
You can cross-check added new remotes using git remote -v
.
(OR)
Group multiple remotes using git config
The git config
command is used to configure git parameters. It will edit the .git/config
file as given input.
git config –add remote.all.url https//domain.com/repo.git
git config –add remote.all.url ssh://user@host/repos/repo.git
Note without –add option command will replace existing remote URL. You can verify the updated config at .git/config
.
(OR)
Edit file .git/config
to add remote and multiple remote URLs if you know the configuration format.
Now you can push multiple remotes simultaneously by referring to the remote name with multiple remote URLs assigned.
git push all master
You can always push to multiple remote repositories without grouping them using formal bash syntax.
git push server master && git push github master
You'll need a script to loop through them. Git doesn't a provide a "push all." You could theoretically do a push in multiple threads, but a native method is not available.
Fetch is even more complicated, and I'd recommend doing that linearly.
I think your best answer is to have once machine that everybody does a push / pull to, if that's at all possible.
For updating the remotes (i.e. the pull
case), things have become easier.
The statement of Linus
Sadly, there's not even any way to fake this out with a git alias.
in the referenced entry at the Git mailing list in elliottcable's answer is no longer true.
git fetch
learned the --all
parameter somewhere in the past allowing to fetch all remotes in one go.
If not all are requested, one could use the --multiple
switch in order to specify multiple remotes or a group.
add an alias to global gitconfig(/home/user/.gitconfig) with below command.
git config --global alias.pushall '!f(){ for var in $(git remote show); do echo "pushing to $var"; git push $var; done; }; f'
Once you commit code, we say
git push
to push to origin by default. After above alias, we can say
git pushall
and code will be updated to all remotes including origin remote.
Adding the all
remote gets a bit tedious as you have to setup on each machine that you use.
Also, the bash
and git
aliases provided all assume that you have will push to all remotes. (Ex: I have a fork of sshag
that I maintain on GitHub and GitLab. I have the upstream remote added, but I don't have permission to push to it.)
Here is a git
alias that only pushes to remotes with a push URL that includes @
.
psall = "!f() { \
for R in $(git remote -v | awk '/@.*push/ { print $1 }'); do \
git push $R $1; \
done \
}; f"
Adding new remote
git remote add upstream https://github.com/example-org/example-repo.git
git remote -vv
Fetch form multiple locations
git fetch --all
Push to locations
git push -u upstream/dev
Success story sharing
git config -e
opens the.git/config
file in your preferred editor.git
's command-line supports this natively, withgit remote set-url ... --add
.[branch "Master"]
setremote = Origin
andgit pull
will use both remotes.