Fix: Django Migration Conflict (Conflicting Migrations Cannot Be Applied)
Quick Answer
How to fix Django migration conflicts — why multiple leaf migrations conflict, how to merge conflicting migrations, resolve dependency chains, and set up a team workflow to prevent migration conflicts.
The Error
Running python manage.py migrate or python manage.py makemigrations fails with:
CommandError: Conflicting migrations detected; multiple leaf nodes in the
migration graph: (0003_add_email, 0003_add_phone) in app 'users'.
To fix them run 'python manage.py makemigrations --merge'.Or:
django.db.migrations.exceptions.MigrationSchemaMissing: Unable to create the
django_migrations table (table "django_migrations" already exists)Or when running showmigrations:
users
[X] 0001_initial
[X] 0002_add_username
[ ] 0003_add_email
[ ] 0003_add_phone ← Two migrations with the same numberWhy This Happens
Django migration conflicts occur when two migrations claim to be the “next” migration in the same app’s history — both have the same parent but were created independently:
- Two developers created migrations in parallel — Developer A creates
0003_add_emailon their branch; Developer B creates0003_add_phoneon their branch. When merged, Django sees two migrations with parent0002, creating a fork in the graph. - Stale migration state — a migration was created based on an outdated model state.
- Squashing went wrong — a squashed migration has incorrect dependencies.
- Migrations not committed before branching — a developer forgets to commit migrations before branching, then makes a migration on the branch that conflicts with the one on the main branch.
Fix 1: Merge Conflicts with makemigrations —merge
The standard fix when Django itself detects the conflict:
# Django tells you exactly what to do
python manage.py makemigrations --merge
# If you have multiple apps with conflicts, specify the app
python manage.py makemigrations --merge users
# Review the generated merge migration before applying
cat users/migrations/0004_merge_0003_add_email_0003_add_phone.pyThe generated merge migration looks like this — it simply depends on both conflicting migrations:
# users/migrations/0004_merge_0003_add_email_0003_add_phone.py
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0003_add_email'),
('users', '0003_add_phone'),
]
operations = [
# Empty — the merge migration just links the two branches
]After creating the merge migration:
python manage.py migrate users
python manage.py showmigrations users
# All migrations should now show [X]Fix 2: Resolve Conflicting Migrations Manually
When the auto-merge would produce incorrect ordering (e.g., one migration adds a column that the other migration also references), resolve manually:
Step 1 — identify which migrations conflict:
python manage.py showmigrations users
# users
# [X] 0001_initial
# [X] 0002_add_username
# [ ] 0003_add_email ← Conflicts with:
# [ ] 0003_add_phone ← This one
python manage.py migrate --check # Returns non-zero if migrations are unappliedStep 2 — decide on the correct order:
Determine which migration should come first logically. If add_phone depends on the email field being present, then add_email must run first.
Step 3 — rename and re-number one migration:
# Rename 0003_add_phone to 0004_add_phone to make it come after 0003_add_email
mv users/migrations/0003_add_phone.py users/migrations/0004_add_phone.pyStep 4 — update the dependencies in the renamed migration:
# users/migrations/0004_add_phone.py
class Migration(migrations.Migration):
dependencies = [
('users', '0003_add_email'), # Now depends on 0003_add_email, not 0002
]
operations = [
migrations.AddField(
model_name='user',
name='phone',
field=models.CharField(max_length=20, blank=True),
),
]Step 5 — apply:
python manage.py migrate usersFix 3: Fix Conflicts in Development After git merge
The most common real-world scenario — you merge a branch and suddenly have conflicting migrations:
git merge feature/add-email-field
# Now you have:
# users/migrations/0003_add_email.py (from main)
# users/migrations/0003_add_phone.py (from your branch)Option A — use makemigrations —merge (safe, recommended):
python manage.py makemigrations --merge --no-input
git add users/migrations/0004_merge_*.py
git commit -m "Merge migration conflict in users app"Option B — delete your local migration and recreate it:
If you haven’t pushed your branch yet and your migration is simpler:
# 1. Unapply your local migration
python manage.py migrate users 0002 # Roll back to before your migration
# 2. Delete your conflicting migration
rm users/migrations/0003_add_phone.py
# 3. Recreate it — it will now depend on 0003_add_email
python manage.py makemigrations users
# Creates: 0004_add_phone.py with correct dependency
# 4. Apply
python manage.py migrate usersOption C — squash and restart (for local dev databases only):
# Reset all migrations for the app (DESTROYS DATA — dev only)
python manage.py migrate users zero # Unapply all migrations
find users/migrations -name "0*.py" -not -name "0001_initial.py" -delete
python manage.py makemigrations users
python manage.py migrate usersFix 4: Fix “django_migrations table already exists” Error
This happens when you try to initialize Django migrations on a database that already has the tables but not the migrations tracking table — common when migrating from a legacy schema:
# Create the migrations table without running any migrations
python manage.py migrate --run-syncdb
# Or — fake the initial migration to tell Django the schema already exists
python manage.py migrate users 0001 --fake-initial--fake-initial tells Django to mark the initial migration as applied without actually running it — useful when the tables already exist from a syncdb or manual SQL.
For all apps at once:
python manage.py migrate --fake-initialFix 5: Prevent Migration Conflicts in Teams
Use a sequential naming convention:
# Bad — Django auto-names by content: 0003_add_email vs 0003_add_phone
python manage.py makemigrations
# Good — use --name to make intent clear (but numbering still conflicts)
python manage.py makemigrations users --name add_email_fieldEstablish a team workflow:
Always pull and migrate before creating a new migration:
git pull origin main python manage.py migrate python manage.py makemigrationsCommit migrations immediately after creating them — never leave them uncommitted.
Use a migration lock in CI — fail the build if unapplied migrations exist:
# In CI before running tests python manage.py migrate --check # Returns exit code 1 if there are unapplied migrations — catches conflicts earlySquash migrations periodically to clean up the history and reduce conflict surface:
python manage.py squashmigrations users 0001 0010 # Creates users/migrations/0001_squashed_0010_...py
Fix 6: Fix Dependency Errors in Migration Files
When a migration references a model or field from another app and the dependency is missing:
django.db.migrations.exceptions.NodeNotFoundError:
Migration users.0003_add_profile references model 'profiles.Profile'
from app 'profiles', which is not installedAdd the missing dependency explicitly:
# users/migrations/0003_add_profile.py
class Migration(migrations.Migration):
dependencies = [
('users', '0002_add_username'),
('profiles', '0001_initial'), # ← Add this dependency
]
operations = [
migrations.AddField(
model_name='user',
name='profile',
field=models.OneToOneField(
'profiles.Profile',
on_delete=models.CASCADE,
null=True,
),
),
]Check the dependency graph:
# Show the full migration dependency graph
python manage.py showmigrations --planFix 7: Fix Migrations on Production After a Bad Deploy
If a bad migration was deployed to production and needs to be rolled back:
Roll back to the previous migration:
# Check current state
python manage.py showmigrations users
# Roll back to the migration before the bad one
python manage.py migrate users 0005 # Reverts 0006 and later
# Verify
python manage.py showmigrations usersIf the migration is not reversible (e.g., it drops a column), write a reverse migration:
class Migration(migrations.Migration):
dependencies = [('users', '0005_safe_migration')]
operations = [
# Forward: removes the column
migrations.RemoveField(model_name='user', name='legacy_field'),
# This migration CANNOT be reversed automatically
# Add database_backwards to make it reversible:
]
def database_backwards(self, app_label, schema_editor, from_state, to_state):
# Manually re-add the column for rollback
schema_editor.execute(
"ALTER TABLE users_user ADD COLUMN legacy_field VARCHAR(255) DEFAULT ''"
)Still Not Working?
Check for circular dependencies. If two apps depend on each other’s migrations, you get a circular dependency error. Resolve by moving the shared model to a third app or using a lazy reference:
# Instead of ForeignKey to a model in another app that depends on this one:
field=models.ForeignKey('other_app.Model', ...) # Lazy string reference — avoids circular importCheck that INSTALLED_APPS includes all apps with migrations. If an app is missing from INSTALLED_APPS, Django cannot find its migrations and reports dependency errors.
Use python manage.py migrate --plan to see what migrations will be applied before running them:
python manage.py migrate --plan
# Lists every migration in the order it will be appliedFor related Django and database issues, see Fix: Django OperationalError No Such Table and Fix: Prisma Migration Failed.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Django Forbidden (403) CSRF verification failed
How to fix Django 403 CSRF verification failed error caused by missing CSRF tokens, AJAX requests, cross-origin issues, HTTPS misconfig, and session problems.
Fix: django.db.utils.OperationalError: no such table (SQLite / PostgreSQL / MySQL)
How to fix Django's 'OperationalError: no such table' error caused by missing migrations, wrong database configuration, corrupted files, or Docker volume issues.
Fix: Flask Route Returns 404 Not Found
How to fix Flask routes returning 404 — trailing slash redirect, Blueprint prefix issues, route not registered, debug mode, and common URL rule mistakes.
Fix: pandas merge() Key Error and Duplicate Columns (_x, _y)
How to fix pandas merge and join errors — KeyError on merge key, duplicate _x/_y columns, unexpected row counts, suffixes, and how to validate merge results.