git clone --mirror 完整迁移仓库的全流程

git clone --mirror 是迁移 Git 仓库最彻底、最可靠的方式,它会完整复制原仓库的所有引用(分支、标签、PR/MR 引用、notes 等),保证目标仓库与原仓库在 Git 对象层面完全一致。

以下是完整迁移流程,按场景分类:


一、核心原理

--mirror 等价于 --bare + 所有引用映射,它会:

  • 克隆所有分支(包括远程追踪分支)
  • 克隆所有标签
  • 克隆所有 Git 引用(如 refs/pull/*/headrefs/notes/* 等)
  • 保留完整的 reflog 和配置

二、标准迁移流程(通用)

步骤 1:镜像克隆原仓库

bash 复制代码
# 创建裸镜像
git clone --mirror https://github.com/old-org/old-repo.git
cd old-repo.git

步骤 2:配置目标仓库地址

bash 复制代码
# 设置目标仓库为新的 remote
git remote set-url origin https://github.com/new-org/new-repo.git

步骤 3:推送所有引用到目标仓库

bash 复制代码
# 推送所有分支、标签、引用
git push --mirror

注意 :如果目标仓库已存在内容,--mirror 推送会强制覆盖,确保目标仓库为空或你确实要覆盖。

步骤 4:清理本地镜像(可选)

bash 复制代码
cd ..
rm -rf old-repo.git

三、完整迁移清单(生产环境推荐)

1. 迁移前准备

bash 复制代码
# 1. 确认原仓库完整性
git clone --mirror https://github.com/old-org/old-repo.git
cd old-repo.git

# 2. 检查仓库大小和引用数量
git count-objects -vH
git show-ref | wc -l

# 3. 验证所有分支和标签
git branch -a
git tag -l

# 4. 检查是否有 Git LFS 文件
git lfs ls-files 2>/dev/null || echo "No LFS detected"

2. 创建目标空仓库

在 GitHub/GitLab/Gitea 等平台创建一个空仓库(不要初始化 README、License 或 .gitignore)。

3. 执行迁移推送

bash 复制代码
# 设置目标地址
git remote set-url origin https://github.com/new-org/new-repo.git

# 推送所有引用(分支 + 标签 + 其他 refs)
git push --mirror

# 如果目标仓库有保护规则限制强制推送,可能需要先临时关闭

4. 迁移 Git LFS(如有)

bash 复制代码
# 如果原仓库使用了 Git LFS,需要单独迁移 LFS 对象
git lfs fetch --all
git lfs push --all origin

5. 验证迁移完整性

bash 复制代码
# 在新机器上克隆目标仓库验证
cd /tmp
git clone https://github.com/new-org/new-repo.git
cd new-repo

# 对比提交数量
git rev-list --all --count

# 对比标签
git tag -l | sort

# 对比分支
git branch -a

四、不同平台迁移的特殊处理

GitHub → GitHub(含 PR 引用)

GitHub 的 Pull Request 引用存储在 refs/pull/*/headrefs/pull/*/merge--mirror 会保留这些引用,但新 GitHub 仓库不会自动重建 PR 记录(PR 是平台元数据,不是 Git 数据)。

bash 复制代码
# 镜像克隆会拉取 PR 引用,但新仓库中这些只是普通引用
git clone --mirror https://github.com/old-org/old-repo.git
git push --mirror https://github.com/new-org/new-repo.git

PR 历史、Issue、Wiki、Actions 记录等属于平台数据,需通过 API 或平台自带迁移工具迁移。

GitLab → GitLab(含 MR 引用)

GitLab 的 MR 引用在 refs/merge-requests/*。同样,--mirror 会保留引用但不会自动重建 MR 记录

自建 Git 服务器 → 新服务器

bash 复制代码
# 直接在服务器上操作(更快)
cd /var/git/old-repo.git
git push --mirror ssh://new-server/var/git/new-repo.git

五、高级:保留原仓库所有配置

bash 复制代码
git clone --mirror https://github.com/old-org/old-repo.git
cd old-repo.git

# 查看原仓库 remote 配置
cat config

# 修改 origin URL 指向新仓库
git remote set-url origin https://github.com/new-org/new-repo.git

# 如果需要保留其他 remote(如 upstream)
git remote -v

# 推送所有引用
git push --mirror

六、常见问题

问题 原因 解决
! [remote rejected] ... 目标仓库有保护分支 临时关闭分支保护
! [rejected] ... (fetch first) 目标仓库非空 创建空仓库或先清空
LFS 文件缺失 未迁移 LFS 对象 执行 git lfs push --all
PR/MR 历史丢失 PR 是平台数据 使用平台 API 迁移
仓库体积异常大 包含大量垃圾对象 原仓库先 git gc --aggressive

七、一键迁移脚本

bash 复制代码
#!/bin/bash
set -e

OLD_URL="https://github.com/old-org/old-repo.git"
NEW_URL="https://github.com/new-org/new-repo.git"
REPO_NAME="old-repo"

# 1. 镜像克隆
git clone --mirror "$OLD_URL" "${REPO_NAME}.git"
cd "${REPO_NAME}.git"

# 2. 检查 LFS
if git lfs ls-files 2>/dev/null | head -1; then
    echo "检测到 Git LFS,正在迁移..."
    git lfs fetch --all
fi

# 3. 设置新地址并推送
git remote set-url origin "$NEW_URL"
git push --mirror

# 4. 推送 LFS(如有)
if command -v git-lfs &> /dev/null && [ -d "lfs" ]; then
    git lfs push --all origin
fi

# 5. 清理
cd ..
rm -rf "${REPO_NAME}.git"

echo "迁移完成: $NEW_URL"

八、迁移后必做检查

  1. 提交历史git log --oneline --all --graph | head -20
  2. 标签完整性git tag -l | wc -l 对比原仓库
  3. 分支完整性git branch -a
  4. 大文件/LFS:检查仓库体积是否合理
  5. CI/CD 配置:更新 webhook、部署密钥、CI 变量
  6. Issue/PR 链接 :旧仓库中的 #123 链接会失效,需平台级迁移

相关推荐
:-)16 小时前
开源项目二开 Git 规范工作流
git
阿米亚波21 小时前
【C/C++包管理器】vcpkg(by microsoft)
c语言·c++·git·vscode·microsoft·github·vcpkg
苍煜1 天前
Git Worktree 多工作树实战教学-工作多分支实用教程
git
RainingTime1 天前
新版IDEA使用传统用户名、密码登录Git
git
DevangLic1 天前
【诡异的空文件夹 和 git:冲突合并】最新的尝试
git
舒一笑2 天前
Windows + WSL2 完整复现 Avernet WAIC 6 Bot 协作演示
人工智能·git·开源
生戎马 平安京策2 天前
git寻根——^和~的区别
git
技术小结-李爽2 天前
【工具】git远程分支合并
git·gitee
RootKai2 天前
Git命令与基本使用流程
git