FlywayGuard:IDEA插件解决Flyway SQL冲突

📅 2026/8/25 5:40:45
FlywayGuard:IDEA插件解决Flyway SQL冲突
摘要在团队协作中Flyway 版本冲突是数据库迁移最常见的痛点——版本号重复、乱序、已推送脚本被修改往往导致合并冲突甚至启动失败。FlywayGuard 是一款开源的 IDEA 插件在 commit、push、merge 前自动检测并拦截违规脚本把 Flyway 版本规则前移到日常操作中纯只读、不植入任何代码帮助团队从源头规避数据库迁移冲突。引言Flyway 迁移的痛点在微服务架构中数据库版本管理是持续交付的关键环节。Flyway 作为流行的数据库迁移工具通过版本化的 SQL 脚本确保数据库结构的一致性。然而在实际团队协作中我们经常遇到以下问题脚本冲突版本号重复、没有递增多个开发人员同时修改数据库结构导致V1.2__add_user_table.sql等脚本版本号重复或乱序多人协作造成冲突merge、commit、push 时产生版本冲突版本号命名不规范推荐使用时间戳 DML/DDL 描述 的命名方式冲突后需要调整 history 表版本冲突后需要手动修改 Flyway 的flyway_schema_history表已提交的 SQL 被修改也会报错Flyway 的 history 表记录了脚本的 md5 校验码已推送的脚本被修改后校验失败Flyway 是一款开源的数据库版本控制工具通过版本化的 SQL 脚本如V1.1__create_table.sql确保数据库结构的一致性。其核心是严格按版本号顺序执行迁移并在数据库中记录执行历史。问题分析SQL 冲突的根源冲突场景示例假设团队中有两位开发者同时工作开发者 A创建了V1.3__add_user_role.sqlALTERTABLEusersADDCOLUMNroleVARCHAR(30);开发者 B创建了V1.3__add_user_department.sqlALTERTABLEusersADDCOLUMNdepartment_idBIGINT;两者都使用了版本号1.3当合并代码时就会产生冲突。传统解决方案需要手动重命名其中一个文件调整依赖关系通知团队成员可能还需要修改已部署环境的脚本解决方案FlywayGuard IDEA 插件FlywayGuard 是一款开源的 IntelliJ IDEA 插件Apache License 2.0定位为Flyway 迁移脚本哨兵在提交、推送、合并这些日常操作前通过纯 IDE 级的行为检测与拦截把 Flyway 的版本规则前移而不是等 CI 或跑数据库时才报错。它不向用户仓库植入任何代码——不写 git hook、不改core.hooksPath、不写任何文件进项目纯只读检测 IDE 拦截。源码https://gitee.com/my_cctest/flyway-guard插件初心与设计原则Flyway 迁移脚本是团队共享的数据库变更契约一旦推送push并被他人执行就不可修改、版本号不可重复、版本号只能递增。违反这些规则会造成修改已推送的脚本→ 别人库里已经跑过改不生效或产生脏数据版本号重复→ Flyway 报Found more than one migration with version X启动即失败版本号乱序新增版本低于已推送的最高版本→ Flyway 默认outOfOrderfalse拒绝执行FlywayGuard 的初心就是在问题发生前拦住它靠 IDE 自动兜底。两条铁律不植入不往仓库写 git hook、不改core.hooksPath、不写任何文件进项目纯只读检测 IDE 拦截。轻量化版本规则、上游分支等一律遵循 Flyway/git 标准自动探测尽量不设配置项。功能总览功能触发场景行为提交拦截commit 前硬拦违规弹「仍然提交 / 取消」推送拦截Push 对话框确认前硬拦违规弹「仍然推送 / 取消」违规脚本编辑器横幅打开文件时违规脚本重复/乱序/已提交被改在编辑器顶部显示警示横幅文件变化实时刷新图标SQL 内容/改名/增删时立即重算非法集合项目树红✕/绿✓即时更新文件状态图标项目树.sql数据库圆柱图标 合规绿✓/非法红✕ 角标总开关工具窗口勾选启用默认取消后不再检测 commit/push/merge 异常 SQL版本冲突实时标红编辑器同版本重复的脚本标红合并/推送后冲突通知merge / pull / push / fetch 后弹通知重复版本 乱序工具窗口手动查看只显示版本号文件名重复/乱序/被改标红可切换中英文双击打开界面截图工具窗口脚本列表、合规/违规角标、状态汇总与「启用」开关文件树角标合规脚本绿✓、违规脚本红✕编辑器顶部警示横幅已提交脚本被修改 / 违规脚本打开时提交拦截弹窗违规项列表 「仍然提交 / 取消」合并前检查预判把分支合并进来会引入的版本冲突拦截规则commit 与 push 均生效修改 / 删除已提交的迁移脚本 →禁止新增脚本版本号重复与项目内已有脚本或上游冲突→禁止新增脚本版本号乱序低于项目内最高版本或上游最高版本Flyway 默认outOfOrderfalse→禁止插件安装与配置1. 安装方式IDEA 插件市场Settings → Plugins → Marketplace → 搜索 “FlywayGuard”安装后重启手动安装Settings → Plugins → ⚙️ → Install Plugin from Disk选择flyway-guard-4.0.0.jar重启#### 2. 环境要求IntelliJ IDEA 2024.2含 Git 插件默认内置系统可执行 git 命令在 PATH 中项目为 git 仓库且当前分支有上游{u}或origin/master/origin/main之一插件仅在 git 仓库项目中生效非 git 项目不产生任何拦截与提示工具窗口会显示提示。上游缺失时仍会做项目内重复/乱序校验。插件核心原理FlywayGuard 基于 IntelliJ PlatformIDEA 2024.2Java 17开发通过平台扩展点实现各类拦截与检测扩展点实现类作用checkinHandlerFactoryFlywayCheckinHandler提交前跑 FlywayCommitChecker违规可 CANCELprePushHandlerFlywayPrePushHandler收集待推送提交的变更跑同一检查器违规返回 ABORTfileIconProviderFlywayGuardIconProvider.sql数据库圆柱图标 合规绿✓/非法红✕ 角标localInspectionFlywayVersionInspection编辑器实时标红同版本重复postStartupActivityFlywayGuardStartupActivity项目打开时刷新状态集合、订阅冲突通知toolWindowFlywayGuardPanel脚本列表版本倒序、重复/乱序标红、双击打开notificationGroupFlywayConflictNotifiermerge/push/fetch 后扫描并弹通知git 操作只读git rev-parse、git ls-tree不依赖 git4idea 的写操作依赖 git4ideaGitRepository.GIT_REPO_CHANGE事件与 DVCS push 框架PrePushHandler扩展点。Flyway 标准版本规则核心版本化迁移 文件名以V数字版本__描述.sql开头前缀V分隔符__版本号为纯数字可用.或_分段、可补零V1、V1.0.1、V1_1、V001.002、V20220824比较按数字逐段比较、忽略前导零V011 V0071.0与1视为相同缺失段视为0唯一性版本不能重复递增新增版本必须高于已推送的最高版本上游已推送基准自动探测无需配置{u}→origin/当前分支→ 最近共同祖先远端分支当前分支未推送时push 拦截用只读git ls-tree -r upstream取已推送脚本集做对比状态图标、工具窗口、通知则用 IDEA 文件状态判定「已提交」为基准无色已提交、蓝色已提交被改、绿色新增不依赖上游解析日常使用新增迁移脚本按 Flyway 命名V更高版本号__描述.sql创建即可。若版本号与上游重复、或低于上游最高版本提交时会被拦截。提交 / 推送被拦IDEA 弹窗列出违规项。选择「取消」回到编辑器修复确认必须执行时选「仍然提交 / 仍然推送」放行。已提交脚本可编辑但会被警示——IDEA 将改动标为蓝色已提交被改文件树显示红✕、编辑器顶部横幅提示提交/推送仍会被拦截如需修改应新增更高版本脚本承载变更。实时标红同版本号的两个脚本在编辑器中直接标红。合并 / 拉取后若引入重复版本或乱序插件自动弹通知提示。工具窗口右侧 FlywayGuard只展示版本号 文件名按版本号倒序重复版本、乱序、已提交被改的脚本红色显示顶部可切换中文 / 英文作用于整个插件双击任意脚本跳转打开「刷新」按钮手动重新扫描。例外通道所有拦截均为 IDE 级提示可通过弹窗中的「仍然提交 / 仍然推送」显式确认后放行不改动任何代码。若确实需要修改已提交脚本请在弹窗提示基础上额外遵循团队约定如--no-verify例外精神。已知限制仅 git 仓库项目生效非 git 项目不拦截、不提示工具窗口显示提示。只拦截 IDEA 内的提交与推送在终端用git commit/git push不会被拦截插件不植入 git hook。编辑器实时标红仅覆盖同版本重复乱序靠工具窗口标红、合并后通知、以及 commit/push 硬拦兜底。单仓库假设一个 IDEA 项目打开多个 git 仓库时只检测项目根所在仓库。上游对比依赖本地已 fetch 到的远程状态git ls-tree upstream协作者刚推送的新版本需先git fetch才能感知。