Git Repository Migration Guide
When to Use
When you want to migrate an entire repository from one hosting platform to another while preserving branches, tags, and other refs, a mirror migration is usually the safest approach.
Common scenarios include:
- Migrating from Gitee to GitHub
- Migrating from a personal repository to an organization repository
- Preserving full history and tags, not just the default branch
Check Current State First
- The target repository should ideally be a newly created empty repository to avoid
--mirroroverwriting existing refs. - Confirm you have read/write access to both the source and target repositories.
- If the repository uses Git LFS, large file objects need additional migration -- a simple
git push --mirrorwon't handle them.
Recommended Commands
Full Migration of All Branches and Tags
git clone --mirror git@gitee.com:username/repo-name.git repo-name.git
cd repo-name.git
git remote set-url origin git@github.com:username/repo-name.git
git push --mirror
This set of commands migrates all refs, not just the current branch.
Common Scenarios
Basic Checks After Migration
git remote -v
git for-each-ref --format='%(refname:short)' refs/heads refs/tags
git ls-remote --heads --tags origin
Just Want to Point the Working Copy to a New Remote
If you're not doing a "full repository mirror migration" but just want to switch an existing working directory to a new remote:
git remote set-url origin https://github.com/username/repo-name.git
git remote -v
Repository Uses Git LFS
git push --mirror only syncs Git refs -- it won't automatically upload LFS large file objects. In this case, run the following in a regular working copy:
git clone git@gitee.com:username/repo-name.git repo-name
cd repo-name
git lfs fetch --all
git remote add github git@github.com:username/repo-name.git
git lfs push --all github
If you haven't configured Git LFS yet, see Cloning Large Files with Git LFS.
Optional Advanced Operation: Rewrite Commit Email Addresses
If your goal is to have old commits attributed to a new email in GitHub Contributions, use git filter-repo -- don't treat git filter-branch as the default choice.
Operate in a temporary mirror copy:
git filter-repo --commit-callback '
if commit.author_email == b"old-email@example.com":
commit.author_name = b"Your Name"
commit.author_email = b"github-email@example.com"
if commit.committer_email == b"old-email@example.com":
commit.committer_name = b"Your Name"
commit.committer_email = b"github-email@example.com"
'
git push --force --mirror
This rewrites history and is only appropriate when you fully understand the consequences and have coordinated with collaborators.
Risks and Boundaries
git push --mirrormakes the target refs identical to the local mirror -- it will also delete refs that exist on the target but not locally.- If the target repository already has a README, initial commit, or default tags, the mirror push may overwrite them.
- History-rewriting operations change commit hashes; if anyone has already developed based on the old history, you must coordinate in advance.
git filter-branchstill works, but it's now considered a legacy tool and is not recommended as the default approach.