☰
GitLab跨环境迁移完整指南:从项目导出到备份恢复
2026/10/8 2:28:55 网站建设 项目流程

做代码迁移这件事,我一直觉得最考验人的不是 Git 命令本身,而是“你根本不知道哪些东西需要搬”。GitLab 在不同环境之间搬代码,表面上就是 clone 和 push 两行命令的事,但真正操作起来你会发现:分支、标签、MR 评审记录、CI/CD 变量、Runner 绑定、Webhook、LFS 对象、甚至仓库的可见性设置,每一个都是独立的坑。我见过太多团队,测试环境跑得好好的代码,往生产环境一迁就“丢三落四”,最后排查半天发现是 MR 历史没带过去,或者 Runner 根本没注册到新实例上。

这篇东西想把我做 GitLab 跨环境迁移的经验完整梳理一遍,覆盖从“单项目搬运”到“整个服务器搬迁”的几种主流方案,包括原生导出导入、Mirror 镜像推送、备份恢复,以及迁移之后的权限恢复、CI/CD 重新接线这些必修课。无论你的场景是从测试环境迁到生产环境、从旧服务器换到新服务器,还是想把代码同步到另一套 GitLab,这篇文章应该都能给你一个可以直接照做的路径。

1. 动工之前,先把“迁移对象”和“迁移方案”盘清楚

1.1 代码迁移不只是代码,你需要搬的东西比想象中多

不同环境间的 GitLab 代码迁移,很多人的第一反应是git clone然后git push,完事。但如果你的团队真的用 GitLab 协作,而不是只把它当个远程存储,那你会发现这套流程漏掉的东西非常多。我简单列一下要确认的清单:

  • 仓库数据本身:所有分支、Tag、提交历史、Commit 签名。
  • Merge Request 和评审记录:MR 里的评论、讨论、Approval 记录、关联的 Issue。这个在原生导出导入里能带走,但用 git clone 方式会全部丢失。
  • CI/CD 配置:.gitlab-ci.yml在仓库里,但 CI/CD Variables、环境 Scope、Runner 绑定关系都不在仓库里,需要单独处理。
  • 权限模型:项目成员、组成员、角色等级、可见性设置。
  • 集成配置:Webhook、Slack 通知、外部集成。
  • 附属数据:Wiki、Issue、Milestone、Container Registry 的镜像、以及 LFS 对象。

这些内容里面,代码本身是最容易搬的,难的是背后那一圈配套数据。我建议在动手之前,先拿一张纸把上面这些项目列出来,确认哪些是你这次迁移必须保留的,哪些可以放弃。比如一个从零开始的演示环境,可能根本不需要带 MR 历史,但生产环境迁移的时候,这些审计记录往往一个都不能少。

1.2 四条路线怎么选:按目标和场景对号入座

根据“要搬的东西有多少”和“新旧环境的关系”,我一般会把迁移方案分成四类,在实际项目里可以组合使用:

方案适合场景迁移内容操作成本主要局限性
GitLab 原生组/项目导出导入单项目或单组从实例 A 迁到实例 B,且需要保留 MR、Issue、Wiki项目数据全量打包中等大仓库导出耗时;跨大版本可能不兼容
git clone --mirror+git push --mirror只关心代码、分支和标签,不要求 MR/Issue代码、分支、Tag、历史低丢失 MR、CI/CD 配置、权限、Wiki
服务器级备份恢复整个 GitLab 实例搬迁,连用户、组、Runner 配置都要保留整套实例数据高新旧版本必须一致;恢复时间长
配置 Repository Mirroring 持续同步两个环境长期保持代码同步,比如测试和生产常驻同步仅分支和 Tag 的增量同步低单向或双向同步策略需要提前规划

四条路线不互斥,我做过最多的组合是“备份恢复搭底、项目导出导入做单仓库修正、Mirror 做后续增量同步”。你先判断这次迁移是一次性的还是长期的,是一次性就选导出导入或备份恢复,是长期同步就直接上 Mirror。方案没有绝对的好坏,只有适不适合当前环境。

2. GitLab 原生导出导入:全家桶式搬运,最稳妥的一招

2.1 版本兼容性检查:先看版本号,再决定能不能直接导

