Django:恢复合并迁移

Kir*_*ski 6 python django database-migration django-migrations

假设我们有以下依赖关系图(全部应用)的迁移:初始状态

现在,出于某种原因,我们希望在应用迁移后将数据库模式恢复到状态0006_f。我们输入:

./manage.py migrate myapp 0006_f
Run Code Online (Sandbox Code Playgroud)

现在我们有以下状态:一个分支恢复

问题是 Django 不会恢复正确的分支,所以现在我们从左分支应用了一些迁移,从右分支应用了一些迁移。

避免它的一种方法是向回迁移0002_b和向前迁移,0006_f但这可能会导致数据丢失。还有一些迁移0006_f, 0005_e, 0004_d,0003_c可能是不可逆的。

另一种方法是运行以下命令:

./manage.py migrate myapp 0006_f
./manage.py migrate myapp 0004_d1
Run Code Online (Sandbox Code Playgroud)

现在,为了达到理想状态,我们只需要恢复迁移0004_d1,我不明白的方式来撤销0004_d1不撤销0006_f0005_e0004_d除开DB外壳和手动恢复它。

有没有一种方法可以显式撤消一次迁移?还有另一种方法可以正确撤消并行分支的迁移吗?在撤消合并迁移时,Django 是否有某种原因不会自动从并行分支恢复迁移?

Tuo*_*ila 4

2019-10-17 编辑:我添加了步骤 0,我发现该步骤可以降低涉及跨应用程序依赖项时的一些风险。

如果我正确地阅读了您的问题,那么您遇到了与我类似的情况,我想恢复一个特定分支而不接触其他分支。

我设法通过以下步骤做到这一点(在 v1.11.7 和 v2.2 中):

  1. 反向迁移到要取消应用的每个分支的第一个节点 (0004_d1)
  2. 假装反向迁移到共同祖先(0003_c)编辑:请参阅底部的注释
  3. 迁移到要恢复的每个分支的第一个节点 (0004_d1)
  4. 从步骤 1 (0003_c) 反向迁移到共同祖先
  5. 伪造迁移到您想要保留的分支的尖端(0007_g)
  6. 根据需要删除或修改合并迁移;见下文(0008_merge)

所以在你的情况下:

./manage.py migrate 0004_d1
./manage.py migrate --fake myapp 0003_c
./manage.py migrate --fake myapp 0004_d1
./manage.py migrate myapp 0003_c
./manage.py migrate --fake myapp 0007_g
Run Code Online (Sandbox Code Playgroud)

如果您的合并迁移 0008_merge 执行任何实际工作或迁移更多分支,您可能需要手动编辑它以省略 0005_e1 分支,然后假迁移到它;否则你应该可以删除它。

编辑:关于步骤 2 的注释:有时,如果步骤 2 导致某些跨应用程序依赖项迁移被假未应用,则它们可能会导致步骤 4 失败。步骤 1 减轻了这种风险,但您应该检查已应用哪些操作,并尝试确保任何跨应用程序依赖项在步骤 4 期间不处于伪造状态。