Mỗi migration trong cùng app có số thứ tự (0023_.py) và dependencies trỏ migration cha. Khi 2 branch cùng tạo migration mới từ 0022, cả 2 đều thành 0023_.py. Merge git xong, Django thấy 2 leaf node song song → python manage.py migrate không biết đi đường nào → báo InconsistentMigrationHistory.
Sửa bằng python manage.py makemigrations --merge → Django sinh *migration 0024_merge_.py** chỉ chứa dependencies = [0023_a, 0023_b], không thêm operation, đóng vai trò "merge commit" trong cây migration.
git merge feature-b
# conflict: cả 2 nhánh đều có 0023_xxx và 0023_yyy
python manage.py makemigrations --merge
git add posts/migrations/0024_merge_*.py
git commitProject có hàng trăm migration thì dùng squashmigrations để gộp lại thành 1 file:
python manage.py squashmigrations posts 0001 0050
# Sinh 0001_squashed_0050.py, giữ file cũ với marker replaces=[...]Đừng xoá file migration cũ khỏi git ngay sau khi squash — môi trường khác đang ở 0030 cần đường đi từ 0030 → squashed.
- Squash xong phải đợi mọi environment migrate hết rồi mới xoá file cũ ở PR sau.
- Migration có
RunPythoncũng không squash tự động được — phải merge thủ công hoặc giữ nguyên.
Each migration in the same app has a sequence number (0023_.py) and dependencies pointing to a parent migration. When two branches each create a migration from 0022 → both become 0023_.py → git merge → Django sees two parallel leaves → python manage.py migrate does not know which path to take → reports InconsistentMigrationHistory.
Fix: run python manage.py makemigrations --merge → Django generates *0024_merge_.py** containing only dependencies = [0023_a, 0023_b], no operations — acting as the "merge commit" in the migration tree.
git merge feature-b
# conflict: both branches have 0023_xxx and 0023_yyy
python manage.py makemigrations --merge
git add posts/migrations/0024_merge_*.py
git commitWhen a project has hundreds of migrations → squashmigrations collapses them into a new single file:
python manage.py squashmigrations posts 0001 0050
# Generates 0001_squashed_0050.py, keeps old files with a replaces=[...] markerPitfall: Do not delete the old migration files from git right after squashing — other environments still sit at 0030 and need a path from 0030 → squashed.
- Wait until every environment has migrated, then remove the old files in a follow-up PR.
- And migrations containing
RunPythoncannot be auto-squashed → merge them manually or keep as-is.