From 04e4f80c1fe9b5ad73c982746e4ccee3bd0d803e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Freitag?= <mail@franek.fr>
Date: Sun, 26 Apr 2020 18:24:43 +0200
Subject: [PATCH] Sorted conflicting migrations by names.

---
 django/db/migrations/loader.py    |  2 +-
 tests/migrations/test_commands.py | 37 +++++++++++++++----------------
 2 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py
index f0f0a42de3..cb61aeca16 100644
--- a/django/db/migrations/loader.py
+++ b/django/db/migrations/loader.py
@@ -317,7 +317,7 @@ class MigrationLoader:
             if app_label in seen_apps:
                 conflicting_apps.add(app_label)
             seen_apps.setdefault(app_label, set()).add(migration_name)
-        return {app_label: seen_apps[app_label] for app_label in conflicting_apps}
+        return {app_label: sorted(seen_apps[app_label]) for app_label in conflicting_apps}
 
     def project_state(self, nodes=None, at_end=True):
         """
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 78cada9106..fb620aab9a 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -247,7 +247,13 @@ class MigrateTests(MigrationTestBase):
         """
         migrate exits if it detects a conflict.
         """
-        with self.assertRaisesMessage(CommandError, "Conflicting migrations detected"):
+        msg = (
+            "Conflicting migrations detected; multiple leaf nodes in the "
+            "migration graph: (0002_conflicting_second, 0002_second in "
+            "migrations).\n"
+            "To fix them run 'python manage.py makemigrations --merge'"
+        )
+        with self.assertRaisesMessage(CommandError, msg):
             call_command("migrate", "migrations")
 
     @override_settings(MIGRATION_MODULES={
@@ -1066,16 +1072,13 @@ class MakeMigrationsTests(MigrationTestBase):
         with self.temporary_migration_module(module="migrations.test_migrations_conflict"):
             with self.assertRaises(CommandError) as context:
                 call_command("makemigrations")
-        exception_message = str(context.exception)
-        self.assertIn(
-            'Conflicting migrations detected; multiple leaf nodes '
-            'in the migration graph:',
-            exception_message
+        self.assertEqual(
+            str(context.exception),
+            "Conflicting migrations detected; multiple leaf nodes in the "
+            "migration graph: (0002_conflicting_second, 0002_second in "
+            "migrations).\n"
+            "To fix them run 'python manage.py makemigrations --merge'"
         )
-        self.assertIn('0002_second', exception_message)
-        self.assertIn('0002_conflicting_second', exception_message)
-        self.assertIn('in migrations', exception_message)
-        self.assertIn("To fix them run 'python manage.py makemigrations --merge'", exception_message)
 
     def test_makemigrations_merge_no_conflict(self):
         """
@@ -1488,20 +1491,16 @@ class MakeMigrationsTests(MigrationTestBase):
                     "makemigrations", "conflicting_app_with_dependencies",
                     merge=True, interactive=True, stdout=out
                 )
-            val = out.getvalue().lower()
-            self.assertIn('merging conflicting_app_with_dependencies\n', val)
-            self.assertIn(
+            self.assertEqual(
+                out.getvalue().lower(),
+                'merging conflicting_app_with_dependencies\n'
                 '  branch 0002_conflicting_second\n'
-                '    - create model something\n',
-                val
-            )
-            self.assertIn(
+                '    - create model something\n'
                 '  branch 0002_second\n'
                 '    - delete model tribble\n'
                 '    - remove field silly_field from author\n'
                 '    - add field rating to author\n'
-                '    - create model book\n',
-                val
+                '    - create model book\n'
             )
 
     def test_makemigrations_with_custom_name(self):