Django:还原合并迁移

Django: revert merge migration

假设我们的迁移具有以下依赖图(全部应用):Initial state

现在,出于某种原因,我们想将数据库架构恢复到应用迁移后的状态 0006_f。我们输入:

./manage.py migrate myapp 0006_f

现在我们有以下状态:One branch reverted

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

避免它的一种方法是迁移回 0002_b 并转发到 0006_f,但这可能会导致数据丢失。还有一些迁移 0006_f0005_e0004_d0003_c 可能是不可逆的。

另一种方法是 运行 以下内容:

./manage.py migrate myapp 0006_f
./manage.py migrate myapp 0004_d1

现在,要达到所需的状态,我们只需要恢复迁移 0004_d1 并且我没有看到在不撤消 0006_f、[=16= 的情况下撤消 0004_d1 的方法] 和 0004_d 除了打开数据库 shell 并手动还原它。

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

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

如果我没看错你的问题,你遇到的情况与我的类似,我想在不触及其他分支的情况下恢复一个特定的分支。

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

  1. 反向迁移到您要取消应用的每个分支的第一个节点(0004_d1)
  2. 伪造向共同祖先的反向迁移(0003_c)编辑:见底部注释
  3. fake 迁移到要还原的每个分支的第一个节点 (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

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

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