Let's suppose we have migrations with the following dependency graph (all applied): Initial state
Now, for some reason we want to revert database schema to the state after applying migration 0006_f
. We type:
./manage.py migrate myapp 0006_f
and now we have the following state: One branch reverted
The problem is that Django does not revert the right branch, so now we have some migrations applied from left branch and some from the right one.
One way to avoid it is to migrate back to 0002_b
and forward to 0006_f
but this can cause data loss. Also some of migrations 0006_f
, 0005_e
, 0004_d
, 0003_c
can be irreversible.
Another way is to run the following:
./manage.py migrate myapp 0006_f
./manage.py migrate myapp 0004_d1
Now, to achieve the desired state we only have to revert the migration 0004_d1
and I do not see a way to undo 0004_d1
without undoing 0006_f
, 0005_e
and 0004_d
except for opening DB shell and reverting it manually.
Is there a way to explicitly undo only one migration? Is there another way to properly undo migrations from parallel branch? Is there some reason for Django not to automatically revert migrations from parallel branch when undoing merge migration?
Django's migration can be reset by cleaning all the migration files except __init__.py files under each project app directory, followed by dropping the database and creating migration again using python manage.py makemigrations and python manage.py migrate .
you can either: temporarily remove your migration, execute python manage.py migrate, add again your migration and re-execute python manage.py migrate. Use this case if the migrations refer to different models and you want different migration files for each one of them.
This may happen due to the following reasons: You did not add the app in INSTALLED_APPS list in settings.py (You have to add either the app name or the dotted path to the subclass of AppConfig in apps.py in the app folder, depending on the version of django you are using). Refer documentation: INSTALLED_APPS.
edited 2019-10-17: I'm adding a step 0 which I've found reduces some risks when cross-app dependencies are involved.
If I'm reading your question correctly, you had a situation similar to mine where I wanted to revert one specific branch without touching the others.
I managed to do this (in v1.11.7, and v2.2) with these steps:
So in your situation:
./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
If your merge migration 0008_merge does any actual work or migrates more branches, you'll probably have to edit it manually to omit the 0005_e1 branch and then fake-migrate to it; otherwise you should be able to just delete it.
edit: note regarding step 2: It seems that sometimes, if step 2 causes some cross-app dependency migrations to be fake-unapplied, they may cause step 4 to fail. Step 1 mitigates this risk, but you should check what operations have been applied and try to make sure any cross-app dependencies are not in a faked state during step 4.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With