Django – squashing migrations versus continuous delivery

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> ./ 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
  Optimized from 4 operations to 3 operations.
Created new squashed migration core/migrations/

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> ./ showmigrations
 [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 ./ migrate. Django will handle this situation.

squash_versus_cd> ./ migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, core, sessions
Running migrations:
  Applying core.0003_rental... OK

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.