GitLab 的导出导入功能经历了多次底层重构,最让人头疼的就是版本兼容性。官方对导出版本和导入版本的建议是:导入方 GitLab 版本不能低于导出方,最好保持大版本一致。举个例子,旧实例是 GitLab 15.11,新实例建议至少也是 15.11,不要拿 14.x 的导出包直接往 16.x 新版里导。如果你要跨大版本迁移,比如从 13 跳到 16,强烈建议先在旧实例上原地升级到 14 以上,再执行导出。因为 GitLab 14 之前的导出包结构和 14 之后有差异,很多字段会丢失。

这里还有个非常现实的兼容性问题:新版 IDE 工具(比如 IntelliJ IDEA、PyCharm 的 GitLab 插件)对 GitLab 版本有硬性要求,低于 14.0 的实例会直接提示gitlab versions older than 14.0 are not supported。所以如果旧环境还停留在老版本,迁移到新环境本身就是一次顺手升级,我把 14.0 当作最低底线来规划。

另外要确认导出账号的权限。导出项目需要Maintainer 及以上角色,导出组需要Owner 角色。如果账号权限不够,导出按钮可能直接是灰的。

2.2 项目导出的操作路径与后台任务逻辑

在 GitLab 界面上导出单个项目,路径是这样的:进入项目 →Settings→General→ 拉到最底部Advanced→ 找到Export project→ 点击Export now。

点击之后 GitLab 不会立刻给你下载链接,而是把导出任务扔到后台。导出的文件会打包成*.tar.gz,里面包含项目仓库、Wiki、Issue、MR、CI/CD 配置等几乎全部数据。导出完成后,同一位置会变成Download export按钮,或者通过邮件收到通知。对于中小型仓库,这个过程可能几分钟就好;但如果你仓库里有几十 GB 的 LFS 对象、大文件,后台任务跑几十分钟甚至几小时都很正常。

如果仓库数量多,建议直接用 API 批量触发,比在界面上一个个点人省事:

# 触发导出任务 curl --request POST --header "PRIVATE-TOKEN: <个人访问令牌>" \ "https://gitlab.old.example.com/api/v4/projects/<project_id>/export" # 轮询导出状态,若导出完成,返回结果里的 export_status 字段是 finished curl --request GET --header "PRIVATE-TOKEN: <个人访问令牌>" \ "https://gitlab.old.example.com/api/v4/projects/<project_id>/export" # 下载导出包 curl --request GET --header "PRIVATE-TOKEN: <个人访问令牌>" \ --output "project_export.tar.gz" \ "https://gitlab.old.example.com/api/v4/projects/<project_id>/export/download"

个人访问令牌(Personal Access Token)在用户设置 → Access Tokens 里创建,权限至少勾上api和read_repository。这是所有自动化操作的前提,我后面所有 API 调用都依赖这个令牌。

2.3 导入项目:界面操作与 API 姿势

在新实例上导入导出的项目,界面路径:顶部New project→Import project→ 选择GitLab export→ 上传tar.gz文件 → 填目标路径和项目名。

如果用 API 批量导入,可以这样:

curl --request POST --header "PRIVATE-TOKEN: <新实例的令牌>" \ --form "path=target_group" \ --form "file=@project_export.tar.gz" \ "https://gitlab.new.example.com/api/v4/projects/import"

导入过程同样是异步的,可以轮询/api/v4/projects/import状态。需要注意几个细节:

  • 如果目标路径的 Group 不存在,导入会失败,需要提前建好组。
  • 导入后项目名称、项目路径都可以改,不会影响代码数据。
  • 原项目里的成员关系默认不会自动映射,除非新旧实例都接了同一个 LDAP 或者 SSO,否则导入后统一默认只有执行导入的账号是 Owner。

我自己用这套方案做过一次生产环境迁移,200 多个项目、500 多个 MR 历史全部完整带过去了。整体感受是“慢但全”,最耗时的环节是后台任务排队的等待,而不是操作本身的复杂度。

3. Mirror 镜像推送:只要代码干净,这是最快的搬运方式

3.1 为什么用--mirror而不是普通 clone

很多人搬仓库用git clone --bare再git push --mirror,其实这里关键点在于mirror 模式会把所有 refs(分支、Tag、远程跟踪分支)完整映射过去,包括那些本地还没拉取的远端引用。好处是目标仓库和源仓库的引用结构完全一致,不丢分支也不丢标签。

我用这套方案迁移过好几个仓库,基本步骤固定为:

