Git 仓库迁移指南
什么时候用
当你想把整个仓库从一个代码托管平台迁移到另一个平台,并且希望保留分支、标签和其他 refs 时,最稳妥的方式通常是镜像迁移。
这类场景包括:
- 从 Gitee 迁移到 GitHub
- 从个人仓库迁移到组织仓库
- 保留完整历史和标签,而不是只复制默认分支
先判断当前状态
- 目标仓库最好是一个新建的空仓库,避免
--mirror覆盖已有 refs。 - 确认你对源仓库和目标仓库都具备读写权限。
- 如果仓库使用了 Git LFS,大文件对象还需要额外迁移,不能只做一次普通
git push --mirror。
推荐命令
完整迁移所有分支和标签
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
这组命令会迁移所有 refs,而不只是当前分支。
常见场景
迁移完成后做基本检查
git remote -v
git for-each-ref --format='%(refname:short)' refs/heads refs/tags
git ls-remote --heads --tags origin
只想让当前工作副本改用新的远程仓库
如果你不是做“整仓镜像迁移”,只是要让已有工作目录切到新远程:
git remote set-url origin https://github.com/username/repo-name.git
git remote -v
仓库启用了 Git LFS
git push --mirror 只会同步 Git refs,不会自动帮你上传 LFS 大文件对象。此时建议在一个普通工作副本里额外执行:
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
如果你还没配置 Git LFS,可以先看 使用Git LFS克隆大文件。
可选高级操作:改写历史提交邮箱
如果你的目的是让旧提交在 GitHub Contributions 中归属到新的邮箱,优先使用 git filter-repo,不要再把 git filter-branch 当首选。
在一个临时镜像副本里操作:
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
这会改写历史,只适合你明确知道后果、并且已经和协作者沟通过的场景。
风险与边界
git push --mirror会让目标端 refs 与本地镜像完全一致,也会删除目标端多出来的 refs。- 如果目标仓库已经有 README、初始提交或默认标签,镜像推送可能会覆盖它们。
- 历史改写类操作会改变提交哈希;只要别人已经基于旧历史开发,就必须提前协调。
git filter-branch仍能工作,但现在已经属于 legacy 工具,不建议作为默认方案。