How to Push to Multiple Remote Git Repositories with a Single Command

J.A. ShezanJ.A. Shezan
9 min read

In modern software development, it's not uncommon to host your project on multiple Git platforms. You might have a primary repository on GitHub for public visibility and collaboration, and a mirror on GitLab for CI/CD pipelines or as a private backup. Manually pushing changes to each remote repository can be tedious and error-prone. Fortunately, Git provides a way to configure your local repository to push to multiple remotes simultaneously with a single command.

This article will guide you through the process of setting up a single remote (commonly origin) to point to multiple repository URLs, allowing for efficient and synchronized updates across all your hosted versions.

Why Push to Multiple Remotes?

Before diving into the "how," let's briefly touch upon the "why":

  • Redundancy and Backup: Hosting your code on multiple platforms mitigates the risk of data loss if one platform experiences an outage.

  • Platform-Specific Features: You might use GitHub for its community features and issue tracking, while leveraging GitLab for its robust built-in CI/CD.

  • Collaboration Across Teams: Different teams or collaborators might prefer or have access to different platforms.

  • Phased Migration: If you're migrating from one Git hosting service to another, pushing to both allows for a smoother transition.

  • Visibility: Maintaining a public repository on a popular platform like GitHub while having a private or internal one on GitLab or Bitbucket.

Step 1: Configure Your Remote with Multiple Repository URLs

The core idea is to tell Git that a single remote name should be associated with multiple "push" destinations. We'll typically use the default remote name origin, but you can choose any name.

Scenario A: Setting up a New Project or Adding a Second Remote to an Existing origin

