257

Instead of doing:

git push origin --all && git push nodester --all && git push duostack --all

Is there a way to do that with just one command?

Thanks :)

balupton
  • 47,113
  • 32
  • 131
  • 182

7 Answers7

351

Create an all remote with several repo URLs to its name:

git remote add all origin-host:path/proj.git
git remote set-url --add all nodester-host:path/proj.git
git remote set-url --add all duostack-host:path/proj.git

Then just git push all --all.


This is how it looks in .git/config:

  [remote "all"]
  url = origin-host:path/proj.git
  url = nodester-host:path/proj.git
  url = duostack-host:path/proj.git
Aristotle Pagaltzis
  • 112,955
  • 23
  • 98
  • 97
  • 12
    Super cool trick! The only disadvantage is that it does not move remote heads. You need to run `git fetch --all` right after doing such push. – madhead Mar 25 '13 at 20:42
  • 16
    Mr. Torvalds (creator of Git) mentions that he uses this method, but he states that it is merely for convenience and offers no technical advantage http://marc.info/?l=git&m=116231242118202&w=2 "And in the end, even a "git push all" that pushes to multiple repositories will actually end up connecting once for each repository, so it's really just a shorthand for doing multiple "git push"es. There's no real technical advantage, just a convenience." – Matt Aug 15 '13 at 03:39
  • 26
    One problem with this approach is that you have to add new URLs to the `all` remote as they become available, whereas `git remote | xargs -L1 git push --all` will automatically pick up any new remotes. – Raffi Khatchadourian May 05 '15 at 21:29
  • 4
    Tip: To no need typing `all` whenever you send a commit, just use "origin" instead of "all": `git remote set-url --add origin nodester-host:path/proj.git` – macabeus Jun 08 '15 at 17:48
  • forgot to set the push urls otherwise `git push` won't update all the urls. answer updated accordingly – user3338098 Apr 13 '16 at 17:58
  • never-mind answer update rejected: just remember to do `git remote set-url --add --push all duostack-host:path/proj.git` otherwise it won't push to that url. – user3338098 Apr 15 '16 at 00:17
  • the corresponding push config setting looks like `pushurl = duostack-host:path/proj.git` – user3338098 Apr 15 '16 at 00:18
  • 1
    The advantage to this answer is that it is about git itself – Samie Bencherif Jul 29 '19 at 16:42
  • this is great... after this how do you remove one from the `all` group? – Keith E. Truesdell May 06 '22 at 14:13
  • Same way you added it? Just delete the line from the `.git/config` file… – Aristotle Pagaltzis May 21 '22 at 02:57
339

To push all branches to all remotes:

git remote | xargs -L1 git push --all

Or if you want to push a specific branch to all remotes:

Replace master with the branch you want to push.

git remote | xargs -L1 -I R git push R master

(Bonus) To make a git alias for the command:

git config --global alias.pushall '!git remote | xargs -L1 git push --all'

Running git pushall will now push all branches to all remotes.

weakish
  • 28,682
  • 5
  • 48
  • 60
  • 2
    Very good and simple solution. BTW you can use xargs -l instead of -L 1, the -l option is the same as -L 1. Also, sometimes I add --all to the git push. git remote | xargs -l git push --all – Tony Jun 18 '14 at 13:34
  • 3
    I get `xargs: illegal option -- l` on OSX. Figured it out, you need `git remote | xargs -L1 git push` – balupton Aug 24 '14 at 22:45
  • 6
    Git allows you to make that call into a custom command. Just put it in a file that 1) is on your path, 2) you have execute permissions for, and 3) called "git-[custom name]" (e.g. git-foo, git-push-all) and you'll be able to simply type "git [custom name]" (e.g. git foo, git push-all). – vowel-house-might Apr 09 '15 at 10:09
  • 4
    @Tony On Ubuntu, `man xargs` says option `-l` is deprecated since it's not in the POISX spec. – wjandrea Sep 15 '17 at 21:51
  • what does `!` in alias? – kyb Apr 10 '18 at 22:19
  • 5
    @kyb In git alias syntax, `!` means the following is not an internal git command, but an external shell command. – weakish Apr 11 '18 at 12:12
  • 1
    note `xargs -I` implies `-L1`. 2nd expression could be shorten. – kyb Apr 11 '18 at 14:14
  • macOS 10.15.3 I get `xargs: push: No such file or directory` when using `-I` but works fine for using `-L1` – James Cushing May 01 '20 at 09:09
  • `git remote | xargs -t -I % git push '%' main` is success on windows. – Banee Ishaque K Nov 18 '21 at 08:22
  • if you're in powershell `git remote | ForEach-Object {git push --all $_}` – j-hap Aug 02 '22 at 13:28
