遇到 MigrationConflictError 通常是因为迁移历史出现了分叉,最稳妥的做法是使用 Django 自带的合并命令生成新的迁移文件,而不是手动修改现有文件。
先说结论:这是迁移图出现了多个头节点,需要合并分支才能继续。
- 先确认:运行 showmigrations 查看是否有多个标记为未应用的头节点
- 先处理:使用 makemigrations `--merge` 自动生成合并迁移文件(CI/CD 环境需加 `--noinput`)
- 再验证:再次运行 showmigrations 确认只剩一个头节点后执行 migrate
命令速用版
本地开发环境直接运行:
python manage.py makemigrations `--merge`
python manage.py migrate
如果是特定应用冲突,指定 app 名称:
python manage.py makemigrations `--merge` your_app_name
注意:在 CI/CD 流水线或非交互环境中,必须添加 `--noinput` 参数,否则命令会等待输入导致进程挂起:
python manage.py makemigrations `--merge` `--noinput`
为什么会这样
Django 的迁移系统依赖一个有向无环图来记录数据库结构变化。当多个开发者基于同一个迁移文件分别创建了新的迁移,或者手动调整了迁移依赖关系,就会导致图中出现多个“叶子节点”。Django 不知道应该先应用哪一个,因此抛出冲突错误。
分步处理
1. 检查迁移状态
python manage.py showmigrations
观察输出,如果看到某个 app 下有两个或多个未应用的迁移文件并列(通常标记为 [ ] 且没有先后依赖),说明存在冲突。
2. 自动合并迁移
python manage.py makemigrations `--merge`
系统会提示你确认合并,输入 yes 后会在 migrations 目录下生成一个新的迁移文件,其 dependencies 包含冲突的两个父节点。
3. 手动修复依赖(仅当自动合并失败时)
如果自动合并不成功,需要手动编辑新生成的迁移文件。打开文件找到 dependencies 列表,确保它明确包含了冲突的两个迁移文件名称。例如:
dependencies = [
('your_app', '0001_initial'),
('your_app', '0002_auto'),
]
修改保存后,再次运行迁移命令。
4. 应用迁移
python manage.py migrate
怎么验证是否生效
再次运行 python manage.py showmigrations,确认每个 app 的迁移链是线性的,没有分叉。同时检查数据库迁移记录表(通常是 django_migrations),确保新生成的合并迁移已被记录。
常见坑
1. 不要随意删除迁移文件:除非你确定数据库状态干净,否则删除已应用的迁移文件会导致后续无法追踪。
2. 团队协作规范:合并代码前先拉取最新代码并运行迁移,避免多人基于旧版本创建新迁移。
3. 自动化流程卡住:在 Jenkins、GitLab CI 等环境中,务必使用 `--noinput` 参数,否则迁移步骤会因等待确认而超时失败。
4. 手动编辑风险:手动修改 dependencies 容易出错,优先使用 `--merge` 参数,只有在自动合并不满足需求时才人工干预。
参考来源
- Django 官方文档 - Migrations: https://docs.djangoproject.com/en/stable/topics/migrations/