从 GitLab 迁到 AngusGit:迁移清单、双跑和回滚

简介: 团队从 GitLab 整体切到 AngusGit,难的不是推送几个仓库,而是切换那天谁都不丢代码、出了问题能退回去。按准备、首次同步、双跑、切换日、回滚五个阶段,给出每一步要做什么、怎么验收,以及分支保护为什么要放在最后一次同步之后再打开。

这篇讲团队从 GitLab 整体切到 AngusGit 时,怎么保证切换那天不丢代码、出了问题能退回去。看完你可以按准备、首次同步、双跑、切换日、回滚五个阶段逐项验收,并给 GitLab 留两周只归档、不删除的回滚窗口。

先登录 AngusGit。GitLab 路径 platform/backend/order-service 只有两级可放:拿不准,或不同子组下有同名项目时,把子组并进仓库名,写成 platform/backend-order-service。仓库名里的点号改成连字符,例如 docs.site 改成 docs-site。在 设置 → 团队 点 新建团队,团队标识 沿用 GitLab 组的英文名。侧栏 仓库 → 新建仓库,添加 README 文件、添加 .gitignore、选择许可证 都不要勾,否则推送会被拒绝。

到 我的 → 访问令牌 点 生成新令牌,密码验证 填当前登录密码。同步脚本用一把勾了 git:write、仓库权限 WRITE 的令牌。Jenkins 只读拉代码另生成一把,只勾 git:read、仓库权限 READ。用户名都是 AngusGit 登录名,密码填令牌,生成后马上复制。先手动成功推一个仓库,在系统凭据窗口里保存,再跑脚本。

把对应关系写成 repos.txt,每行两列,先 GitLab 路径,再「所有者/仓库名」:

platform/backend/order-service platform/backend-order-service

然后执行(域名换成你的):

while read -r src dst; do
  git clone --bare "https://gitlab.example.com/${src}.git" tmp.git || continue
  git -C tmp.git branch -m master main 2>/dev/null
  git -C tmp.git push "https://git.anguskit.com/${dst}.git" --all
  git -C tmp.git push "https://git.anguskit.com/${dst}.git" --tags
  rm -rf tmp.git
done < repos.txt

每个仓库用下面的命令对比,没有意外输出才算一致。master 改成 main 时,这一对名字不同是预期的:

