tl;dr You can push to multiple remotes at once.


You’ve probably got the same muscle memory I do.

git remote add origin [paste the repo path you copied from Github]

I memorized this cryptic line years before I knew what it did. Let’s review what this is real quick.

What is a remote?

Git’s fancy way of saying “the place where your code is stored.” https://help.github.com/articles/about-remote-repositories/

Cool. And you can’t push until you know where you’re pushing.

To explore a bit, here’s a fun trick.

tail -F .git/config

This will allow us to peak behind the curtain as we add the remote (in another terminal of course).

Note that this is an uppercase F. -f does not work due to the way Git touches itself.

Now let’s do the dang thing and see what happens.

git remote add origin git@github.com:reergymerej/multiple-git-remotes.git

Hey, look! We got a new remote entry for “origin.” And it’s the url we specified.

.git/config

What is this we’re looking at? You can learn all about it here, but I’m betting you don’t want to read that. The gist of it is, this is the file where Git stores configurations like your remotes and any other repo-specific options.

So why are we looking at it? You’ll see in a second, but next, let’s add another remote to push to.

Time Out - Why?

You know that icky feeling you got when you found out Github was bought by MICROS~1? For me, I thought, “Dang. Why have I centralized all my code? Git’s built to be decentralized, but I keep putting everything on Github. Should I move it all? What happens with Salesforce buys the next place? Go to another? Why can’t I just spread my code all over the place?”

That’s what we’re doing.

Get Pushy

Here’s another fun trick. Watch .git/config while we do this.

git remote set-url --push origin git@gitlab.com:reergymerej/multiple-git-remotes.git
[remote "origin"]
	url = git@github.com:reergymerej/multiple-git-remotes.git
	fetch = +refs/heads/*:refs/remotes/origin/*
	pushurl = git@gitlab.com:reergymerej/multiple-git-remotes.git

Now look at your remotes with the more familar git remote -v.

origin	git@github.com:reergymerej/multiple-git-remotes.git (fetch)
origin	git@gitlab.com:reergymerej/multiple-git-remotes.git (push)

Yay! We went through a lot of silly stuff to tell it to fetch from Github and push to Gitlab. WTF?

Hold on, pushy. We’re just exploring.

Let’s read the man page for git remote set-url to understand what we just did.

$ git remote set-url --help
usage: git remote set-url [--push] <name> <newurl> [<oldurl>]
   or: git remote set-url --add <name> <newurl>
   or: git remote set-url --delete <name> <url>

    --push                manipulate push URLs
    --add                 add URL
    --delete              delete URLs

This is probably the easiest to comprehend Git documentation I’ve ever seen. Something is not obvious here, though. You can combine a couple of them so instead of just manipulating the push URL, you can also add one.

Let’s Get Crazy!

git remote set-url --add --push origin git@banana.com:boom.git
git remote set-url --add --push origin this-will-never-work!
git remote set-url --add --push origin :D

.git/config

[remote "origin"]
	url = git@github.com:reergymerej/multiple-git-remotes.git
	fetch = +refs/heads/*:refs/remotes/origin/*
	pushurl = git@gitlab.com:reergymerej/multiple-git-remotes.git
	pushurl = git@banana.com:boom.git
	pushurl = this-will-never-work!
	pushurl = :D
$ git remote -v
origin	git@github.com:reergymerej/multiple-git-remotes.git (fetch)
origin	git@gitlab.com:reergymerej/multiple-git-remotes.git (push)
origin	git@banana.com:boom.git (push)
origin	this-will-never-work! (push)
origin	:D (push)

I think this has been demystified a bit. So let’s push!

Shameless plug: If you’re exploring Git, it is nice to be able to generate commits. Try glitter.

$ glitter 6
$ git log --oneline
4ba02f6 (HEAD -> master) Remove one useful Dysprosium
9832ee2 Change zero experimental Americium
899901a Add three violet Gallium
6a21594 Change zero experimental Silver
e4c0d8c Remove three hidden Thorium
5d76bfd Change six nasty Arsenic

$ git push -u origin master

Wow. That failed miserably, probably because many of those remotes were crap. Now, try removing them with your badass Git skills and replacing them with real repos you have access to. Then when you push, you can push to a bunch of different places at once. Who cares who owns them?!


Demo

I realize that I missed the mark a bit. What I really wanted to show you is that you can add each of those remotes like a schmuck, or, now that you are familiar with .git/config, you can just add them there much faster. (Hint: You can delete silly garbage remotes, too!)

$ git remote -v
origin	git@eggbasket:/opt/git/multiple-git-remotes.git (fetch)
origin	git@eggbasket:/opt/git/multiple-git-remotes.git (push)
origin	git@github.com:reergymerej/multiple-git-remotes.git (push)
origin	git@gitlab.com:reergymerej/multiple-git-remotes.git (push)

$ git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 317 bytes | 317.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To eggbasket:/opt/git/multiple-git-remotes.git
   4ba02f6..425b7aa  master -> master

Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 317 bytes | 317.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:reergymerej/multiple-git-remotes.git
   4ba02f6..425b7aa  master -> master

Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 317 bytes | 317.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To gitlab.com:reergymerej/multiple-git-remotes.git
   4ba02f6..425b7aa  master -> master