Reputation: 3369
In Django's migrations code, there's a squashmigrations
command which: "Squashes the migrations for app_label
up to and including migration_name
down into fewer migrations, if possible."
So, if you want to squash, say, the first 5 migrations, this will help.
What's the best way to squash starting with a particular migration_name
?
In a project I'm currently working on, we've added 5-10 new migration files as we've added new features. We'll deploy the whole project at once and it looks like running these individually will take too long. I'd like to squash all the migrations for this project into a single migration and test the time to run that.
Upvotes: 116
Views: 73607
Reputation: 6539
Squash migrations command was introduced in Django 1.9
If you are using Django 1.8 you need to
squashmigrations.py
from Django 1.9 version
https://github.com/django/django/blob/stable/1.9.x/django/core/management/commands/squashmigrations.py/-package-/-app-/management/commands/
squashmigrations19.py
./manage.py squashmigrations19 -app- 0002 0003
Upvotes: 7
Reputation: 6808
I created django-squash
https://pypi.org/project/django-squash/ as a way to not have to deal with migrations on a per-app level or worse a per-app-specific-migration level, and handle it on a per-project level. The idea is to hopefully integrate it inside core Django at some point.
Basic idea:
Example:
/app1/migrations/__init__.py
/app1/migrations/0001_initial.py
/app1/migrations/0002_created_user_model.py
/app1/migrations/0003_added_username.py
/app1/migrations/0004_added_password.py
/app1/migrations/0005_last_name.py
You've applied them all.
But every time you run your tests, every single one of those steps need to run, taking valuable time. So we squash. The new directory will look like this:
/app1/migrations/__init__.py
/app1/migrations/0001_initial.py
/app1/migrations/0002_created_user_model.py
/app1/migrations/0003_added_username.py
/app1/migrations/0004_added_password.py
/app1/migrations/0005_last_name.py
/app1/migrations/0006_squash.py
inside 0006_squash.py
you will find a replaces = [..]
with the names of migrations 1-5. You will also find a Migration.operations = [..]
with everything you would expect if you deleted all your migrations and did a ./manage.py makemigrations
+ any RunSQL
/RunPython
with elidable=False
. If you deploy to an environment that is missing any of migrations 1-5 it will apply it from source and not use 0006 AT ALL. (this is standard Django migrations)
Some time passes, now your migrations look like this:
/app1/migrations/__init__.py
/app1/migrations/0001_initial.py
/app1/migrations/0002_created_user_model.py
/app1/migrations/0003_added_username.py
/app1/migrations/0004_added_password.py
/app1/migrations/0005_last_name.py
/app1/migrations/0006_squash.py
/app1/migrations/0007_change_username_to_100_char.py
/app1/migrations/0008_added_dob.py
You squash again. This time the following will happen. Anything inside the replaces = [..]
will be deleted. 0006_squash.py
will be modified to have replaces
be an empty list. Lastly the squash will be recreated with the new changes. All told, will look like this:
/app1/migrations/0006_squash.py
/app1/migrations/0007_change_username_to_100_char.py
/app1/migrations/0008_added_dob.py
/app1/migrations/0009_squash.py
Starting the cycle once again.
Upvotes: 6
Reputation: 2593
python manage.py squashmigrations <appname> <squashfrom> <squashto>
python manage.py help squashmigrations
https://docs.djangoproject.com/en/dev/topics/migrations/#migration-squashing
This will give you more granular control over which migrations to squash, and let you keep a cleaner commit history. Deleting + recreating all migrations may cause other issues such as circular dependencies depending on how models are constructed.
Upvotes: 203
Reputation: 13160
You can just delete the migration files and run makemigrations
again. If you have a dev deployment that uses these, you should migrate back to the one before the first one you delete.
Also, it's probably a good idea to commit your code first, in case something goes wrong.
Also:
The slight complication with this is that if there's custom RunPython code, it won't be included in the new migration created by makemigrations
Upvotes: 33