How to Keep Two Git Repositories in Sync – and Fix a Subtle Remote URL Typo That Breaks Mirroring

Published Date Author: , Posted April 21st, 2026 at 10:32:21am

Sometimes the hardest part of Git is not Git at all. It is syntax.

This started as a practical question: how do you keep two repositories in sync?

From there, it narrowed into a more specific and more useful problem:

How do you take a working repository on one machine, make it live on another server as a proper Git host, avoid rsync, and use only Git commands?

Then came the part that makes this worth writing down: the setup was basically correct, but one tiny typo in the remote URL caused Git to reject the destination entirely.

It was a perfect example of how a one-character mistake can make a perfectly reasonable setup look broken.

Here is the clean version of the full answer.

What “keep two repos in sync” usually means

People often use that phrase to describe three different situations.

The first is simple: one working repository, two remotes, and both remotes should contain the same code. In that case, you can push to both destinations from one local repo.

The second is more selective: one repo feeds another, but not every branch or commit should move across. That is a fetch-and-merge or cherry-pick workflow.

The third is the one that matters here: the second server should become a real Git host for the same repository. That means it should behave like a proper remote, support clone and fetch operations, and stay aligned with the source.

That is not really a file-copying problem. It is a Git mirroring problem.

Why rsync is not the best long-term answer

Yes, you can use rsync to copy the contents of a repository from one machine to another. If the destination is already a bare Git repository, that can work for bootstrapping.

But rsync copies files. Git copies refs, history, tags, and deletions in a Git-aware way.

If the goal is to make another server act as a real hosted Git remote, Git’s own mirroring commands are the better tool. They are cleaner, more accurate, and better suited for ongoing synchronization.

So the better question becomes:

What is the most efficient Git-only way to mirror a working repository to another server?

The correct Git-only approach

If the directory already exists on the target server but has not been initialized yet, the next step is simple.

On the target server, initialize that directory as a bare repository:

cd /path/to/new-git-dir
git init --bare

That matters.

A hosted Git repository should normally be bare. A bare repo contains the Git database and refs, but no checked-out working tree. That is what you want for a server-side remote.

Then, from the source machine, inside the working repository, add the target server as a remote and push a mirror:

cd /path/to/repoA
git remote add target user@hostB:/path/to/new-git-dir
git push --mirror target

That is the cleanest Git-native answer.

The --mirror option pushes all refs, which means:

  • branches
  • tags
  • remote-tracking refs
  • deletions

If the goal is a true mirror, this is exactly what you want.

To verify that the target is live, run:

git ls-remote user@hostB:/path/to/new-git-dir

If it prints refs, the target is serving the repo correctly.

The real-world failure: a malformed remote URL

That should have been straightforward, but here is where things went sideways.

The remote was added like this:

git remote add target git.continuent.com/volumes/data/git/claude-coach/

Then the push was attempted:

git push --mirror target

Git responded with:

fatal: 'git.continuent.com/volumes/data/git/claude-coach/' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

At that point it was tempting to assume the server path was wrong or the repository had not been initialized yet.

But the actual problem was smaller and more annoying than that.

The remote URL itself was malformed.

A second attempt was made:

git remote add target git@git.continuent.com/volumes/data/git/claude-coach/

That produced a different error:

error: remote target already exists.

Now there were two issues in play.

First, the remote named target already existed, so git remote add was the wrong command.

Second, the replacement URL was still not quite right.

The one missing character

For SSH-style Git remotes, the path must be written in one of these forms:

git@host:/absolute/path/to/repo.git

or:

ssh://git@host/absolute/path/to/repo.git

The broken version looked like this:

git@git.continuent.com/volumes/data/git/claude-coach/

The correct version is:

git@git.continuent.com:/volumes/data/git/claude-coach/

The missing character was the colon after the hostname.

That one colon is what tells Git to interpret the rest as a remote SSH path.

Without it, Git does not understand the destination the way you expect.

How to fix the already-created remote

Because the remote already existed, the correct repair was not to add it again. It was to update it.

This is the fix:

git remote set-url target git@git.continuent.com:/volumes/data/git/claude-coach/
git remote -v
git push --mirror target

If the real directory on the server ends in .git, then match the real path:

git remote set-url target git@git.continuent.com:/volumes/data/git/claude-coach.git
git push --mirror target

The rule is simple: the remote URL must match the actual path on the server, and the SSH syntax must be valid.

Do not skip the bare repo initialization

Even with the URL fixed, the target still needs to be initialized correctly on the server.

On the remote host:

mkdir -p /volumes/data/git/claude-coach
cd /volumes/data/git/claude-coach
git init --bare

If the directory exists but has not been turned into a bare Git repo, the push still will not behave the way you want.

A plain directory is not a Git host.

A bare repo is.

The clean end-to-end sequence

If you want the shortest reliable recipe for making a working repo live on another server using only Git commands, this is it.

On the target server:

mkdir -p /volumes/data/git/claude-coach
cd /volumes/data/git/claude-coach
git init --bare

On the source machine:

cd /Users/erics/wyzaerd/claude-coach
git remote add target git@git.continuent.com:/volumes/data/git/claude-coach/
git push --mirror target

If the remote was already added incorrectly, repair it instead:

git remote set-url target git@git.continuent.com:/volumes/data/git/claude-coach/
git remote -v
git push --mirror target

And verify it:

git ls-remote git@git.continuent.com:/volumes/data/git/claude-coach/

If that returns refs, the repository is live.

When to use which method

This entire conversation really came down to a few practical rules.

If you want one local repo to push to two different hosted destinations, use multiple push URLs or a second remote.

If you want to copy a repo from one server to another once, rsync can work, but only if the target is a bare repo and you understand that you are copying files, not using Git as Git.

If you want a proper ongoing mirror to another server, initialize the target as bare and use:

git push --mirror

And if Git insists the destination “does not appear to be a git repository,” do not just stare at the server path. Inspect the remote URL character by character. The problem may be nothing more than one missing colon.

Final takeaway

The best solution turned out to be very clean:

  1. Create the target directory.
  2. Initialize it with git init --bare.
  3. Add the remote using correct SSH syntax.
  4. Push with git push --mirror.

The actual failure was not a complicated Git problem at all. It was a syntax problem disguised as a repository problem.

That is what makes this particular mistake worth documenting.

When a Git mirror setup looks correct but still fails, sometimes the fix is not a redesign, a reinstall, or a new workflow.

Sometimes it is one character.

No comments as yet.

Leave Your Comment  Leave a comment

All fields marked with "*" are required.