HomeBlogGit Mirroring: git clone --mirror vs git push --mirror for Repository Migration...

Git Mirroring: git clone –mirror vs git push –mirror for Repository Migration and Backups

Author

Date

Category

Use git clone --mirror to copy a repository exactly, then use git push --mirror to write that exact copy to another remote. That is the cleanest Git-native method for repository migration and low-level backup replication. It copies branches, tags, notes, and other refs, not just the working branches a normal clone shows you.

TLDR: git clone --mirror creates a complete bare mirror of the source repository, while git push --mirror sends every local ref to the target and deletes refs on the target that are missing locally. For example, a team migrating 48 repositories with 1,200 branches and 3,800 tags should mirror clone each source repo, then mirror push to the new host after access checks. Expect the process to preserve Git history well, but not issues, pull requests, CI secrets, or permissions. The risky part is git push --mirror, because it can overwrite and remove refs on the destination.

What git clone --mirror actually does

git clone --mirror creates a bare repository. There is no working tree, no checked-out files, and no normal editing workflow. Instead, the repository is stored as Git database data, usually in a directory ending with .git.

Compared with git clone --bare, a mirror clone is more exact. It copies all refs under refs/*, not only branch heads and tags. It also sets the remote fetch refspec so later fetches update all mirrored refs directly.

  • Normal clone: best for development work.
  • Bare clone: useful for server-side Git storage.
  • Mirror clone: best for migration, archival replication, and exact ref transfer.

A typical command looks like this:

git clone --mirror https://old.example.com/team/project.git

This creates:

project.git/

Inside it, Git stores objects, refs, packed refs, hooks, config, and metadata needed for the repository itself. The mirror is not a copy of your hosting platform. It is a copy of Git data.

server rack with blinking green lights git repositories mirror backup server migration

What git push --mirror actually does

git push --mirror pushes every ref from the local mirror to the remote. That includes branches, tags, notes, custom refs, and other refs stored under refs/*. It also removes destination refs that do not exist locally.

That last part matters. A mirror push is not a gentle upload. It is synchronization by replacement. If the target has a branch named experiment and your local mirror does not, the push may delete experiment from the target.

The catch is that this looks harmless when the target repository is empty. It becomes dangerous when someone has already pushed work to the new location. One accidental mirror push can wipe out newly created branches in seconds.

Basic migration flow:

git clone --mirror https://old.example.com/team/project.git
cd project.git
git remote set-url origin https://new.example.com/team/project.git
git push --mirror

Some teams prefer to keep the original remote name untouched and add a separate destination:

git remote add neworigin https://new.example.com/team/project.git
git push --mirror neworigin

This is safer during audits because the source and target are clearly separated.

When to use each command

Use git clone --mirror when you need a faithful local copy of Git refs. Use git push --mirror when you are ready to make a remote match that local copy.

Task Recommended command Reason
Prepare repository migration git clone --mirror Captures all refs from the source.
Move history to a new empty remote git push --mirror Writes the full mirrored state.
Create developer workspace git clone Creates files for normal work.
Update backup mirror git remote update --prune Refreshes refs and removes deleted ones.

Repository migration checklist

For migrations, treat mirror pushes like production changes. A short checklist prevents ugly surprises.

  1. Freeze writes on the old repository or announce a clear cutoff time.
  2. Create the target repository empty. Do not initialize it with a README.
  3. Run git clone --mirror from a trusted machine with stable network access.
  4. Push to the new remote with git push --mirror.
  5. Compare refs using git ls-remote on both source and target.
  6. Transfer non-Git data separately, including issues, pull requests, wikis, releases, webhooks, deploy keys, secrets, and branch rules.
  7. Ask users to update remotes after validation.

Validation should not be skipped. Run:

git ls-remote https://old.example.com/team/project.git > old.refs
git ls-remote https://new.example.com/team/project.git > new.refs
diff old.refs new.refs

If the output is empty, the visible remote refs match. If not, inspect the differences before opening the new repository to users.

a man sitting on a chair holding up a paper pokemon trainer checklist raid planning

Using mirrors for backups

A mirror clone can also serve as a compact backup. You can store the mirror on another server and refresh it on a schedule.

git clone --mirror https://example.com/team/project.git /backups/project.git
cd /backups/project.git
git remote update --prune

For a scheduled backup, run git remote update --prune through cron or a system timer. The --prune option removes refs that were deleted upstream, keeping the backup aligned with the source.

Honestly, it feels like backup systems make this sound more complete than it is. A Git mirror backs up Git history. It does not automatically back up hosting features. If your compliance plan requires issue comments, review history, branch protection settings, or audit logs, you need platform exports or API-based backups too.

For higher safety, keep multiple generations. A single mirror that prunes deleted refs can faithfully copy an accidental deletion. Many teams keep a daily mirror plus weekly snapshots, with at least 30 days of retention. That gives room to recover from force pushes, bad cleanup scripts, and mistaken branch deletion.

Common risks and limits

  • Protected branches may reject mirror pushes. Temporarily adjust rules or push as an administrator only during the migration window.
  • Git LFS objects are separate. Run LFS migration commands if the repository uses large file storage.
  • Submodules need separate handling. Each submodule points to its own repository URL.
  • Default branch settings may not move. Set the default branch in the new host after pushing.
  • Access control is outside Git. Recreate teams, roles, deploy keys, and tokens manually or by API.

For Git LFS, use commands like these after installing LFS support:

git lfs fetch --all
git lfs push --all https://new.example.com/team/project.git
grayscale photo of man large files git lfs storage transfer 1

Best-practice recommendation

For a clean migration, start with an empty destination and use git clone --mirror followed by git push --mirror. Do not use mirror push casually against a repository where people are already working. It is powerful, blunt, and unforgiving.

For backups, use mirror clones as one layer, not the whole plan. Pair them with retention snapshots and exports of hosting-platform data. That gives you both Git-level recovery and business-level recovery.

The simple rule is this: git clone --mirror copies the source into your hands; git push --mirror makes another remote match that copy. Use the first freely. Use the second only when you are ready to replace the target state.

Recent posts