During development I often get frustrated by how frequently I need to change the database schema and generate new migrations, which quickly clutters the project and slows things down; my staging environment adds another twist since it runs entirely in Docker without Python installed on the host, giving me more free space and isolation but also making it harder to manage migrations directly, so this guide is written to help developers like me — and you — keep migrations clean, squash them when needed, and stay sane while juggling schema changes in containerized setups.
🧩 Why squashing?
Squashing migrations reduces clutter. Instead of having many small migration files, you combine them into one. This makes your project cleaner and faster to migrate on fresh databases.
📖 Step‑by‑Step Guide
1. Check your current migrations
Run:
python manage.py showmigrations myapp
You’ll see something like:
[X] 0001_initial
[X] 0002_auto
[X] 0003_add_field
[X] 0004_auto
[X] 0005_auto
The [X] means they’ve already been applied.
2. Run squashmigrations
Tell Django to squash up to the latest migration:
python manage.py squashmigrations myapp 0005
This creates a new file, usually named:
myapp/migrations/0001_squashed_0005.py
3. Edit the replaces list
Open the new squashed migration file. You’ll see something like:
replaces = [
('myapp', '0001_initial'),
('myapp', '0002_auto'),
('myapp', '0003_add_field'),
('myapp', '0004_auto'),
('myapp', '0005_auto'),
]
Since you only want to squash 0004 and 0005, trim the list:
replaces = [
('myapp', '0004_auto'),
('myapp', '0005_auto'),
]
4. Keep old migrations temporarily
Do not delete 0004 and 0005 yet. Commit the squashed migration alongside them. Django will treat the squashed migration as equivalent to those two.
5. Test on a fresh database
Drop your local DB and recreate it, then run:
python manage.py migrate
Check that the squashed migration applies cleanly and the schema looks correct.
6. Clean up
Once you’re confident:
- Delete
0004_auto.pyand0005_auto.pyfrom your repo. - Keep
0001,0002,0003(since they’re already applied in production). - Keep the new squashed migration file.
7. Push to Git
Commit the changes and push. Teammates who already applied 0004 and 0005 won’t break — Django knows the squashed migration replaces them.
🚀 Best Practices
- Always test squashed migrations on a fresh database.
- Never squash migrations that are already deployed unless you’re only squashing the latest ones.
- Communicate with your team before removing old migration files.
Hopefully this article will help you in the development or extend your knowledge in field of database migrations in Django. As always if you have any thoughts, criticism or just want to clarify something, write a comment!
Top comments (0)