# 1. 在旧环境上做镜像克隆 git clone --mirror git@gitlab.old.example.com:group/project.git # 2. 进入裸仓库目录 cd project.git # 3. 在新环境的目标仓库上做镜像推送 git push --mirror git@gitlab.new.example.com:group/project.git # 4. 校验远端引用是否完整 git ls-remote git@gitlab.new.example.com:group/project.git

执行完第三步之后,新仓库里的分支和 Tag 理论上和旧仓库完全一致。速度上比导出导入快很多,因为整个过程就是标准的 Git 数据传输,没有后台打包、文件上传这些环节。

3.2 文件都搬过去了,LFS 对象别落下

如果项目里用了 Git LFS,git push --mirror只会把 LFS 指针(pointer)推过去,真正的 LFS 文件对象不会跟着走。新环境里的人拉下来会看到一堆指向文件的引用,但检出时会报错说对象缺失。解决办法是在 push 之前先把所有 LFS 对象拉全,再推到新环境:

# 拉取所有 LFS 对象 git lfs fetchall --all # 推送 LFS 对象到新远端 git lfs push --all git@gitlab.new.example.com:group/project.git

顺序上一定要先fetchall再push,如果跳过 fetchall 直接把空对象目录推到新环境,那更麻烦。这里我吃过一次亏,后果是生产环境上某个二进制资源文件彻底拿不回来,最后回到旧实例重新拉一遍才解决。

3.3 这套方案丢了什么:明确边界,别等上线后才发现

Mirror 方式被很多人诟病,主要是因为它“只搬代码”。MR 的讨论记录、Issue、CI/CD 配置、成员权限、Webhook,全部不在这个流程里。所以要合理评估自己的场景:

  • 可以接受:只做演示环境、临时环境、或者单向代码同步。
  • 不太建议:正式的生产环境整体搬迁,除非你能把 MR 和 Issue 全部放弃,并且后续靠代码注释和 Commit Message 自解释。

另外,如果你用了Repository Mirroring 功能(GitLab 自带的镜像同步),要注意它有强制覆盖(force update)和保留差异分支(keep divergent refs)两个选项。默认强制覆盖意味着目标端那些“本地提交但没有推回源端”的分支会被直接覆盖掉,多个环境并行开发的团队最好勾上“Keep divergent refs”,否则别人在新环境上的未推送提交可能会被静默冲掉。

4. 服务器级备份恢复:连用户、Runner 和全局配置一起“抄家”

4.1 什么场景才需要走到这一层

我在前文说的导出导入,核心是“项目维度”的搬迁;但如果你遇到的是换服务器、换自建机房、或者从 docker 单机实例迁移到另一台 docker 单机实例,而且希望新环境一上来就和旧环境长得一模一样,包括所有用户账号、SSH Key、Runner 注册状态、甚至审计日志,那就得用 GitLab 自带的备份恢复功能。

GitLab 备份和项目导出最大的区别在于:备份是针对整个实例的,包含所有项目、所有用户、所有组的元数据;项目导出只是单个项目的打包。备份恢复适合“整体搬家”,项目导出适合“挑几个项目搬过去”。如果新环境只是部分项目需要迁移,用备份恢复反而杀鸡用牛刀。

4.2 备份与恢复的完整命令链路

先备份旧实例。我用的命令如下(不同版本命令略有差异,GitLab 12.4 以后推荐gitlab-backup):

# 在旧服务器上创建完整备份 sudo gitlab-backup create

备份默认存储在/var/opt/gitlab/backups目录下,文件名类似1691234567_2023_08_05_16.5.0_gitlab_backup.tar,前面的时间戳是备份序号。如果你是用 docker 方式部署的 GitLab,备份流程也是一样,只是命令要在容器里面执行:

docker exec -t <容器名> gitlab-backup create

然后把这个 tar 包复制到新服务器上(scp/rsync/挂载盘都行)。这里我得强调一个血泪教训:备份文件里的版本号必须和新实例的 GitLab 版本一致或非常接近,比如旧实例是 16.5.0,新实例最好也装 16.5.x。差一个小版本问题还能扛,差一个大版本直接 restore 失败。所以做整体迁移时,我的套路是先在新服务器上安装和旧实例相同版本的 GitLab,恢复成功后再考虑升级。

新服务器上恢复的流程:

# 把备份包放到正确目录,并确保权限和属主是 git 用户 sudo cp 1691234567_2023_08_05_16.5.0_gitlab_backup.tar /var/opt/gitlab/backups/ sudo chown git.git /var/opt/gitlab/backups/*.tar # 停掉相关服务,避免恢复过程中有数据写入 sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq # 执行恢复,BACKUP 后面不要带 .tar 后缀 sudo gitlab-backup restore BACKUP=1691234567_2023_08_05_16.5.0 # 恢复完成,重新配置并启动 sudo gitlab-ctl reconfigure sudo gitlab-ctl restart

恢复期间 GitLab 会提示这个操作会覆盖当前所有数据,确认无误后继续。整个恢复过程根据数据量大小可能耗时很长,我恢复过一个接近 40GB 的实例,光还原数据就花了 50 分钟。

4.3 配置文件两次“迁移”的坑:忘了它等于前功尽弃

备份恢复里最容易忽略、但最致命的是/etc/gitlab/gitlab.rb和/etc/gitlab/gitlab-secrets.json。前者是 GitLab 的配置文件,包含域名、SMTP、LDAP 配置;后者是各种加密密钥、OTP 密钥、Runner 注册密钥,它一旦和新环境不一致,恢复后项目 clone 链接里的密码会解析失败、用户 2FA 会被重置、甚至 Runner 全部失联。

所以完整的服务器迁移步骤应该是:

  1. 打包备份:tar备份数据 + 拷贝/etc/gitlab/gitlab.rb+ 拷贝/etc/gitlab/gitlab-secrets.json
  2. 在新实例上安装相同版本的 GitLab
  3. 用旧配置文件覆盖新配置文件(注意域名如果变了要改 External URL)
  4. 执行sudo gitlab-ctl reconfigure让新实例按旧配置重新生成服务
  5. 最后再恢复备份数据

顺序不能乱,而且gitlab-secrets.json的优先级极高。我有一次图省事没有同步这个文件,恢复完成后一票项目的 HTTP 访问权限全部异常,排查了半天才发现是这个原因。那次之后,我养成了个习惯:配置文件永远和数据备份一起打包,文件名前缀都保持一致。

5. 搬迁后的接线时刻:权限、CI/CD 变量与 Runner 的重新对焦

5.1 用户与权限映射:为什么一导入成员全没了

不管是项目导出导入还是备份恢复,都会遇到用户映射问题。备份恢复因为整库还原,用户数据本身就在里面,一般不存在这个问题;但项目导出导入迁移到新实例后,新实例上可能压根没有“张三”“李四”这些账号。就算有,GitLab 也不会自动把旧的 author 或 assignee 对应到同名新账号。

处理权限映射我常用的有三种思路,看你们公司基础设施选:

  • LDAP/SSO 统一认证:新旧实例都接了同一个 LDAP 或 SAML SSO,导入后 GitLab 能按用户的外部身份自动关联,这是最省事的方案。
  • 管理员手动重新添加成员:在新实例上把迁移项目的 Owner/Maintainer/Developer 重新加一遍。适合项目数量少、人员结构固定的团队。
  • 批量脚本同步:从旧实例通过 API 拉出每个项目的成员列表,再到新实例调用/api/v4/projects/:id/members批量添加。项目多的时候我用这个方案,比手动加靠谱得多。脚本核心逻辑就是两层循环:遍历项目、遍历成员,角色字符串直接映射过去。

顺带提醒一句:导入项目的可见性默认继承导入者的权限。如果原来的项目是 Private,导入完记得检查新实例上的可见性设置,防止因为默认设置导致代码仓库变成了 Internal 甚至 Public。这个坑我在测试环境踩过,好在发现得早,没有造成实际泄露。

5.2 CI/CD 变量和 Runner 绑定关系:代码仓库里没有的东西

.gitlab-ci.yml是跟着仓库走的,导出导入能带过去;但CI/CD Variables(项目变量、组变量)、Environment Scope、以及 Runner 与项目的绑定关系,在项目导出包里是没有的。迁移之后如果不重新配置,流水线要么因为变量缺失直接失败,要么因为找不到可用的 Runner 一直卡在 pending。

CI/CD Variables 这块没有批量迁移的官方接口,我的做法是:

  1. 在旧实例上用 API 拉出所有项目变量:GET /api/v4/projects/:id/variables
  2. 写脚本把变量逐个 POST 到新实例
  3. 注意变量的类型(Variable Type: Variable / File)、环境作用域(Environment Scope)、是否 Protected、是否 Masked,这些属性在 API 里都有对应字段,别只拷贝 value 就收工