diff \
  <(git ls-remote --heads --tags https://gitlab.example.com/platform/backend/order-service.git | sort) \
  <(git ls-remote --heads --tags https://git.anguskit.com/platform/backend-order-service.git | sort)

分支保护要等切换日最后一次同步之后再开。进入仓库 设置 → 分支保护,点 添加规则,分支名称 选盘点表里的分支(通常是 main)。打开 需要代码评审,必需的评审人数 填 GitLab 上记下的人数;打开 对管理员同样生效;允许强制推送 和 允许删除 保持关闭。同步期间不要开,否则脚本推 main 会被拒绝。

准备、首次同步、双跑、切换日、两周回滚窗口

1. 这一轮只迁仓库

GitLab 上不只有代码,还有合并请求、议题、CI 流水线和各种集成。一次全部切走,任何一块出问题都会拖住整个迁移。建议分期:

期次 内容 说明
本轮 Git 仓库、成员权限、分支保护、Webhook 切换完成后,团队在 AngusGit 上提交、评审和合并
下一轮 CI 本轮先让现有构建能被 AngusGit 触发,下一轮再决定是否改写流水线
另行安排 议题、Wiki 这些在 GitLab 的数据库里,不在 Git 仓库中,推送带不过来

CI 虽然放到下一轮,切换日之前也必须有着落。GitLab 不再收到推送之后,GitLab CI 也就不会再触发。本轮最稳妥的过渡做法,是让现有的 Jenkins 任务改从 AngusGit 拉代码,并用 Jenkins 的 轮询 SCM(Poll SCM)定时检查 main 有没有新提交,例如每两分钟一次。不管代码是命令行推送进来的,还是在拉取请求页点合并进来的,轮询都能发现。Jenkins 拉代码用开头那把只读令牌:只勾 git:read,仓库权限 READ,用户名填登录名,密码填令牌。

2. 准备:先盘点

迁移前把下面每一项都查一遍,结果写进一张表。切换日的每一步都要用到它。

盘点项 在 GitLab 上怎么查 记下什么
仓库清单 各群组的项目列表 路径、可见性(谁能看到仓库)、默认分支名、大致大小,以及在 AngusGit 上对应的「团队/仓库名」
成员和角色 群组和项目的 成员 页 每个人在每个仓库要读还是要写,谁是维护者
受保护分支 项目 设置 → 仓库 → 受保护分支 哪些分支禁止直接推送、合并前要几个人批准
CI 项目里的 .gitlab-ci.yml 和 Runner 哪些仓库有构建;切换后用什么触发
Webhook 和集成 项目 设置 → Webhooks 每个 Webhook 的地址和用途,切换后要在 AngusGit 上重建
写死 Git 地址的地方 在代码里搜索 GitLab 域名 .gitmodules、CI 和部署脚本、依赖声明里的 Git 地址、文档里的克隆命令
进行中的合并请求 每个项目的 合并请求 列表 切换日之前要合并或关闭,评审记录带不过来
Git LFS 项目里有没有 .gitattributes 中的 filter=lfs AngusGit 不支持 LFS,用到的仓库要先处理大文件

盘点表里「写死 Git 地址的地方」最容易漏。部署脚本、子模块、依赖声明里还写着 GitLab 地址,切换之后不会马上报错,要等 GitLab 下线那天才一起出问题。

3. 首次同步

  1. 在 AngusGit 建团队和空仓库

    按盘点表的对应关系,建好团队和空仓库。新建仓库时三个初始化选项都不勾。

  2. 成员先只给读权限

    把成员加进团队或仓库,这个阶段一律只给读取权限。双跑期间,AngusGit 上的代码只能从 GitLab 同步过来,不能有人直接往 AngusGit 推送;只给读权限,就从权限上保证了这一点。

  3. 分支保护先不开

    同步脚本会直接把分支推到 AngusGit,包括 main。这时如果已经给 main 开了分支保护,同步推送会被拒绝。分支保护规则可以先整理好,等到切换日最后一次同步之后再建。

  4. 跑一次同步脚本,然后验收

    执行同步脚本,把 repos.txt 里的仓库全部推过去。每个仓库都用开头的 git ls-remote --heads --tags 对比 GitLab 和 AngusGit,没有意外输出才算同步成功。master 改成 main 时,这一对名字不同是预期的。

4. 双跑:GitLab 写,AngusGit 读

双跑期间,团队照常在 GitLab 上提交、评审、合并。AngusGit 每天从 GitLab 同步一次,让团队提前熟悉新地址和新界面。

双跑只有一条规则:任何时候只有一边能写。两边都能写,代码就会分叉。分叉之后,同步推送会被拒绝,最后只能手工合并,这正是迁移最怕的情况。

这段时间可以做这些事:

  • 用定时任务每天执行一次同步脚本,每次跑完都用 git ls-remote 对比一遍。
  • 请几位成员从 AngusGit clone 仓库,确认 SSH 或 HTTPS 访问都没问题,访问令牌都已备好。
  • 在一个测试仓库里,让大家把拉取请求、评审、合并完整走一遍。
  • 新建一个测试用的 Jenkins 任务,从 AngusGit 拉代码、打开轮询 SCM,确认它能发现同步过来的新提交并开始构建。

开发者只向 GitLab 推送,AngusGit 每天单向同步、只读

5. 切换日

切换日按下面的顺序做,每一步做完再做下一步。

  1. 提前通知冻结时间

    至少提前一天通知全员:几点开始停止向 GitLab 推送,几点之后改用 AngusGit。进行中的合并请求,要在冻结之前合并或关闭。

  2. 冻结 GitLab

    到点后,把每个项目在 GitLab 上归档(项目 设置 → 通用 → 高级 → 归档项目)。归档后项目变成只读,任何人都推不上去,代码和合并请求记录都还在。

  3. 最后一次同步并对比

    执行同步脚本,然后对每个仓库跑一遍 git ls-remote 对比。全部一致才往下走;有不一致的,先查清楚是哪个分支、为什么。

  4. 打开 AngusGit 的写权限和分支保护

    按盘点表把成员的权限从只读改成读写,再在每个仓库的 设置 → 分支保护 里按开头添加规则:打开 需要代码评审 并填上盘点的人数,打开 对管理员同样生效,允许强制推送 和 允许删除 保持关闭。

  5. 切换 CI 和集成

    把 Jenkins 任务的源码地址改成 AngusGit,打开轮询 SCM,再推一个测试提交,确认构建被触发。盘点表里的其他 Webhook,在 AngusGit 仓库的 设置 → Webhooks 里重建。

  6. 通知全员改地址

    每个人在自己的本地仓库里执行一次 git remote set-url origin <AngusGit 地址>,然后 git fetch 确认能拉取。双跑期间直接从 AngusGit clone 的人,不需要改。

切换日结束前,还要按盘点表把写死 GitLab 地址的地方,逐个改成 AngusGit 地址并提交。

6. 回滚

GitLab 上的项目只归档,不删除。从切换日起留一个回滚窗口,例如两周。窗口内如果遇到无法马上解决的问题,例如权限大面积出错、构建全部断掉,可以退回 GitLab。

回滚时,AngusGit 上已经有了切换后的新提交,要先把它们带回 GitLab:

  1. 冻结 AngusGit

    通知全员停止向 AngusGit 推送,把成员权限改回只读。

  2. 取消 GitLab 归档

    GitLab 上归档的项目拒绝推送,先在项目 设置 → 通用 → 高级 里取消归档。

  3. 把新提交推回 GitLab

    迁移时把 master 改成了 main 的,先把它改回 master;GitLab 在冻结之后没有新提交,这次推送是普通的追加,不需要强制推送。

  4. 对比后通知全员改回地址

    用 git ls-remote 对比两边一致后,通知全员把 origin 改回 GitLab 地址,CI 也切回 GitLab。

回滚时用 git clone --bare 得到一份只存 Git 数据、没有可编辑工作区的副本,再推回 GitLab:

git clone --bare https://git.anguskit.com/platform/backend-order-service.git
cd backend-order-service.git
git branch -m main master
git push https://gitlab.example.com/platform/backend/order-service.git --all
git push https://gitlab.example.com/platform/backend/order-service.git --tags

回滚窗口结束、确认不再需要 GitLab 之后,再按公司的数据保留要求处理 GitLab 上的项目。

7. 出错时

你看到的 原因 怎么处理
双跑期间同步推送 main 被拒绝 AngusGit 上已经给 main 开了分支保护 先删掉这条保护规则,等切换日最后一次同步之后再建
同步推送 ! [rejected] … (non-fast-forward) 有人在双跑期间直接往 AngusGit 推了代码,两边分叉 找到这条提交,确认是否需要保留。要保留的,在 GitLab 上重新提交一次;然后把 AngusGit 上的分支重置成 GitLab 的版本。同时检查成员权限是否真的只读
切换日对比有差异 冻结之前有推送没赶上同步,或者同步中途断开 再执行一次同步脚本,直到对比一致
切换后部分构建不再触发 Jenkins 任务的源码地址还是 GitLab,或者没打开轮询 SCM;构建脚本里还写着 GitLab 地址 对照盘点表逐个改 Jenkins 任务和脚本里的地址
切换后有人推送报 repository '…' not found 本地 origin 改错了,团队名或仓库名和对应规则不一致 从 AngusGit 仓库页的 代码 按钮复制地址,重新 git remote set-url

常见问题

能不能让 GitLab 和 AngusGit 一直双向同步,慢慢切?

不建议。两边都能写,就一定会在某个时候分叉。分叉后由谁来合并、以哪边为准,都很难说清。双跑期间只保留一个写入方,切换就是一个明确的时间点。

几十个仓库要一天切完吗?

不必。可以按团队或业务线分批,每批走一遍第 5 节。但同一批里互相依赖的仓库,例如主仓库和它的子模块,要放在同一天切。

合并请求的讨论记录怎么办?

带不过来。重要的设计讨论,在 GitLab 归档前导出或整理成文档,放进仓库的 docs 目录;进行中的合并请求,冻结前合并或关闭。

切换后,CI 什么时候迁?

本轮先让 Jenkins 改从 AngusGit 拉代码,现有构建继续工作,等团队适应了新的仓库和评审流程,再单独安排一轮评估。AngusGit 团队版和企业版自带流水线,新建流水线时可以选 导入 GitLab CI,从 .gitlab-ci.yml 生成初稿。社区版没有 CI/CD 菜单。

小结

从 GitLab 迁到 AngusGit,本轮只迁仓库,CI 和议题另排。先盘点仓库、成员、受保护分支、CI、Webhook 和写死 Git 地址的地方。首次同步之后进入双跑:GitLab 是唯一能写的一边,AngusGit 只读、每日同步。切换日按顺序做:冻结 GitLab,最后同步,对比一致,然后打开写权限和分支保护,切换 CI,通知全员改地址。GitLab 项目只归档不删除,回滚窗口内需要退回时,把 AngusGit 的新提交推回 GitLab,再取消归档。

结论: 批量迁移期间必须保持「单边可写」:双跑期只写 GitLab、每日单向同步到只读的 AngusGit;切换日先归档冻结 GitLab 并用 git ls-remote 对齐全部引用后,再开启 AngusGit 的写权限与分支保护。

参考文章

相关文章
|
16天前
|
缓存 资源调度 运维
npm 私服怎么搭:从安装到配源、scope 和 publish
私有化部署后接 npm:建 HOSTED/PROXY/GROUP,配 .npmrc 与 scope,用最小包跑通 publish/install,并处理 E401、E404、E409。
|
14天前
|
缓存 Java 数据库
AngusRepo 缓存架构设计与实践
制品仓库要同时保住权限、覆盖写和多进程一致。本文说明 AngusRepo 如何划分缓存层次、用版本号表达失效,以及单节点与多实例如何共用同一套模型。
AngusRepo 缓存架构设计与实践
|
16天前
|
供应链 安全 数据挖掘
制品入库怎么拦住漏洞和许可证问题
上传不等于扫过。对接 AngusSecurity 后由平台跑 SCA,Repo 负责策略触发与「未通过时拒绝下载」;给出集成步骤、能力对照、灰度验证与翻车表。
|
Java Maven Docker
一套制品库接入 28 种格式:Maven、Docker、npm、PyPI、Helm 实战指南
在同一套 AngusRepo 服务中,为 Maven、Docker、npm、PyPI 等 10 种格式完成认证、发布和拉取。
一套制品库接入 28 种格式:Maven、Docker、npm、PyPI、Helm 实战指南
|
10天前
|
JSON 供应链 安全
按能力出报告:SAST、组件、镜像、密钥和许可证
同一份「全能力」报告太厚:研发只想看代码路径,供应链只想看 CVE,合规只要许可证例外——这时不要再开五种互不相干的导出工具,而是在同一套报告快照上按能力收窄。
|
10天前
|
存储 缓存 资源调度
云上免费 npm 私有源怎么起步:从发包到公开分发
不想自建服务器时,用 AngusRepo 云服务托管私有 npm:统一源安装、HOSTED 发布,对外用公开浏览页复制匿名安装命令。
|
10天前
|
缓存 安全 数据安全/隐私保护
云上免费 Docker 镜像仓怎么起步:推送、拉取与公开浏览
用 AngusRepo 云服务托管私有镜像:login 后推送到 HOSTED,按需拉取;对外用公开浏览页匿名 pull。
|
10天前
|
安全 开发工具 Docker
私有仓制品怎么公开下载:/explore 匿名安装命令
合作方 npm install 401、又不愿发令牌时:在 AngusRepo(repo.anguskit.com)把交付 HOSTED 标 isPublic,用 /explore 匿名搜索并复制安装命令。
|
10天前
|
缓存 资源调度 网络协议
国内访问 npmjs 不稳怎么办:改走团队统一源做缓存
`npm install` 卡在 `registry.npmjs.org`,日志里是超时、`ECONNRESET`,偶发还有 TLS 握手失败或上游 502
|
10天前
|
人工智能 缓存 安全
用 AI 助手只读查制品库:AngusRepo MCP 怎么接入
Coding Agent 要在对话里问「这个坐标在哪个仓、依赖和漏洞计数是什么」,并不需要把 mvn npm docker 搬进模型上下文。AngusRepo 把这条能力做成进程内的 MCP 只读端点:宿主连上之后调用具名工具,服务端回环本进程管理 API,返回元数据投影。