背景有两个独立的 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:passwordgitlab.old.xyz/group/project.git其他步骤同下。方向二登录gitlab.new.xyz进入源项目依次打开Settings → Repository → Mirroring repositories点击 Add new填写Git repository URL例如http://token_name:tokengitlab.old.xyz/group/project.gitAuthentication method - Username 和 Password用于登录旧 Gitlab 的账号密码选择性勾选 Keep divergent refs 和 Mirror only protected branches最后点击 mirror repositoryGitLab 会立即触发一次同步可以在列表里看到同步状态。如果出现报错可以看到 Error 信息再根据报错排查问题。第三步验证在源仓库随便推一个提交然后去旧仓库刷新确认提交已经同步过来。同步一般在几秒到一分钟内完成延迟取决于两个实例之间的网络情况。旧仓库的后续处理旧仓库变成纯镜像仓库后不再需要任何协作功能建议做以下关闭操作避免有人误操作在旧仓库提交代码进入旧仓库Settings → General → Visibility, project features, permissions关闭以下功能Merge requests关闭后 MR 入口消失无法再创建新的合并请求Issues可选旧仓库不需要 issue 跟踪小结整体方案很简单源仓库配 Push Mirror目标仓库关掉协作功能一次配置长期生效。唯一需要注意的是如果使用 token那么 Access Token 的有效期GitLab 默认 Token 可以设置过期时间建议设置一个较长的有效期或者不过期避免某天同步静默失败。