Git仓库无缝迁移

105 阅读5分钟

为什么需要仓库迁移?

在日常开发工作中,Git仓库迁移是一个常见但容易被忽视的关键任务。无论是从GitHub迁移到自建GitLab、SVN过渡到Git,还是在云服务提供商(如AWS CodeCommit)之间切换,合理的迁移策略可以:

  1. 保留完整项目历史(提交记录、分支、标签)
  2. 确保团队协作连续性
  3. 保留关键配置(钩子、忽略规则)
  4. 避免工作丢失和协作中断

本文将带您从基础到进阶,一步步掌握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
  1. IDE设置更新

    • VS Code: 修改.git/config文件
    • IntelliJ: VCS > Git > Remotes 更新URL
  2. 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. 迁移后验证流程

  1. 完整性检查

    # 比较提交计数
    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
    
  2. 分支一致性检查

    # 获取全部引用对比
    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
    
  3. 大文件验证

    # 检查LFS指针文件
    git lfs ls-files
    # 验证实际文件
    git lfs checkout
    md5sum large-file.dat
    

五、迁移工具推荐

工具适用场景优点命令示例
git clone --mirror简单完整迁移保留所有元数据git push --mirror new-repo
git-lfs-migrateLFS仓库迁移自动重写历史git lfs migrate import --everything
SubGitSVN到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仓库迁移不仅是技术操作,更是项目维护的重要策略。成功的迁移应当:

  1. 零感知迁移:团队成员无需特殊操作
  2. 历史连续性:bug追溯不受影响
  3. 元数据完整:标签、分支保持原样
  4. 流程自动化:CI/CD无缝过渡

"一个好的迁移就像一次完美的搬家——所有物品到达新家时,不但完好无损,而且放在了最合理的位置。"

附录:各平台迁移文档