不能依赖 git 分支合并顺序保证 ddl 执行顺序,因为 git 仅同步 sql 文件内容,不记录执行上下文或时序约束,易导致外键失败、乱序执行等问题;迁移必须按全局编号严格递增管理,与分支解耦。

Git 多分支架构本身不感知数据库变更,表结构同步必须靠人工约定 + 工具链兜底。没有自动同步机制,靠分支命名或合并顺序“暗示”DDL 顺序是危险的。
为什么不能依赖 Git 分支合并顺序来保证 DDL 执行顺序
Git 分支只是代码快照的逻辑分组,git merge 不会触发、记录或校验任何数据库操作。即使你在 feature/user-auth 分支里写了 ALTER TABLE users ADD COLUMN phone VARCHAR(20),它和 develop 分支里的 CREATE TABLE roles 脚本之间,没有任何执行时序约束。上线时若先跑后者再跑前者,可能因外键依赖失败;若在不同环境手动执行,顺序更难保障。
- 分支合并只同步 SQL 文件内容,不携带执行上下文(如目标库版本、当前 schema 版本、前置依赖)
- CI/CD 流水线若未显式声明迁移执行阶段,
migrate up可能被跳过或重复执行 - 多人并行开发时,两个 feature 分支各自带一个
ADD COLUMN,合并后脚本编号若未按时间严格递增,工具可能乱序执行
迁移脚本必须与分支解耦,按语义版本+全局序号管理
把迁移文件放在 migrations/ 目录下,但禁止按分支组织子目录(如 migrations/feature-x/)。所有脚本统一用 001_add_users_table.up.sql 这类前缀编号,编号由工具生成(如 migrate create),而非人工手写。编号代表全局执行顺序,与分支无关。
- 编号必须严格递增且不可复用:即使某个分支被废弃,其已生成的
005_...脚本仍保留在主干migrations/目录中 - 每个脚本必须自包含:
up.sql要能独立执行成功,不能依赖前一个脚本里临时建的视图或变量 -
down.sql不必 100% 可逆(如DROP COLUMN在 MySQL 中无法回滚),但要明确标注限制,避免误用
CI/CD 流水线中必须强制校验迁移一致性
不能只在本地跑 migrate up 就合入 develop。每次 PR 提交,CI 必须做两件事:检查新迁移脚本是否编号连续;用 migrate -dry-run 或 migrate validate 验证语法和依赖关系(比如引用了尚未定义的表)。
- Git hook(如
pre-push)可拦截本地漏检,但不可替代 CI —— hook 可被绕过,CI 是唯一可信防线 - 生产部署前,必须比对目标库当前
version和待执行脚本最小编号,禁止跳号或重号 - 错误示例:
migrate -path migrations -database postgres://... up 3手动指定步数,易遗漏中间脚本
跨分支协作时,DDL 变更需提前对齐基线版本
当 feature/reporting 和 feature/billing 并行开发,且都涉及 orders 表修改时,不能各自提交 ALTER 脚本然后等合并时“自然解决”。必须在分支创建初期就协商好该表的下一个变更编号(如约定都用 012_),或由 DBA 主持评审会议确认变更冲突点。
- 工具层面可用
migrate status导出各环境当前版本,作为 PR 描述的必填字段 - 禁止在 feature 分支里直接修改已有迁移脚本(如重命名
003_为004_),这会导致其他分支拉取后本地状态错乱 - 真正容易被忽略的是:测试环境数据库往往复用同一套迁移历史,但不同 feature 分支可能基于不同 commit 构建,导致
migrate version输出不一致,进而影响自动化判断











