Every Django project may encounter a steady increase in a number of migrations over time. One way to lower their quantity is to use squashing. Squashing amounts to taking contents of few migrations and connecting them into one. This would reduce their number, but what happens if we squash a bunch of migrations that were already partially applied to one of application’s instances?
Let’s consider following situation. We have three different migrations in our app:
- 0001_initial - 0002_auto_20170531_2038 - 0003_rental
We squashed them to one:
~/squash_versus_cd> ./manage.py squashmigrations core 0001_initial 0003_rental Will squash the following migrations: - 0001_initial - 0002_auto_20170531_2038 - 0003_rental Do you wish to proceed? [yN] y Optimizing... Optimized from 4 operations to 3 operations. Created new squashed migration core/migrations/0001_initial_squashed_0003_rental.py
If we inspect newly created migration’s code we discover that django placed a clear sign that our new migration replaces old ones:
replaces = [ ('core', '0001_initial'), ('core', '0002_auto_20170531_2038'), ('core', '0003_rental') ]
If we ever decided to set up another instance of our application, it django would execute our squashed migration only (0001_initial_squashed_0003_rental).
What if we found ourselves in a less pleasant situation, when we have our instance partially migrated? Let’s say we have executed migrations 0001 and 0002:
squash_versus_cd> ./manage.py showmigrations core [X] 0001_initial [X] 0002_auto_20170531_2038 [ ] 0003_rental
Unless we deleted original migration files (django won’t touch them) we will be able to just run ./manage.py migrate. Django will handle this situation.
squash_versus_cd> ./manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, core, sessions Running migrations: Applying core.0003_rental... OK0