diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py index a5b7cce393..d459f2c524 100644 --- a/django/db/migrations/loader.py +++ b/django/db/migrations/loader.py @@ -280,6 +280,11 @@ class MigrationLoader(object): continue for parent in self.graph.node_map[migration].parents: if parent not in applied: + # Skip unapplied squashed migrations that have all of their + # `replaces` applied. + if parent in self.replacements: + if all(m in applied for m in self.replacements[parent].replaces): + continue raise InconsistentMigrationHistory( "Migration {}.{} is applied before its dependency {}.{}".format( migration[0], migration[1], parent[0], parent[1], diff --git a/docs/releases/1.10.1.txt b/docs/releases/1.10.1.txt index 8f0756bb9e..89fc2b2b19 100644 --- a/docs/releases/1.10.1.txt +++ b/docs/releases/1.10.1.txt @@ -29,3 +29,7 @@ Bugfixes * Fixed the ``isnull`` lookup on a ``ForeignKey`` with its ``to_field`` pointing to a ``CharField`` (:ticket:`26983`). + +* Prevented the ``migrate`` command from raising + ``InconsistentMigrationHistory`` in the presence of unapplied squashed + migrations (:ticket:`27004`). diff --git a/tests/migrations/test_loader.py b/tests/migrations/test_loader.py index 0b014f7d57..c97cddb913 100644 --- a/tests/migrations/test_loader.py +++ b/tests/migrations/test_loader.py @@ -381,6 +381,23 @@ class LoaderTests(TestCase): with self.assertRaisesMessage(InconsistentMigrationHistory, msg): loader.check_consistent_history(connection) + @override_settings( + MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed_extra'}, + INSTALLED_APPS=['migrations'], + ) + def test_check_consistent_history_squashed(self): + """ + MigrationLoader.check_consistent_history() should ignore unapplied + squashed migrations that have all of their `replaces` applied. + """ + loader = MigrationLoader(connection=None) + recorder = MigrationRecorder(connection) + recorder.record_applied('migrations', '0001_initial') + recorder.record_applied('migrations', '0002_second') + loader.check_consistent_history(connection) + recorder.record_applied('migrations', '0003_third') + loader.check_consistent_history(connection) + @override_settings(MIGRATION_MODULES={ "app1": "migrations.test_migrations_squashed_ref_squashed.app1", "app2": "migrations.test_migrations_squashed_ref_squashed.app2", diff --git a/tests/migrations/test_migrations_squashed_extra/0001_initial.py b/tests/migrations/test_migrations_squashed_extra/0001_initial.py new file mode 100644 index 0000000000..9a330e1067 --- /dev/null +++ b/tests/migrations/test_migrations_squashed_extra/0001_initial.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + pass diff --git a/tests/migrations/test_migrations_squashed_extra/0001_squashed_0002.py b/tests/migrations/test_migrations_squashed_extra/0001_squashed_0002.py new file mode 100644 index 0000000000..79beebea1c --- /dev/null +++ b/tests/migrations/test_migrations_squashed_extra/0001_squashed_0002.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + replaces = [ + ("migrations", "0001_initial"), + ("migrations", "0002_second"), + ] diff --git a/tests/migrations/test_migrations_squashed_extra/0002_second.py b/tests/migrations/test_migrations_squashed_extra/0002_second.py new file mode 100644 index 0000000000..4b892a7e8b --- /dev/null +++ b/tests/migrations/test_migrations_squashed_extra/0002_second.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [("migrations", "0001_initial")] diff --git a/tests/migrations/test_migrations_squashed_extra/0003_third.py b/tests/migrations/test_migrations_squashed_extra/0003_third.py new file mode 100644 index 0000000000..b69ae8883b --- /dev/null +++ b/tests/migrations/test_migrations_squashed_extra/0003_third.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [("migrations", "0002_second")] diff --git a/tests/migrations/test_migrations_squashed_extra/__init__.py b/tests/migrations/test_migrations_squashed_extra/__init__.py new file mode 100644 index 0000000000..e69de29bb2