GitLab 代码仓库迁移与同步最佳实践
关键词:GitLab,Repository Mirror,Push Mirror,跨实例同步,CI/CD
背景
有两个独立的 GitLab 实例:
- 新仓库(主开发地址):
https://gitlab.new.xyz/group/project - 旧仓库(历史地址):
http://gitlab.old.xyz/group/project
未来所有开发和维护都在新仓库进行,但旧仓库因为历史问题还需要继续使用(如旧流水线、旧部署脚本仍指向旧地址)。
起初不知道有 Mirror 这功能,直接配置 gitlab.yml 来执行,发现存在很多不方便的地方,比如两个仓库的 gitlab runner 不同,仓库配置使用的 Gitlab 环境变量不同,一旦同步,gitlab pipeline 在旧的仓库也会触发,引起麻烦。
目标:新仓库 master 分支的每次提交,自动同步到旧仓库,不需要人工干预。
扩宽知识面,充分使用已有的完善的工具,避免重复造轮子、绕圈子,也是一个很好的习惯。
在工作中,如何实现功能、做成事情不是特别重要,只要结果目的达到。
但是如果过程能善假于物,借助成熟的方案,节省更多时间和精力的方案更值得推荐。
方案选型
有三种常见方案:
| 方案 | 触发时机 | 运维成本 | 前提条件 |
|---|---|---|---|
| GitLab Push Mirror(内置) | push 后即触发 | 极低 | 源实例支持 Mirror 功能 |
| CI/CD Pipeline 脚本推送 | push 后即触发 | 低 | Runner 可访问目标实例 |
| 定时 cron 脚本 | 分钟级延迟 | 中 | 有中间跳板机 |
最终选择 GitLab 内置的 Push Mirror,原因是配置一次之后完全托管,不需要维护额外脚本,也不依赖 Runner 的网络环境。
原理简介
GitLab 的 Repository Mirroring 分两种方向:
- Pull Mirror:从远端拉取到本仓库(目标仓库拉取源仓库)
- Push Mirror:本仓库有新提交时,主动推送到远端(源仓库推送到目标仓库)
本次使用 Push Mirror。每次向源仓库 push 代码,GitLab 会在后台自动执行一次 git push 到配置好的镜像地址,认证通过 Access Token 完成。
官方文档参考:Repository mirroring | GitLab Docs
配置步骤
第一步,获取原 GitLab 上的账号信息
方向一:
如果是旧版本的 Gitlab,可以直接先尝试使用登录的账号密码。
方向二:
通常情况下,登录 gitlab.old.xyz,进入目标项目,依次打开:
- Settings → Access Tokens
- 创建一个 Project Access Token,权限勾选
write_repository,记录生成的 token 值 - 也可以使用 Personal Access Token,效果相同。
第二步,在源 GitLab 上配置 Push Mirror
方向一:
使用账号密码,类似: http://username:password@gitlab.old.xyz/group/project.git,其他步骤同下。
方向二:
登录 gitlab.new.xyz,进入源项目,依次打开:
Settings → Repository → Mirroring repositories
点击 Add new,填写:
- Git repository URL,例如
http://<token_name>:<token>@gitlab.old.xyz/group/project.git - Authentication method - Username 和 Password(用于登录旧 Gitlab 的账号密码)
- 选择性勾选 Keep divergent refs 和 Mirror only protected branches
最后点击 mirror repository,GitLab 会立即触发一次同步,可以在列表里看到同步状态。
如果出现报错,可以看到 Error 信息,再根据报错排查问题。
第三步,验证
在源仓库随便推一个提交,然后去旧仓库刷新,确认提交已经同步过来。
同步一般在几秒到一分钟内完成,延迟取决于两个实例之间的网络情况。
旧仓库的后续处理
旧仓库变成纯镜像仓库后,不再需要任何协作功能,建议做以下关闭操作,避免有人误操作在旧仓库提交代码:
进入旧仓库:Settings → General → Visibility, project features, permissions
关闭以下功能:
- Merge requests,关闭后 MR 入口消失,无法再创建新的合并请求
- Issues(可选),旧仓库不需要 issue 跟踪
小结
整体方案很简单:源仓库配 Push Mirror,目标仓库关掉协作功能,一次配置,长期生效。
唯一需要注意的是,如果使用 token,那么 Access Token 的有效期,GitLab 默认 Token 可以设置过期时间,建议设置一个较长的有效期或者不过期,避免某天同步静默失败。