Let's assume you have a project and you want to host it on both GitHub and GitLab.

  1. Initialize your local Git repository (if you haven't already):

     git init
     # Add your project files
     git add .
     git commit -m "Initial commit"
    
  2. Add the first repository URL to origin:

    This command creates the origin remote and sets its fetch and push URL to your primary repository, for example, on GitHub.

     git remote add origin git@github.com:your-username/your-repo.git
    
    • git remote add: This is the command to add a new remote.

    • origin: This is the conventional name for the primary remote repository. You can use a different name if you prefer.

    • git@github.com:your-username/your-repo.git: This is the SSH URL for your GitHub repository. You can also use an HTTPS URL.

  3. Add the second repository URL to origin for pushing:

    This command adds an additional URL specifically for push operations to the existing origin remote.

     git remote set-url --add --push origin git@gitlab.com:your-username/your-repo.git
    
    • git remote set-url: This command changes or adds URLs for a remote.

    • --add: This flag ensures that you are adding a new URL instead of replacing existing ones.

    • --push: This flag specifies that the URL being added is for push operations. Fetch operations will still default to the original URL (e.g., from GitHub).

    • origin: The name of the remote you're modifying.

    • git@gitlab.com:your-username/your-repo.git: The SSH URL for your GitLab repository.

Example:

Let's say your GitHub repo is git@github.com:tech-wizard/magic-project.git and your GitLab repo is git@gitlab.com:tech-wizard/magic-project-mirror.git.

# If origin doesn't exist yet or you're starting fresh for this setup
git remote add origin git@github.com:tech-wizard/magic-project.git

# Add GitLab as an additional push URL
git remote set-url --add --push origin git@gitlab.com:tech-wizard/magic-project-mirror.git

Scenario B: origin Already Exists and Points to One Repository

If you already have an origin remote configured (e.g., pointing to GitHub) and you want to add GitLab as an additional push destination:

  1. Verify your current origin:

     git remote -v
    

    You might see something like:

     origin  git@github.com:your-username/your-repo.git (fetch)
     origin  git@github.com:your-username/your-repo.git (push)
    
  2. Add the second repository's push URL:

     git remote set-url --add --push origin git@gitlab.com:your-username/your-repo.git
    

    Now, origin will still fetch from the primary URL (GitHub in this case) but will push to both GitHub and GitLab.

Using HTTPS URLs

If you prefer HTTPS URLs, the commands are similar:

git remote add origin https://github.com/your-username/your-repo.git
git remote set-url --add --push origin https://gitlab.com/your-username/your-repo.git

Keep in mind that with HTTPS URLs, you might be prompted for credentials more often unless you're using a credential helper. SSH keys are generally recommended for a smoother, password-less experience.


Step 2: Push to Both Repositories

Once your origin remote is configured with multiple push URLs, pushing to all of them is straightforward.

To push changes from your local branch (e.g., main, master, dev) to all configured push URLs for origin, use:

git push origin <branch-name>

Example: Pushing the main branch

git push origin main

If this is the first time you're pushing this branch and you want to set up upstream tracking, use the -u flag:

git push -u origin main
  • -u or --set-upstream: This flag sets up a tracking relationship between your local branch and the remote branch. This means that in the future, for this branch, you can simply use git push (if origin is your default push remote and the current branch is tracking origin/main) and git pull. Since you have multiple push URLs, git pull will still fetch from the primary URL specified for origin (the one not added with --push).

Git will now attempt to push the specified branch to each URL listed under the push configuration for origin. You'll see output indicating the push status for each remote.

What happens if one push fails?

If one of the remote pushes fails (e.g., due to network issues, permissions, or a non-fast-forward push that's rejected), Git will report the error for that specific remote. The push to other remotes might still succeed. You'll need to resolve the issue for the failed remote and attempt the push again. For critical synchronization, ensure all pushes are successful.


Step 3: Verify the Configuration

It's always a good practice to verify your remote configuration to ensure everything is set up as expected.

Use the git remote -v (verbose) command:

git remote -v

You should see an output similar to this, clearly listing multiple push URLs for origin:

origin  git@github.com:your-username/your-repo.git (fetch)
origin  git@github.com:your-username/your-repo.git (push)
origin  git@gitlab.com:your-username/your-repo.git (push)

Or, if you used the tech-wizard example:

origin  git@github.com:tech-wizard/magic-project.git (fetch)
origin  git@github.com:tech-wizard/magic-project.git (push)
origin  git@gitlab.com:tech-wizard/magic-project-mirror.git (push)

This output confirms:

  • Fetch URL: When you run git fetch origin or git pull origin, Git will fetch updates from git@github.com:your-username/your-repo.git.

  • Push URLs: When you run git push origin main, Git will attempt to push the main branch to both git@github.com:your-username/your-repo.git and git@gitlab.com:your-username/your-repo.git.


Alternative: Using a Dedicated Remote for Multiple Pushes

Instead of modifying origin to push to multiple URLs, you might prefer to keep origin pointing to your primary repository (e.g., GitHub) and create a new, separate remote (e.g., all-mirrors or sync-all) specifically for pushing to multiple destinations.

This approach can be cleaner if you want more explicit control or if origin has a very specific meaning in your workflow.

  1. Ensure origin points to your primary repository:

     git remote add origin git@github.com:your-username/your-repo.git
     # Or if it exists, verify with git remote -v
    
  2. Add your second repository as a standard separate remote (optional but good for clarity):

     git remote add gitlab git@gitlab.com:your-username/your-repo.git
    
  3. Create a new remote that will handle multiple push URLs:

    First, make it point to one of the repositories (it needs an initial URL).

     git remote add all-mirrors git@github.com:your-username/your-repo.git
    
  4. Add the other repository URLs as push URLs to this new remote:

     git remote set-url --add --push all-mirrors git@gitlab.com:your-username/your-repo.git
     # If you have a third one on Bitbucket, for example:
     # git remote set-url --add --push all-mirrors git@bitbucket.org:your-username/your-repo.git
    
  5. Verify the new remote:

     git remote -v
    

    You should see something like:

     all-mirrors  git@github.com:your-username/your-repo.git (fetch)
     all-mirrors  git@github.com:your-username/your-repo.git (push)
     all-mirrors  git@gitlab.com:your-username/your-repo.git (push)
     # all-mirrors  git@bitbucket.org:your-username/your-repo.git (push)
     gitlab       git@gitlab.com:your-username/your-repo.git (fetch)
     gitlab       git@gitlab.com:your-username/your-repo.git (push)
     origin       git@github.com:your-username/your-repo.git (fetch)
     origin       git@github.com:your-username/your-repo.git (push)
    
  6. Push using the new remote:

    Now, to push to all mirrored repositories, you would use:

     git push all-mirrors main
    

    And to push to just your primary:

     git push origin main
    

This method offers more granularity at the cost of a slightly more complex remote setup.


Managing Credentials for Multiple Remotes

If you're using SSH URLs (e.g., git@github.com:...), Git will use your SSH keys for authentication. Ensure your SSH keys are configured correctly for each service (GitHub, GitLab, Bitbucket, etc.). Typically, you'd add the same public SSH key to your accounts on all these platforms.

If you're using HTTPS URLs, Git might prompt for a username and password for each service unless you have a credential helper configured (like Git Credential Manager). Setting up a credential helper can significantly streamline authentication for HTTPS.

Real-World Examples and Use Cases

  • Open-Source Project with a Private CI Mirror:

    • origin (GitHub): Public, for community interaction.

        git remote add origin git@github.com:my-oss-project/main.git
      
    • Add GitLab for private CI/CD or as a staging mirror.

        git remote set-url --add --push origin git@internal-gitlab.com:my-team/main-ci.git
      
    • Push command: git push origin feature-branch updates both.

  • Personal Project Backup:

    • origin (GitLab): Primary development platform.

        git remote add origin git@gitlab.com:my-user/my-awesome-app.git
      
    • Add GitHub as a backup or for public portfolio display (if the project becomes public).

        git remote set-url --add --push origin git@github.com:my-user/my-awesome-app-backup.git
      
    • Push command: git push origin main.

  • Client Project with Multiple Stakeholder Repositories:

    Imagine a client requires code delivery to their private Bitbucket, but your team primarily works on GitHub.

    • origin (GitHub): Team's primary workspace.

        git remote add origin git@github.com:our-company/client-project.git
      
    • Add client's Bitbucket as a push target.

        git remote set-url --add --push origin git@bitbucket.org:client-org/project-delivery.git
      
    • Push command for releases: git push origin release-v1.0.

Potential Considerations

  • Push Time: Pushing to multiple remotes will naturally take longer than pushing to a single remote, as Git has to establish connections and transfer data for each URL.

  • Error Handling: As mentioned, if one push fails, the command will report an error for that specific remote. You'll need a strategy to handle such failures, especially in automated scripts.

  • Consistency: While this method helps keep repositories synchronized from your local machine, it doesn't prevent others from pushing directly to one of the remotes, potentially causing divergence. Clear team conventions are important.

  • Fetch Behavior: Remember that git fetch origin or git pull origin will (by default) only fetch from the first URL associated with origin (the one not added with --push specifically, or the one that isn't explicitly marked as a push-only URL). If you need to fetch from multiple sources explicitly, you'd manage them as separate remotes.

Summary

By configuring a single Git remote (like origin) with multiple push URLs, you can significantly streamline your workflow when working with projects hosted on different platforms. The git remote set-url --add --push command is the key to this setup. This method allows you to update all your repositories—be they on GitHub, GitLab, Bitbucket, or your own private server—with a single git push command.

This not only saves time but also reduces the chance of forgetting to update one of the repositories, ensuring consistency across your project's various homes. Whether for backup, CI/CD integration, or multi-platform collaboration, mastering this Git feature is a valuable addition to any developer's toolkit.


0
Subscribe to my newsletter

Read articles from J.A. Shezan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

J.A. Shezan
J.A. Shezan

Shezan loves technology who is currently studying Computer Science and Engineering. He codes frontend & backend of a website. He also does penetration testing on web apps.