为什么需要仓库迁移?
在日常开发工作中,Git仓库迁移是一个常见但容易被忽视的关键任务。无论是从GitHub迁移到自建GitLab、SVN过渡到Git,还是在云服务提供商(如AWS CodeCommit)之间切换,合理的迁移策略可以:
- 保留完整项目历史(提交记录、分支、标签)
- 确保团队协作连续性
- 保留关键配置(钩子、忽略规则)
- 避免工作丢失和协作中断
本文将带您从基础到进阶,一步步掌握Git迁移的核心技巧和最佳实践。
一、基础迁移:简单仓库的完整迁移
1. 完整镜像克隆(保留所有分支和标签)
# 创建裸克隆(bare clone)获取完整仓库镜像
git clone --mirror https://github.com/user/old-repo.git
# 进入克隆的仓库
cd old-repo.git
# 查看所有分支验证完整性
git branch -a
# 推送所有内容到新仓库
git push --mirror https://gitlab.com/user/new-repo.git
此方法会迁移:
- 所有分支(包括未合并的分支)
- 所有标签(tag)
- 完整提交历史
- 引用(refs)和配置
2. 本地仓库重定向(已有本地副本时)
# 查看当前远程信息
git remote -v
# 修改远程URL
git remote set-url origin https://new-host.com/user/repo.git
# 完整推送(强制覆盖)
git push --all --force
git push --tags --force
迁移验证清单 ✅
- 主分支内容完整
- 标签存在且指向正确提交
- 提交历史无缺失
- 特殊分支(如gh-pages)已迁移
- .gitignore文件完整
二、进阶场景:复杂仓库迁移处理
1. 迁移包含子模块的仓库
# 递归方式克隆仓库
git clone --recursive https://github.com/user/multi-repo.git
# 进入项目目录
cd multi-repo
# 更新.gitmodules文件
sed -i 's#old-domain.com#new-domain.com#g' .gitmodules
# 初始化子模块
git submodule update --init --recursive
# 推送到新仓库
git push --recurse-submodules=on-demand --mirror https://new-host.com/user/repo.git
2. Git LFS大文件迁移
# 克隆原仓库(含LFS)
git lfs clone https://github.com/user/big-repo.git
# 进入目录
cd big-repo
# 提取所有LFS文件
git lfs fetch --all
# 推送到新仓库
git lfs push --all https://new-host.com/user/repo.git
# 推送仓库主体
git push --mirror https://new-host.com/user/repo.git
3. 迁移特定分支和标签
# 只克隆特定分支
git clone -b production --single-branch https://github.com/user/repo.git
# 添加其他重要分支(如hotfix)
git remote set-branches --add origin hotfix-2023
git fetch origin hotfix-2023
# 选择性推送
git push https://new-host.com/repo.git production
git push https://new-host.com/repo.git hotfix-2023
git push https://new-host.com/repo.git --tags
三、特殊迁移场景处理
1. 从SVN迁移到Git(完整历史迁移)
# 创建作者映射文件 authors.txt
svn-user1 = Full Name <user1@email.com>
svn-user2 = Another Name <user2@email.com>
# 执行标准迁移
git svn clone <svn-repo-url> --authors-file=authors.txt --stdlayout
# 清理SVN元数据
git filter-branch --tree-filter 'rm -rf .svn' -- --all
# 推送到Git仓库
git push --mirror https://gitlab.com/user/git-repo.git
2. 合并多个仓库
# 创建新仓库
mkdir super-repo && cd super-repo
git init
# 添加子项目A
git remote add projectA https://github.com/user/projectA.git
git fetch projectA
git merge projectA/main --allow-unrelated-histories
# 移动文件到子目录
mkdir -p projects/projectA
git mv * projects/projectA # 除了.gitignore等特殊文件
git commit -m "迁移 ProjectA"
# 重复添加其他子项目
四、迁移后的关键操作
1. 更新本地开发环境(团队通知模板)
**仓库迁移通知**
各位开发者:
我们的代码库已迁移到新位置:
新地址:https://new-git-host.com/team/repo
请按以下步骤更新本地环境:
1. **终端更新**:
```bash
git remote set-url origin https://new-git-host.com/team/repo
git fetch --all --prune
-
IDE设置更新:
- VS Code: 修改
.git/config文件 - IntelliJ: VCS > Git > Remotes 更新URL
- VS Code: 修改
-
CI/CD更新:
- 更新Jenkinsfile中的仓库地址
- 重新配置部署密钥
### 2. 钩子(hooks)迁移实践
```bash
# 从原仓库复制钩子
scp -r user@old-git-server:/repo/path/.git/hooks ./old-hooks
# 选择性迁移(如pre-commit, post-receive)
cp old-hooks/pre-commit .git/hooks/
chmod +x .git/hooks/pre-commit
# 测试钩子
git commit -m "测试迁移钩子"
3. 迁移后验证流程
-
完整性检查:
# 比较提交计数 git rev-list --count main > old-count.txt git clone https://new-host.com/repo.git cd repo git rev-list --count main > new-count.txt diff old-count.txt new-count.txt -
分支一致性检查:
# 获取全部引用对比 git ls-remote --heads https://old-host.com/repo > old-refs git ls-remote --heads https://new-host.com/repo > new-refs diff old-refs new-refs -
大文件验证:
# 检查LFS指针文件 git lfs ls-files # 验证实际文件 git lfs checkout md5sum large-file.dat
五、迁移工具推荐
| 工具 | 适用场景 | 优点 | 命令示例 |
|---|---|---|---|
| git clone --mirror | 简单完整迁移 | 保留所有元数据 | git push --mirror new-repo |
| git-lfs-migrate | LFS仓库迁移 | 自动重写历史 | git lfs migrate import --everything |
| SubGit | SVN到Git迁移 | 双向同步支持 | subgit configure repo.git |
| repo-sync | 多平台同步 | 增量同步 | repo-sync --source github --target gitlab |
使用git-lfs-migrate重写历史示例:
# 安装扩展
git lfs install
# 重写所有分支和标签
git lfs migrate export --everything --include="*.psd,*.zip"
# 推送到新仓库
git push --mirror https://new-host.com/repo.git
六、迁移中的避坑指南
1. 认证问题处理
# SSH密钥问题:
# 尝试:GIT_SSH_COMMAND="ssh -v" git fetch 查看详细错误
# HTTPS认证问题:
# 使用凭证助手
git config --global credential.helper store
# 特殊字符转义:
# 密码中有@符号时,使用百分比编码:password%40
2. 巨型仓库优化
# 浅层克隆加速
git clone --depth 1 https://large-repo.com
# 按日期筛选克隆
git clone --shallow-since="2023-01-01"
# 部分克隆(需要Git 2.22+)
git clone --filter=blob:limit=10m https://huge-repo.com
3. 不可变提交保留
# 查找签名提交
git log --show-signature
# 验证GPG签名
git verify-commit HEAD
# 迁移后重新验证
for commit in $(git rev-list --all); do git verify-commit $commit; done
小结
Git仓库迁移不仅是技术操作,更是项目维护的重要策略。成功的迁移应当:
- 零感知迁移:团队成员无需特殊操作
- 历史连续性:bug追溯不受影响
- 元数据完整:标签、分支保持原样
- 流程自动化:CI/CD无缝过渡
"一个好的迁移就像一次完美的搬家——所有物品到达新家时,不但完好无损,而且放在了最合理的位置。"
附录:各平台迁移文档