Pushing to multiple git remotes simultaneously

You can push to multiple git remotes simultaneously by setting up a remote with multuple Push URLs.1

Let’s say you have a repository on GitHub you’d like to switch over to Codeberg. Currently, the local checkout of the repository has a remote named origin, which points to the repository on GitHub:

git remote get-url origin
https://github.com/jeffkreeftmeijer/ox-md-title.el.git

First, rename the origin to github:2

git remote rename origin github

Then, add the codeberg remote:3

git remote add codeberg https://codeberg.org/jkreeftmeijer/ox-md-title.el.git

Now, let’s set up the origin so it fetches from the codeberg remote, but pushes to both codeberg and github. First, set up the fetch URL for the origin remote to point to the codeberg remote:

git remote add origin https://codeberg.org/jkreeftmeijer/ox-md-title.el.git

Then, add both Codeberg and GitHub as push URLs:4

git remote set-url --add --push origin https://codeberg.org/jkreeftmeijer/ox-md-title.el.git
git remote set-url --add --push origin https://github.com/jeffkreeftmeijer/ox-md-title.el

Now, the origin remote fetches from Codeberg, and pushes to both the GitHub and Codeberg repositories:

git remote show origin
* remote origin
  Fetch URL: https://codeberg.org/jkreeftmeijer/ox-md-title.el.git
  Push  URL: https://codeberg.org/jkreeftmeijer/ox-md-title.el.git
  Push  URL: https://github.com/jeffkreeftmeijer/ox-md-title.el
  HEAD branch: main
  Remote branch:
    main new (next fetch will store in remotes/origin)
  Local ref configured for 'git push':
    main pushes to main (up to date)

  1. https://gist.github.com/rvl/c3f156e117e22a25f242 ↩︎
  2. If the repository doesn’t have a remote yet, add the github remote gith git remote add instead of renaming an existing remote.

    ↩︎
  3. When moving a repository to Codeberg, use the migrator to automatically include data like labels, issues, pull requests, releases and milestones.

    ↩︎
  4. To ensure the remotes are set up properly, add a setup script that can be run on subsequent checkouts:

    #!/bin/sh
    for remote in \
      "https://codeberg.org/jkreeftmeijer/ox-md-title.el.git" \
      "https://github.com/jeffkreeftmeijer/ox-md-title.el.git"
    do
      git remote set-url --delete --push origin $remote 2> /dev/null
      git remote set-url --add --push origin $remote
    done
    
    git remote show origin
    
    ↩︎