diff --git a/django/db/migrations/optimizer.py b/django/db/migrations/optimizer.py
index caf0798b2e..f5179a8286 100644
--- a/django/db/migrations/optimizer.py
+++ b/django/db/migrations/optimizer.py
@@ -53,6 +53,26 @@ class MigrationOptimizer(object):
                 migrations.DeleteModel,
                 self.reduce_model_alter_delete,
             ),
+            (
+                migrations.AlterModelTable,
+                migrations.AlterModelTable,
+                self.reduce_model_alter_alter,
+            ),
+            (
+                migrations.AlterUniqueTogether,
+                migrations.AlterUniqueTogether,
+                self.reduce_model_alter_alter,
+            ),
+            (
+                migrations.AlterIndexTogether,
+                migrations.AlterIndexTogether,
+                self.reduce_model_alter_alter,
+            ),
+            (
+                migrations.AlterOrderWithRespectTo,
+                migrations.AlterOrderWithRespectTo,
+                self.reduce_model_alter_alter,
+            ),
             (
                 migrations.CreateModel,
                 migrations.RenameModel,
@@ -206,6 +226,14 @@ class MigrationOptimizer(object):
         if operation.name_lower == other.name_lower:
             return [other]
 
+    def reduce_model_alter_alter(self, operation, other, in_between):
+        """
+        Folds two AlterModelTable, AlterFooTogether, or AlterOrderWithRespectTo
+        operations into the latter.
+        """
+        if operation.name_lower == other.name_lower:
+            return [other]
+
     def reduce_model_create_rename(self, operation, other, in_between):
         """
         Folds a model rename into its create
diff --git a/tests/migrations/test_optimizer.py b/tests/migrations/test_optimizer.py
index b22905b033..faf297b5e7 100644
--- a/tests/migrations/test_optimizer.py
+++ b/tests/migrations/test_optimizer.py
@@ -117,6 +117,45 @@ class OptimizerTests(SimpleTestCase):
     def test_create_alter_owrt_delete_model(self):
         self._test_create_alter_foo_delete_model(migrations.AlterOrderWithRespectTo("Foo", "a"))
 
+    def _test_alter_alter_model(self, alter_foo, alter_bar):
+        """
+        Two AlterUniqueTogether/AlterIndexTogether/AlterOrderWithRespectTo
+        should collapse into the second.
+        """
+        self.assertOptimizesTo(
+            [
+                alter_foo,
+                alter_bar,
+            ],
+            [
+                alter_bar,
+            ],
+        )
+
+    def test_alter_alter_table_model(self):
+        self._test_alter_alter_model(
+            migrations.AlterModelTable("Foo", "a"),
+            migrations.AlterModelTable("Foo", "b"),
+        )
+
+    def test_alter_alter_unique_model(self):
+        self._test_alter_alter_model(
+            migrations.AlterUniqueTogether("Foo", [["a", "b"]]),
+            migrations.AlterUniqueTogether("Foo", [["a", "c"]]),
+        )
+
+    def test_alter_alter_index_model(self):
+        self._test_alter_alter_model(
+            migrations.AlterIndexTogether("Foo", [["a", "b"]]),
+            migrations.AlterIndexTogether("Foo", [["a", "c"]]),
+        )
+
+    def test_alter_alter_owrt_model(self):
+        self._test_alter_alter_model(
+            migrations.AlterOrderWithRespectTo("Foo", "a"),
+            migrations.AlterOrderWithRespectTo("Foo", "b"),
+        )
+
     def test_optimize_through_create(self):
         """
         We should be able to optimize away create/delete through a create or delete