Runner 注册这块,新版本的 GitLab 改动比较大。GitLab 16.0 之后已经取消了项目 Runner 注册令牌(registration token)这个说法,你直接在目标实例的Settings → CI/CD → Runners页面创建 Runner 认证令牌(authentication token),然后在旧实例上用的 Runner 机器上重新注册一遍即可:

gitlab-runner register \ --non-interactive \ --url https://gitlab.new.example.com \ --token <新实例自动生成的runner认证令牌> \ --executor docker \ --docker-image alpine:latest \ --description "migrated-runner"

Runner 绑定完成后别急着跑流水线,先手动触发一次流水线验证执行环境。我之前遇到过一种情况:Runner 注册成功了,但 executor 类型从旧的生产机shell变成了docker,导致脚本里面依赖宿主机环境的命令全部报错。这种问题光看注册状态是发现不了的。

5.3 Webhook、容器镜像和全局设置的补齐项

权限和 CI/CD 搞定之后,再做一轮“外围设备”排查:

  • Webhook:从旧实例项目设置里把 Webhook 列表拍下来,再到新实例重新添加。其实 GitHub 的 Webhook 有密钥签名,GitLab 也有类似的 Secret Token,迁移后这些密钥一般没法自动同步,需要重新生成或手工配置。
  • Container Registry:如果项目里有 Docker 镜像推送记录,这些镜像不在导出包里。整体备份恢复时仓库镜像能跟着走,但单项目导出导入不行。要迁移镜像就用脚本把旧 registry 里的镜像 pull 下来再 push 到新的 registry,或者直接用skopeo copy批量同步,速度比 docker pull/push 快不少。
  • 全局设置:比如是否允许创建新项目、是否开启注册开关、外发邮件设置。这些都在 Admin 区域里,迁移后根据新环境的定位(内网测试 or 生产)手动确认一遍。

迁移完成后的验证环节也非常重要。我的习惯是派一个完全不知道本次迁移背景的同事(或者最重要的几个核心用户),让他们在新环境上正常走一遍流程:克隆、提 MR、跑流水线、部署到测试环境。如果他们全程没有感觉到异常,那这次迁移基本算是成功了。

6. 我踩过的那些坑:版本代差、大仓库超时、LFS 丢失

6.1 版本代差导致的导入失败与编译警告

从热词里也能看出来,很多人卡在版本兼容上:GitLab 14.0 之前的实例,不仅新版 IDE 不支持,导出包导入到新版本也可能出现字段解析异常。我处理过一次比较典型的:旧实例停在 GitLab 13.7,新实例已经升到了 15.10。导出之后导入到一半直接报“导入失败”,日志里提示存在不兼容的ci_runner数据。查了一下,旧版本导出包里包含的 Runner 配置格式在 15.x 里已经完全变了。

这类问题没有特别优雅的办法,我的处理路线是:

  1. 在旧实例上先做“小步升级”,比如 13.7 → 13.12 → 14.10 → 15.0 → 15.10,每一步都跑一遍备份和验证。
  2. 全部升完再执行导出导入。
  3. 导入后如果还有零星报错,接受局部数据丢失(比如某个老 Runner 绑定),手动在新实例上重新补配置。

这种小步升级老实例的方式,其实也顺便把之前 GitLab 高危漏洞的修复方案落了地。老版本不升不修,漏洞就一直悬着;借迁移这个机会一口气把版本补丁打满,属于顺手做安全加固。

6.2 大仓库导致 export 超时或下载卡顿

项目仓库超过几个 GB,导出任务很容易卡在后台队列里。GitLab 的导出逻辑是先把 Git 仓库打包,再打包附属数据,期间对内存和磁盘 IO 都有压力。我遇到过一次 20GB 的仓库,等了两个小时还没完成,最后还是去服务器上看日志,发现导出任务因为临时目录空间不足死掉了。

大仓库迁移前建议先做一次仓库瘦身:

# 清理已经合并但还留在大分支里的历史引用 git remote prune origin git gc --prune=now --aggressive

