告别“野路子”:如何将网页端乱改的 Supabase 优雅接回本地 CLI
之前用 Supabase 的方式,一直很野。
基本工作流就是:去 Dashboard 里建表、改 SQL;去网页端贴 Edge Function 代码;改完能跑就算大功告成。
这种方式前期确实爽,业务跑得飞快。但到了后期,就会越来越抓狂,因为你会发现一个残酷的现实:线上到底改了什么,你的 Git 仓库里根本没有真值(Source of Truth)。
本地代码和线上函数开始“漂移”,下次想继续开发不知道该从哪接手,想做数据库回滚、代码 Review 更是天方夜谭。
痛定思痛,我决定把项目正式接回本地,用 Supabase CLI 来接管。
这篇文章记录的是一个非常具体的实战场景:项目已经在线上跑起来了,很多东西是在网页端改的,现在要把它们完整拉回本地,作为 Git 真值继续维护。
如果你也正处于这种“骑虎难下”的状态,这篇避坑指南就够用了。
核心结论:接管线上项目的黄金准则
不要急着敲代码,一句话总结我们的目标:先把远端现状完整拉下来,再开始继续开发。
我最后确认下来的最稳接管流程如下:
- 安装 Node.js 和 Docker Desktop。
- 优先使用
npx supabase运行 CLI。 supabase link绑定线上项目。supabase db pull拉取远端 Schema 到本地。- 将第一次 Pull 下来的 Schema 记为 Baseline Migration 并标记已应用。
supabase functions download <name>将线上函数全部拉取到本地。
从跑通这一刻起,以本地 supabase/ 目录作为唯一真值。
步步为营:完整接管流程与踩坑实录
明确了目标不是“新建项目”而是“接管现有项目(保留现有数据库和函数)”后,我们开始实操。
第一步:跑起 CLI 与 Docker(注意旧环境避坑)
我建议直接使用 npx supabase 而不是全局安装。这样不污染全局环境,版本跟着项目走,换电脑协作也更方便。
同时,Docker Desktop 是必备项。db pull 这类数据库同步流程强依赖 Docker 守护进程。但在安装 Docker 时,我踩了一个大坑。
如果你以前装过 Docker,在使用 Homebrew 重装时可能会遇到冲突报错。这是因为 /usr/local/bin 里残留了指向旧版 Docker 的软链接(如 hub-tool、vpnkit 等)。
解决办法: 遇到提示 already a Binary at... 时别慌,清理掉这些旧的软链接,重新安装即可。只要 docker ps 能正常响应,环境就准备就绪了。
第二步:登录并绑定线上项目
先登录你的账号:
npx supabase login
列出账号下的项目,找到你需要接管的项目 Ref ID:
npx supabase projects list
明确目标后,执行绑定:
npx supabase link --project-ref <你的项目Ref>
成功后,本地仓库的 .temp 目录就会写入当前项目的上下文。
第三步:拉取数据库真值(最关键的一步)
既然之前都在 Dashboard 里改数据库,现在就要把远端 Schema 导出成一份本地 Migration。
npx supabase db pull
这一步会让你的本地仓库第一次拥有“数据库结构真值”,生成类似 20260313xxxxxx_remote_schema.sql 的文件。这也是你当前线上数据库的 Baseline(基线)。
这里有两个高频踩坑点:
- 坑 1:残留空文件导致历史不一致。 如果某次
db pull中途失败,可能会在migrations目录下留下一个 0 字节的空文件。这会导致后续同步报错。一定要先删掉空文件,再重新 pull。 - 坑 2:密码验证失败导致报错 EOF。 拉取成功后,CLI 会询问是否更新远端 migration 历史表(
Update remote migration history table?)。选 Y 后如果报错unexpected EOF,通常是因为数据库密码没配对。- 注意:这里需要的是数据库自身的 Password,不是 anon key,也不是 API Keys。
- 通过
export SUPABASE_DB_PASSWORD='<你的数据库密码>'注入环境变量,重新 link 后,再通过命令修复并标记为已应用: npx supabase migration repair --linked --status applied <时间戳>
第四步:接管 Edge Functions
数据库搞定了,接下来是云函数。先查看线上有哪些函数:
npx supabase functions list
然后挨个把它们下载到本地:
npx supabase functions download <function-name>
下载完成后,你的 supabase/functions/ 目录下就会整整齐齐排列好所有的函数代码。到这一步,线上函数的真值也正式回到了本地。
认知升级:从“网页直改”到“本地真值”
这是最重要的一次工程习惯切换。工具的改变是表象,思维的转变才是核心。
| 对比维度 | 过去的“野路子”模式 | 现在的“工程化”模式 |
|---|---|---|
| 真实来源 (Truth) | 网页端 Dashboard + 本地零散代码 | 本地 Git 仓库的 supabase/ 目录 |
| 数据库变更 | SQL Editor 随手执行 | 本地编写 Migration -> db push |
| 云函数修改 | 网页端粘贴代码 -> Save | 修改本地 functions/ -> deploy |
| 历史追溯 | 靠脑子记,找不回历史版本 | Git 提交记录一目了然 |
以后绝对不要再出现“本地改一点,网页端补一点”的情况。一旦本地接管完成,后续的任何改动都应该遵循以下流程:
- 数据库改动:
npx supabase db push - 函数部署:
npx supabase functions deploy <function-name>
如果你真的忍不住在网页端临时改了东西(比如为了紧急修 Bug),必须立刻同步回本地(db pull 或 functions download),否则仓库和线上很快又会发生不可逆的漂移。
写在最后
一旦项目开始正式跑起来,就一定要尽快收口真值。
前期在网页端改来改去真的很爽,但随着项目变复杂,函数变多、SQL 变多、甚至需要区分测试/生产环境时,迟早会陷入一种“好像哪里都能改,但没人知道真相到底在哪”的泥潭。
这次接回本地,线上环境从“唯一记忆体”退回到了它应有的位置——“运行态”。真值掌握在 Git 手里,后面再做任何扩展,心里就踏实多了。