134

If you want to always push to repo1, repo2, and repo3 but always pull only from repo1, set up the remote 'origin' as

[remote "origin"]
    url = https://exampleuser@example.com/path/to/repo1
    pushurl = https://exampleuser@example.com/path/to/repo1
    pushurl = https://exampleuser@example.com/path/to/repo2
    pushurl = https://exampleuser@example.com/path/to/repo3
    fetch = +refs/heads/*:refs/remotes/origin/*

Configure at command line:

$ git remote add origin https://exampleuser@example.com/path/to/repo1
$ git remote set-url --push --add origin https://exampleuser@example.com/path/to/repo1
$ git remote set-url --push --add origin https://exampleuser@example.com/path/to/repo2
$ git remote set-url --push --add origin https://exampleuser@example.com/path/to/repo3

If you only want to pull from repo1 but push to repo1 and repo2 for a specific branch specialBranch:

[remote "origin"]
    url = ssh://git@aaa.xxx.com:7999/yyy/repo1.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    ...
[remote "specialRemote"]
    url = ssh://git@aaa.xxx.com:7999/yyy/repo1.git
    pushurl = ssh://git@aaa.xxx.com:7999/yyy/repo1.git
    pushurl = ssh://git@aaa.xxx.com:7999/yyy/repo2.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    ...
[branch "specialBranch"]
    remote = origin
    pushRemote = specialRemote
    ...

See https://git-scm.com/docs/git-config#git-config-branchltnamegtremote.

Meng Lu
  • 13,726
  • 12
  • 39
  • 47
20

As a CLI Alternative to editing the .git/config file, you could use the following commands:

# git remote add all origin-host:path/proj.git
# git remote set-url --add all nodester-host:path/proj.git
# git remote set-url --add all duostack-host:path/proj.git

The same git push all --all works here as well.

You have accomplished the same as answer #1. You have just done it with Command Line instead of raw editing of the config file.

2

I wrote a short bash function to push to many remotes in one call. You can specify a single remote as a parameter, multiple remotes separated by spaces or don't specify any to have it push to all remotes.

This can be added to your .bashrc or .bash_profile.

function GitPush {
  REMOTES=$@

  # If no remotes were passed in, push to all remotes.
  if [[ -z "$REMOTES" ]]; then
    REM=`git remote`

    # Break the remotes into an array
    REMOTES=$(echo $REM | tr " " "\n")
  fi

  # Iterate through the array, pushing to each remote
  for R in $REMOTES; do
    echo "Pushing to $R..."
    git push $R
  done
}

Example: Let's say your repo has 3 remotes: rem1, rem2 and rem3.

# Pushes to rem1
GitPush rem1

# Pushes to rem1 and rem2
GitPush rem1 rem2

# Pushes to rem1, rem2 and rem3
GitPush
KeyboardCowboy
  • 563
  • 4
  • 13
1

You can utilize git hooks - especially pre-push: add non-origin pushes to .git/hooks/pre-push.

Vitaly Zdanevich
  • 13,032
  • 8
  • 47
  • 81
-1

If you already have an existing repository with origin as the default remote and want to push to multiple remote repositories by just calling git push (or with the git sync button of your IDE / text editor) first add the current origin URL (that is used for all operations e.g. push, pull, fetch) as a push-specific remote origin URL:

git remote set-url --push --add origin "$(git remote get-url --push origin)"

... and then add each other remote repository to the push-specific URLs like that:

git remote set-url --push --add origin "git@github.com:username/repo-name.git"

Now all fetch and pull operations will only fetch from your original remote repository.

But with a simple git push git pushes your latest changes to all remote repositories you've added right now.

miu
  • 1,234
  • 2
  • 18
  • 34