如果确实不想清理历史,则注意两个操作细节:导出时在界面上勾选Include Git LFS objects;导出任务期间不要让 GitLab 实例处于高负载状态,最好在业务低峰期执行。下载导出包时也要留意 HTTP 超时时间,服务器反向代理(Nginx)的proxy_read_timeout默认可能只有 60 秒,大包下载稍微一慢就断。我的解决办法是用wget -c断点续传,或者直接到服务器上用scp拷贝临时文件。

6.3 LFS 对象丢失:最容易“表面成功、实际失败”的一环

Git LFS 对象的丢失是我见过最多的隐性迁移故障。表面上看仓库路径、分支结构全都在,但一旦有人 checkout 到历史版本或拉取大文件,就开始报错。项目导出导入时,如果导出界面上“Include Git LFS objects”没勾选,导出包可能只有几十 MB,但 Git 仓库在正常文件外还有一大堆 LFS 指针等着回源,这些对象一个都没带走。

我自己现在做 LFS 迁移会固定加两步验证:

# 检查本地LFS对象是否齐全 git lfs fsck --all # 查看远端是否有遗漏 git lfs ls-files --all

这两条命令都能在迁移完成后发现问题,而且报错信息很清楚。另外 LFS 对象的存储位置在 GitLab 默认的/var/opt/gitlab/git-lfs/objects,如果是用备份恢复整个实例,这一目录是自动包含在备份里的,反而不用担心太多,主要还是单项目导出导入时容易疏忽。

6.4 自动化与持续同步:迁移不是终点,同步才是常态

如果测试环境和生产环境之间的代码同步是持续性的需求,我不建议每次手动走一遍导出导入。GitLab 原生支持 Repository Mirroring,在项目设置里配置好源和目标仓库地址,就能定期或事件触发式地把分支和 Tag 增量同步过去。

配置路径:Settings → Repository → Mirroring repositories,填目标 GitLab 仓库地址和认证方式,选择Push方向,勾选需要的选项。Mirror 默认会覆盖目标端与源端有差异的分支,配置时如果目标是“两个环境并行开发,只是定期双向校对”,记得勾上Keep divergent refs。

对于整个组的持续同步,我的做法是写一个脚本,遍历组的项目列表,分别拉取存在或不存在的 Mirror URL,批量通过 API 添加 Mirror 配置。核心请求就是:

# 获取组内所有项目 curl --header "PRIVATE-TOKEN: <令牌>" \ "https://gitlab.old.example.com/api/v4/groups/<group_id>/projects?per_page=100" # 对每个项目设置 push mirror curl --request POST --header "PRIVATE-TOKEN: <新实例令牌>" \ --form "url=git@gitlab.new.example.com:group/project.git" \ --form "enabled=true" \ --form "keep_divergent_refs=true" \ "https://gitlab.old.example.com/api/v4/projects/<project_id>/remote_mirrors"

这类脚本跑完以后,日常的代码同步就不再需要人为介入了,环境间的差异维持在“上次 mirror 触发的时间点”附近。要注意的是 mirror 同步有并发限制,免费版社区版里 4 个同步任务并发、每周同步次数还有配额,大批量项目配置时要规划好触发频率,别把所有项目的同步时间都堆在同一分钟。

6.5 迁移的“数字遗产”也要搬:项目 ID、克隆 URL 与本地 Remote

最后提醒一个运维上的细节:代码迁移后,项目 ID 和克隆 URL 都会变化。如果团队里有人本地仓库的 remote 还指向旧地址,提交推送的时候会直接失败。我的习惯是在迁移完成后的通知里,把每个项目的新克隆地址整理成表格,让大家手动执行一遍:

git remote set-url origin git@gitlab.new.example.com:group/project.git

个别开发机如果 clone 用的还是 SSH 协议的旧 host key,第一次连接时也会报 host key verification 失败,这个不是迁移问题,而是 SSH 指纹换了,把~/.ssh/known_hosts里对应条目删除重连即可。这些小问题看起来不起眼,但在实际迁移后的第一周占了工单的最大比例。

我自己做 GitLab 跨环境迁移做过不下十几轮了,最终形成的经验是:别追求单一方案完成所有事,不同数据用不同的搬运方式,导出导入承载代码和 MR,Mirror 负责增量同步,备份恢复用来兜底整个实例,权限和 CI/CD 永远留半天时间专门重新接线。代码迁移真正的复杂度从来都在代码之外,但把这些外围工作一件件列出来逐项做完,也就没那么慌了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询