diff --git a/core/assets/scaffold/files/default.settings.php b/core/assets/scaffold/files/default.settings.php
index 1c8dbee9e7..8208086121 100644
--- a/core/assets/scaffold/files/default.settings.php
+++ b/core/assets/scaffold/files/default.settings.php
@@ -741,6 +741,19 @@
  */
 $settings['entity_update_backup'] = TRUE;
 
+/**
+ * Node migration type.
+ *
+ * This is used to force the migration system to use the classic node migrations
+ * instead of the default complete node migrations. The migration system will
+ * use the classic node migration only if there are existing migrate_map tables
+ * for the classic node migrations and they contain data. These tables may not
+ * exist if you are developing custom migrations and do not want to use the
+ * complete node migrations. Set this to TRUE to force the use of the classic
+ * node migrations.
+ */
+$settings['migrate_node_migrate_type_classic'] = FALSE;
+
 /**
  * Load local development override configuration, if available.
  *
diff --git a/core/modules/comment/migrations/d6_comment.yml b/core/modules/comment/migrations/d6_comment.yml
index e6b4e1295f..7f8e727aa4 100644
--- a/core/modules/comment/migrations/d6_comment.yml
+++ b/core/modules/comment/migrations/d6_comment.yml
@@ -24,9 +24,12 @@ process:
     -
       plugin: migration_lookup
       migration:
+        - d6_node_complete
         - d6_node
         - d6_node_translation
       source: nid
+    -
+      plugin: node_complete_node_lookup
     -
       plugin: skip_on_empty
       method: row
diff --git a/core/modules/comment/migrations/d7_comment.yml b/core/modules/comment/migrations/d7_comment.yml
index eafa8e36ec..a27523f565 100644
--- a/core/modules/comment/migrations/d7_comment.yml
+++ b/core/modules/comment/migrations/d7_comment.yml
@@ -25,9 +25,12 @@ process:
     -
       plugin: migration_lookup
       migration:
+        - d7_node_complete
         - d7_node
         - d7_node_translation
       source: nid
+    -
+      plugin: node_complete_node_lookup
     -
       plugin: skip_on_empty
       method: row
diff --git a/core/modules/content_translation/migrations/d6_entity_reference_translation.yml b/core/modules/content_translation/migrations/d6_entity_reference_translation.yml
index 87150ec395..945b2fa9d2 100644
--- a/core/modules/content_translation/migrations/d6_entity_reference_translation.yml
+++ b/core/modules/content_translation/migrations/d6_entity_reference_translation.yml
@@ -14,6 +14,7 @@ provider:
 target_types:
   node:
     - d6_node_translation
+    - d6_node_complete
 # The source plugin will be set by the deriver.
 source:
   plugin: empty
diff --git a/core/modules/content_translation/migrations/d6_term_node_translation.yml b/core/modules/content_translation/migrations/d6_term_node_translation.yml
index 8ce46e5e5d..9894b75e38 100644
--- a/core/modules/content_translation/migrations/d6_term_node_translation.yml
+++ b/core/modules/content_translation/migrations/d6_term_node_translation.yml
@@ -11,8 +11,12 @@ process:
   dest_nid:
     -
       plugin: migration_lookup
-      migration: d6_node_translation
+      migration:
+        - d6_node_complete
+        - d6_node_translation
       source: nid
+    -
+      plugin: node_complete_node_translation_lookup
     -
       plugin: skip_on_empty
       method: row
diff --git a/core/modules/content_translation/migrations/d7_entity_reference_translation.yml b/core/modules/content_translation/migrations/d7_entity_reference_translation.yml
index 2e8d548f0a..0856caf488 100644
--- a/core/modules/content_translation/migrations/d7_entity_reference_translation.yml
+++ b/core/modules/content_translation/migrations/d7_entity_reference_translation.yml
@@ -14,6 +14,7 @@ provider:
 target_types:
   node:
     - d7_node_translation
+    - d7_node_complete
 # The source plugin will be set by the deriver.
 source:
   plugin: empty
diff --git a/core/modules/content_translation/migrations/node_translation_menu_links.yml b/core/modules/content_translation/migrations/node_translation_menu_links.yml
index 466ed39931..d6809f8fa6 100644
--- a/core/modules/content_translation/migrations/node_translation_menu_links.yml
+++ b/core/modules/content_translation/migrations/node_translation_menu_links.yml
@@ -61,6 +61,8 @@ process:
       # d7_node_translation mapping tables to find the new node ID.
       plugin: migration_lookup
       migration:
+        - d6_node_complete
+        - d7_node_complete
         - d6_node_translation
         - d7_node_translation
       no_stub: true
diff --git a/core/modules/content_translation/migrations/state/content_translation.migrate_drupal.yml b/core/modules/content_translation/migrations/state/content_translation.migrate_drupal.yml
index 85a9914073..4e21859fcb 100644
--- a/core/modules/content_translation/migrations/state/content_translation.migrate_drupal.yml
+++ b/core/modules/content_translation/migrations/state/content_translation.migrate_drupal.yml
@@ -9,6 +9,8 @@ finished:
       - menu_link_content
     locale: content_translation
     menu: content_translation
+  # Node revision translations.
+    node: content_translation
     statistics: statistics
     taxonomy: content_translation
   7:
@@ -20,7 +22,8 @@ finished:
     locale: content_translation
     menu: content_translation
     statistics: statistics
-
+    # Node revision translations.
+    node: content_translation
 not_finished:
   # Also D6 and D7 node revision translations.
   6:
@@ -29,9 +32,6 @@ not_finished:
     i18n: content_translation
     # Taxonomy term references.
     i18ntaxonomy: content_translation
-    # Node revision translations.
-    # https://www.drupal.org/project/drupal/issues/2746541
-    node: content_translation
   7:
     # @TODO: Move to finished when remaining Drupal 7 i18n issues are resolved.
     # See https://www.drupal.org/project/drupal/issues/2208401
@@ -42,6 +42,3 @@ not_finished:
     # @TODO: Remove when taxonomy term field translations are migrated.
     # See https://www.drupal.org/project/drupal/issues/3073050
     i18n_taxonomy: content_translation
-    # Node revision translations.
-    # https://www.drupal.org/project/drupal/issues/2746541
-    node: content_translation
diff --git a/core/modules/migrate/src/Audit/IdAuditor.php b/core/modules/migrate/src/Audit/IdAuditor.php
index f482acd597..17f6ffe938 100644
--- a/core/modules/migrate/src/Audit/IdAuditor.php
+++ b/core/modules/migrate/src/Audit/IdAuditor.php
@@ -3,6 +3,7 @@
 namespace Drupal\migrate\Audit;
 
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\migrate\Plugin\migrate\destination\EntityContentComplete;
 use Drupal\migrate\Plugin\MigrationInterface;
 
 /**
@@ -33,11 +34,12 @@ public function audit(MigrationInterface $migration) {
       throw new AuditException($migration, "ID map does not implement $interface");
     }
 
-    if ($destination->getHighestId() > $id_map->getHighestId()) {
+    if ($destination->getHighestId() > $id_map->getHighestId() || ($destination instanceof EntityContentComplete && !$this->auditEntityComplete($migration))) {
       return AuditResult::fail($migration, [
         $this->t('The destination system contains data which was not created by a migration.'),
       ]);
     }
+
     return AuditResult::pass($migration);
   }
 
@@ -55,4 +57,44 @@ public function auditMultiple(array $migrations) {
     return $conflicts;
   }
 
+  /**
+   * Audits an EntityComplete migration.
+   *
+   * @param \Drupal\migrate\Plugin\MigrationInterface $migration
+   *   The migration to audit.
+   *
+   * @return bool
+   *   TRUE if the audit passes and FALSE if not.
+   *
+   * @todo Refactor in https://www.drupal.org/project/drupal/issues/3061676 or
+   *   https://www.drupal.org/project/drupal/issues/3091004
+   */
+  private function auditEntityComplete(MigrationInterface $migration) {
+    $map_table = $migration->getIdMap()->mapTableName();
+
+    $database = \Drupal::database();
+    if (!$database->schema()->tableExists($map_table)) {
+      throw new \InvalidArgumentException();
+    }
+
+    $query = $database->select($map_table, 'map')
+      ->fields('map', ['destid2'])
+      ->range(0, 1)
+      ->orderBy('destid2', 'DESC');
+    $max = (int) $query->execute()->fetchField();
+
+    // Make a migration based on node_complete but with an entity_revision
+    // destination.
+    $revision_migration = $migration->getPluginDefinition();
+    $revision_migration['id'] = $migration->getPluginId() . '-revision';
+    $revision_migration['destination']['plugin'] = 'entity_revision:node';
+    $revision_migration = \Drupal::service('plugin.manager.migration')->createStubMigration($revision_migration);
+
+    // Get the highest node revision ID.
+    $destination = $revision_migration->getDestinationPlugin();
+    $highest = $destination->getHighestId();
+
+    return $max <= $highest;
+  }
+
 }
diff --git a/core/modules/migrate/src/Plugin/Derivative/MigrateEntityComplete.php b/core/modules/migrate/src/Plugin/Derivative/MigrateEntityComplete.php
new file mode 100644
index 0000000000..c276a3a7b3
--- /dev/null
+++ b/core/modules/migrate/src/Plugin/Derivative/MigrateEntityComplete.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Drupal\migrate\Plugin\Derivative;
+
+use Drupal\migrate\Plugin\migrate\destination\EntityContentComplete;
+
+/**
+ * MigrateEntityComplete deriver.
+ */
+class MigrateEntityComplete extends MigrateEntity {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    foreach ($this->entityDefinitions as $entity_type => $entity_info) {
+      $this->derivatives[$entity_type] = [
+        'id' => "entity_complete:$entity_type",
+        'class' => EntityContentComplete::class,
+        'requirements_met' => 1,
+        'provider' => $entity_info->getProvider(),
+      ];
+    }
+    return $this->derivatives;
+  }
+
+}
diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentComplete.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentComplete.php
new file mode 100644
index 0000000000..88e44bab65
--- /dev/null
+++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentComplete.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace Drupal\migrate\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityChangedInterface;
+use Drupal\migrate\EntityFieldDefinitionTrait;
+use Drupal\migrate\Row;
+
+/**
+ * Provides a destination for migrating the entire entity revision table.
+ *
+ * @MigrateDestination(
+ *   id = "entity_complete",
+ *   deriver = "Drupal\migrate\Plugin\Derivative\MigrateEntityComplete"
+ * )
+ */
+class EntityContentComplete extends EntityContentBase {
+
+  use EntityFieldDefinitionTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids = [];
+    $id_key = $this->getKey('id');
+    $ids[$id_key] = $this->getDefinitionFromEntity($id_key);
+
+    $revision_key = $this->getKey('revision');
+    if ($revision_key) {
+      $ids[$revision_key] = $this->getDefinitionFromEntity($revision_key);
+    }
+
+    $langcode_key = $this->getKey('langcode');
+    if ($langcode_key) {
+      $ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
+    }
+
+    return $ids;
+  }
+
+  /**
+   * Gets the entity.
+   *
+   * @param \Drupal\migrate\Row $row
+   *   The row object.
+   * @param array $old_destination_id_values
+   *   The old destination IDs.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   The entity.
+   */
+  protected function getEntity(Row $row, array $old_destination_id_values) {
+    $revision_id = $old_destination_id_values
+      ? $old_destination_id_values[1]
+      : $row->getDestinationProperty($this->getKey('revision'));
+    // If we are re-running a migration with set revision IDs and the
+    // destination revision ID already exists then do not create a new revision.
+    if (!empty($revision_id) && ($entity = $this->storage->loadRevision($revision_id))) {
+      $entity->setNewRevision(FALSE);
+    }
+    elseif (($entity_id = $row->getDestinationProperty($this->getKey('id'))) && ($entity = $this->storage->load($entity_id))) {
+      // We want to create a new entity. Set enforceIsNew() FALSE is  necessary
+      // to properly save a new entity while setting the ID. Without it, the
+      // system would see that the ID is already set and assume it is an update.
+      $entity->enforceIsNew(FALSE);
+      // Intentionally create a new revision. Setting new revision TRUE here may
+      // not be necessary, it is done for clarity.
+      $entity->setNewRevision(TRUE);
+    }
+    else {
+      // Attempt to set the bundle.
+      if ($bundle = $this->getBundle($row)) {
+        $row->setDestinationProperty($this->getKey('bundle'), $bundle);
+      }
+
+      // Stubs might need some required fields filled in.
+      if ($row->isStub()) {
+        $this->processStubRow($row);
+      }
+      $entity = $this->storage->create($row->getDestination());
+      $entity->enforceIsNew();
+    }
+
+    // We need to update the entity, so that the destination row IDs are
+    // correct.
+    $entity = $this->updateEntity($entity, $row);
+    $entity->isDefaultRevision(TRUE);
+    if ($entity instanceof EntityChangedInterface && $entity instanceof ContentEntityInterface) {
+      // If we updated any untranslatable fields, update the timestamp for the
+      // other translations.
+      /** @var \Drupal\Core\Entity\ContentEntityInterface|\Drupal\Core\Entity\EntityChangedInterface $entity */
+      foreach ($entity->getTranslationLanguages() as $langcode => $language) {
+        // If we updated an untranslated field, then set the changed time for
+        // for all translations to match the current row that we are saving.
+        // In this context, getChangedTime() should return the value we just
+        // set in the updateEntity() call above.
+        if ($entity->getTranslation($langcode)->hasTranslationChanges()) {
+          $entity->getTranslation($langcode)->setChangedTime($entity->getChangedTime());
+        }
+      }
+    }
+    return $entity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function save(ContentEntityInterface $entity, array $old_destination_id_values = []) {
+    parent::save($entity, $old_destination_id_values);
+    return [
+      $entity->id(),
+      $entity->getRevisionId(),
+    ];
+  }
+
+}
diff --git a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
index 8c4f582805..d85c043dce 100644
--- a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
+++ b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php
@@ -3,6 +3,7 @@
 namespace Drupal\migrate\Plugin\migrate\id_map;
 
 use Drupal\Core\Database\DatabaseException;
+use Drupal\Core\Database\DatabaseExceptionWrapper;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Plugin\PluginBase;
@@ -600,7 +601,16 @@ public function lookupDestinationIds(array $source_id_values) {
       }
     }
 
-    return $query->execute()->fetchAll(\PDO::FETCH_NUM);
+    try {
+      return $query->execute()->fetchAll(\PDO::FETCH_NUM);
+    }
+    catch (DatabaseExceptionWrapper $e) {
+      // It's possible that the query will cause an exception to be thrown. For
+      // example, the URL alias migration uses a dummy node ID of 'INVALID_NID'
+      // to cause the lookup to return no results. On PostgreSQL this causes an
+      // exception because 'INVALID_NID' is not the expected type.
+      return [];
+    }
   }
 
   /**
diff --git a/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrate_no_migrate_drupal_test.info.yml b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrate_no_migrate_drupal_test.info.yml
new file mode 100644
index 0000000000..dfaccb76f9
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrate_no_migrate_drupal_test.info.yml
@@ -0,0 +1,8 @@
+name: 'Migrate No Migrate Drupal Test'
+type: module
+description: Provides fixture for testing without migrate_drupal.
+package: Testing
+version: VERSION
+dependencies:
+  - drupal:migrate
+  - drupal:node
diff --git a/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrate_no_migrate_drupal_test.routing.yml b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrate_no_migrate_drupal_test.routing.yml
new file mode 100644
index 0000000000..20e9f4d468
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrate_no_migrate_drupal_test.routing.yml
@@ -0,0 +1,7 @@
+migrate_no_migrate_drupal_test.execute:
+  path: '/migrate_no_migrate_drupal_test/execute'
+  defaults:
+    _controller: '\Drupal\migrate_no_migrate_drupal_test\Controller\ExecuteMigration::execute'
+    _title: 'Execute'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrations/node_migration_no_upgrade.yml b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrations/node_migration_no_upgrade.yml
new file mode 100644
index 0000000000..3630cbd4f6
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/migrations/node_migration_no_upgrade.yml
@@ -0,0 +1,22 @@
+id: node_migration_no_migate_drupal
+label: Node Migration No Migrate Drupal
+source:
+  plugin: embedded_data
+  data_rows:
+    -
+      id: 1
+      nid: 1
+      title: Node 1
+    -
+      id: 2
+      nid: 2
+      title: Node 2
+  ids:
+    id:
+      type: integer
+process:
+  nid: nid
+  title: title
+destination:
+  default_bundle: no_migrate_drupal
+  plugin: entity:node
diff --git a/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/src/Controller/ExecuteMigration.php b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/src/Controller/ExecuteMigration.php
new file mode 100644
index 0000000000..a25e63ab58
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_no_migrate_drupal_test/src/Controller/ExecuteMigration.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Drupal\migrate_no_migrate_drupal_test\Controller;
+
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Plugin\MigrationInterface;
+
+/**
+ * Class ExecuteMigration.
+ */
+class ExecuteMigration extends ControllerBase {
+
+  /**
+   * Display success.
+   *
+   * @return array
+   *   Return markup array.
+   */
+  public function execute() {
+    $migration_plugin_manager = \Drupal::service('plugin.manager.migration');
+    $definitions = $migration_plugin_manager->getDefinitions();
+    if ($definitions['node_migration_no_migate_drupal']['label'] !== 'Node Migration No Migrate Drupal') {
+      throw new InvalidPluginDefinitionException('node_migration_no_migate_drupal');
+    }
+    $migrations = $migration_plugin_manager->createInstances('');
+    $result = (new MigrateExecutable($migrations['node_migration_no_migate_drupal']))->import();
+    if ($result !== MigrationInterface::RESULT_COMPLETED) {
+      throw new \RuntimeException('Migration failed');
+    }
+
+    return [
+      '#type' => 'markup',
+      '#markup' => 'Migration was successful.',
+    ];
+  }
+
+}
diff --git a/core/modules/migrate/tests/src/Functional/MigrateNoMigrateDrupalTest.php b/core/modules/migrate/tests/src/Functional/MigrateNoMigrateDrupalTest.php
new file mode 100644
index 0000000000..91b8b08f12
--- /dev/null
+++ b/core/modules/migrate/tests/src/Functional/MigrateNoMigrateDrupalTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Drupal\Tests\migrate\Functional;
+
+use Drupal\node\Entity\Node;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
+
+/**
+ * Execute migration.
+ *
+ * @group migrate
+ */
+class MigrateNoMigrateDrupalTest extends BrowserTestBase {
+  use ContentTypeCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'migrate',
+    'migrate_no_migrate_drupal_test',
+    'node',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->createContentType(['type' => 'no_migrate_drupal']);
+  }
+
+  /**
+   * Tests execution of a migration.
+   */
+  public function testExecutionNoMigrateDrupal() {
+    $this->drupalGet('/migrate_no_migrate_drupal_test/execute');
+    $this->assertSession()->pageTextContains('Migration was successful.');
+    $node_1 = Node::load(1);
+    $node_2 = Node::load(2);
+    $this->assertEquals('Node 1', $node_1->label());
+    $this->assertEquals('Node 2', $node_2->label());
+  }
+
+}
diff --git a/core/modules/migrate_drupal/migrate_drupal.module b/core/modules/migrate_drupal/migrate_drupal.module
index 3f9439dd3b..f9bb4e7ac8 100644
--- a/core/modules/migrate_drupal/migrate_drupal.module
+++ b/core/modules/migrate_drupal/migrate_drupal.module
@@ -46,7 +46,8 @@ function migrate_drupal_migration_plugins_alter(&$definitions) {
       ],
     ];
     $vocabulary_migration = \Drupal::service('plugin.manager.migration')->createStubMigration($vocabulary_migration_definition);
-    $translation_active = \Drupal::service('module_handler')->moduleExists('content_translation');
+    $module_handler = \Drupal::service('module_handler');
+    $translation_active = $module_handler->moduleExists('content_translation');
 
     try {
       $source_plugin = $vocabulary_migration->getSourcePlugin();
@@ -89,6 +90,5 @@ function migrate_drupal_migration_plugins_alter(&$definitions) {
       // When the definitions are loaded it is possible the tables will not
       // exist.
     }
-
   }
 }
diff --git a/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php b/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php
index 8cb60347bc..4c3170ba70 100644
--- a/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php
+++ b/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php
@@ -121,8 +121,29 @@ protected function createDatabaseStateSettings(array $database, $drupal_version)
    */
   protected function getMigrations($database_state_key, $drupal_version) {
     $version_tag = 'Drupal ' . $drupal_version;
-    /** @var \Drupal\migrate\Plugin\Migration[] $all_migrations */
+    /** @var \Drupal\migrate\Plugin\MigrationInterface[] $all_migrations */
     $all_migrations = $this->getMigrationPluginManager()->createInstancesByTag($version_tag);
+
+    // Unset the node migrations that should not run based on the type of node
+    // migration. That is, if this is a complete node migration then unset the
+    // classic node migrations and if this is a classic node migration then
+    // unset the complete node migrations.
+    $type = NodeMigrateType::getNodeMigrateType(\Drupal::database(), $drupal_version);
+    switch ($type) {
+      case NodeMigrateType::NODE_MIGRATE_TYPE_COMPLETE:
+        $patterns = '/(d' . $drupal_version . '_node:)|(d' . $drupal_version . '_node_translation:)|(d' . $drupal_version . '_node_revision:)|(d7_node_entity_translation:)/';
+        break;
+
+      case NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC:
+        $patterns = '/(d' . $drupal_version . '_node_complete:)/';
+        break;
+    }
+    foreach ($all_migrations as $key => $migrations) {
+      if (preg_match($patterns, $key)) {
+        unset($all_migrations[$key]);
+      }
+    }
+
     $migrations = [];
     foreach ($all_migrations as $migration) {
       // Skip migrations tagged with any of the follow-up migration tags. They
@@ -185,7 +206,7 @@ protected function getFollowUpMigrationTags() {
    *   A string representing the major branch of Drupal core (e.g. '6' for
    *   Drupal 6.x), or FALSE if no valid version is matched.
    */
-  protected function getLegacyDrupalVersion(Connection $connection) {
+  public static function getLegacyDrupalVersion(Connection $connection) {
     // Don't assume because a table of that name exists, that it has the columns
     // we're querying. Catch exceptions and report that the source database is
     // not Drupal.
diff --git a/core/modules/migrate_drupal/src/NodeMigrateType.php b/core/modules/migrate_drupal/src/NodeMigrateType.php
new file mode 100644
index 0000000000..54ff90e9ac
--- /dev/null
+++ b/core/modules/migrate_drupal/src/NodeMigrateType.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace Drupal\migrate_drupal;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Site\Settings;
+
+/**
+ * Provides a class to determine the type of migration.
+ */
+final class NodeMigrateType {
+
+  use MigrationConfigurationTrait;
+
+  /**
+   * Only the complete node migration map tables are in use.
+   */
+  const NODE_MIGRATE_TYPE_COMPLETE = 'COMPLETE';
+
+  /**
+   * Only the classic node migration map tables are in use.
+   */
+  const NODE_MIGRATE_TYPE_CLASSIC = 'CLASSIC';
+
+  /**
+   * Determines the type of node migration to be used.
+   *
+   * The node complete migration is the default. It is not used when there
+   * are existing tables for dN_node.
+   *
+   * @param \Drupal\Core\Database\Connection $connection
+   *   The connection to the target database.
+   * @param string|false $version
+   *   The Drupal version of the source database, FALSE if it cannot be
+   *   determined.
+   *
+   * @return string
+   *   The migrate type.
+   *
+   * @internal
+   */
+  public static function getNodeMigrateType(Connection $connection, $version) {
+    $migrate_node_migrate_type_classic = Settings::get('migrate_node_migrate_type_classic', FALSE);
+    if ($migrate_node_migrate_type_classic) {
+      return static::NODE_MIGRATE_TYPE_CLASSIC;
+    }
+
+    $migrate_type = static::NODE_MIGRATE_TYPE_COMPLETE;
+    if ($version) {
+      // Create the variable name, 'node_has_rows' or 'node_complete_exists' and
+      // set it the default value, FALSE.
+      $node_has_rows = FALSE;
+      $node_complete_has_rows = FALSE;
+
+      // Find out what migrate map tables have rows for the node migrations.
+      // It is either the classic, 'dN_node', or the complete,
+      // 'dN_node_complete', or both. This is used to determine which migrations
+      // are run and if migrations using the node migrations in a
+      // migration_lookup are altered.
+      $bases = ['node', 'node_complete'];
+      $tables = $connection->schema()
+        ->findTables('migrate_map_d' . $version . '_node%');
+      foreach ($bases as $base) {
+        $has_rows = $base . '_has_rows';
+        $base_tables = preg_grep('/^migrate_map_d' . $version . '_' . $base . '_{2}.*$/', $tables);
+        // Set the has_rows True when a map table has rows with a positive
+        // count for the matched migration.
+        foreach ($base_tables as $base_table) {
+          if ($connection->schema()->tableExists($base_table)) {
+            $count = $connection->select($base_table)->countQuery()
+              ->execute()->fetchField();
+            if ($count > 0) {
+              $$has_rows = TRUE;
+              break;
+            }
+          }
+        }
+      }
+
+      // Set the node migration type to use.
+      if ($node_has_rows && !$node_complete_has_rows) {
+        $migrate_type = static::NODE_MIGRATE_TYPE_CLASSIC;
+      }
+    }
+    return $migrate_type;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeLookup.php b/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeLookup.php
new file mode 100644
index 0000000000..bd5e5d069d
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeLookup.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Returns only the nid from migration_lookup on node_complete migration.
+ *
+ * It is possible that migration_lookups that use the classic node migrations
+ * in the migration key have been altered to include the complete node
+ * migration. The classic node migration and complete node migration have a
+ * different number of destination keys. This process plugin will ensure that
+ * when the complete node migration is used in the lookup the nid value is
+ * returned. This keeps the behaviour the same as the classic node migration.
+ *
+ * @see \Drupal\migrate\Plugin\MigrateProcessInterface
+ *
+ * @MigrateProcessPlugin(
+ *   id = "node_complete_node_lookup"
+ * )
+ */
+class NodeCompleteNodeLookup extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value) && count($value) === 3) {
+      return $value[0];
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeRevisionLookup.php b/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeRevisionLookup.php
new file mode 100644
index 0000000000..7416e6561a
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeRevisionLookup.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Returns only the vid from migration_lookup on node_complete migration.
+ *
+ * It is possible that migration_lookups that use the classic node migrations
+ * in the migration key have been altered to include the complete node
+ * migration. The classic node migration and complete node migration have a
+ * different number of destination keys. This process plugin will ensure that
+ * when the complete node migration is used in the lookup the vid value is
+ * returned. This keeps the behaviour the same as the classic node migration.
+ *
+ * @see \Drupal\migrate\Plugin\MigrateProcessInterface
+ *
+ * @MigrateProcessPlugin(
+ *   id = "node_complete_node_revision_lookup"
+ * )
+ */
+class NodeCompleteNodeRevisionLookup extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value) && count($value) === 3) {
+      return $value[1];
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeTranslationLookup.php b/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeTranslationLookup.php
new file mode 100644
index 0000000000..671d9fe708
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/process/NodeCompleteNodeTranslationLookup.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Returns nid and langcode from migration_lookup on node_complete migration.
+ *
+ * It is possible that migration_lookups that use the classic node migrations
+ * in the migration key have been altered to include the complete node
+ * migration. The classic node migration and complete node migration have a
+ * different number of destination keys. This process plugin will ensure that
+ * when the complete node migration is used in the lookup the nid and langcode
+ * values are returned. This keeps the behaviour the same as the classic node
+ * migration.
+ *
+ * @see \Drupal\migrate\Plugin\MigrateProcessInterface
+ *
+ * @MigrateProcessPlugin(
+ *   id = "node_complete_node_translation_lookup"
+ * )
+ */
+class NodeCompleteNodeTranslationLookup extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value) && count($value) === 3) {
+      unset($value[1]);
+      return array_values($value);
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php
index e80de1b7f8..a2f38d180c 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/ContentEntity.php
@@ -265,6 +265,10 @@ public function fields() {
   public function getIds() {
     $id_key = $this->entityType->getKey('id');
     $ids[$id_key] = $this->getDefinitionFromEntity($id_key);
+    if ($this->entityType->isRevisionable()) {
+      $revision_key = $this->entityType->getKey('revision');
+      $ids[$revision_key] = $this->getDefinitionFromEntity($revision_key);
+    }
     if ($this->entityType->isTranslatable()) {
       $langcode_key = $this->entityType->getKey('langcode');
       $ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal6.php b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
index ca641233d9..a6e4ab7610 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal6.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
@@ -44473,10 +44473,10 @@
   'vid' => '1',
   'type' => 'story',
   'language' => '',
-  'title' => 'Test title',
+  'title' => 'Test title rev 3',
   'uid' => '1',
   'status' => '1',
-  'created' => '1388271197',
+  'created' => '1390095702',
   'changed' => '1420861423',
   'comment' => '0',
   'promote' => '0',
@@ -44507,7 +44507,7 @@
   'vid' => '4',
   'type' => 'test_planet',
   'language' => '',
-  'title' => 'Test planet title 3',
+  'title' => 'Test page title rev 4',
   'uid' => '1',
   'status' => '1',
   'created' => '1388271527',
@@ -44524,7 +44524,7 @@
   'vid' => '6',
   'type' => 'test_planet',
   'language' => '',
-  'title' => '',
+  'title' => 'Node 4',
   'uid' => '1',
   'status' => '1',
   'created' => '1388271527',
@@ -44541,7 +44541,7 @@
   'vid' => '7',
   'type' => 'test_planet',
   'language' => '',
-  'title' => '',
+  'title' => 'Node 5',
   'uid' => '1',
   'status' => '1',
   'created' => '1388271527',
@@ -44558,7 +44558,7 @@
   'vid' => '8',
   'type' => 'test_planet',
   'language' => '',
-  'title' => '',
+  'title' => 'Node 6',
   'uid' => '1',
   'status' => '1',
   'created' => '1388271527',
@@ -44575,7 +44575,7 @@
   'vid' => '9',
   'type' => 'test_planet',
   'language' => '',
-  'title' => '',
+  'title' => 'Node 7',
   'uid' => '1',
   'status' => '1',
   'created' => '1388271527',
@@ -44592,7 +44592,7 @@
   'vid' => '10',
   'type' => 'test_planet',
   'language' => '',
-  'title' => '',
+  'title' => 'Node 8',
   'uid' => '1',
   'status' => '1',
   'created' => '1388271527',
@@ -45288,7 +45288,7 @@
   'body' => 'test',
   'teaser' => 'test',
   'log' => '',
-  'timestamp' => '1420861423',
+  'timestamp' => '1390095702',
   'format' => '1',
 ))
 ->values(array(
@@ -45317,10 +45317,10 @@
   'nid' => '1',
   'vid' => '5',
   'uid' => '1',
-  'title' => 'Test title rev 3',
-  'body' => 'body test rev 3',
-  'teaser' => 'teaser test rev 3',
-  'log' => 'modified rev 3',
+  'title' => 'Test title rev 2',
+  'body' => 'body test rev 2',
+  'teaser' => 'teaser test rev 2',
+  'log' => 'modified rev 2',
   'timestamp' => '1390095703',
   'format' => '1',
 ))
@@ -45526,11 +45526,11 @@
   'nid' => '1',
   'vid' => '2001',
   'uid' => '2',
-  'title' => 'Test title rev 2',
-  'body' => 'body test rev 2',
-  'teaser' => 'teaser test rev 2',
-  'log' => 'modified rev 2',
-  'timestamp' => '1390095702',
+  'title' => 'Test title rev 3',
+  'body' => 'body test rev 3',
+  'teaser' => 'teaser test rev 3',
+  'log' => 'modified rev 3',
+  'timestamp' => '1420861423',
   'format' => '1',
 ))
 ->values(array(
@@ -49670,29 +49670,29 @@
   'value' => 'i:0;',
 ))
 ->values(array(
-  'name' => 'i18n_newnode_current_employee',
+  'name' => 'i18n_lock_node_sponsor',
   'value' => 'i:0;',
 ))
 ->values(array(
-  'name' => 'i18n_node_employee',
-  'value' => 's:1:"1";',
-))
-->values(array(
-  'name' => 'i18n_required_node_employee',
+  'name' => 'i18n_newnode_current_employee',
   'value' => 'i:0;',
 ))
 ->values(array(
-  'name' => 'i18n_lock_node_sponsor',
+  'name' => 'i18n_newnode_current_sponsor',
   'value' => 'i:0;',
 ))
 ->values(array(
-  'name' => 'i18n_newnode_current_sponsor',
-  'value' => 'i:0;',
+  'name' => 'i18n_node_employee',
+  'value' => 's:1:"1";',
 ))
 ->values(array(
   'name' => 'i18n_node_sponsor',
   'value' => 'i:1;',
 ))
+->values(array(
+  'name' => 'i18n_required_node_employee',
+  'value' => 'i:0;',
+))
 ->values(array(
   'name' => 'i18n_required_node_sponsor',
   'value' => 'i:0;',
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal7.php b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
index 8df6422c67..a44a0a457c 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal7.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
@@ -5117,7 +5117,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'body_value' => "...is that it's the absolute best show ever. Trust me, I would know.",
@@ -5129,7 +5129,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
   'body_value' => "is - ...is that it's the absolute best show ever. Trust me, I would know.",
@@ -6994,23 +6994,23 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'field_link_url' => '<front>',
-  'field_link_title' => 'Home',
-  'field_link_attributes' => 'a:0:{}',
+  'field_link_title' => NULL,
+  'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}',
 ))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
   'field_link_url' => '<front>',
-  'field_link_title' => 'Home',
+  'field_link_title' => NULL,
   'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}',
 ))
 ->execute();
@@ -7622,7 +7622,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'field_reference_target_id' => '5',
@@ -7632,7 +7632,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
   'field_reference_target_id' => '4',
@@ -7642,7 +7642,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '4',
-  'revision_id' => '4',
+  'revision_id' => '13',
   'language' => 'und',
   'delta' => '0',
   'field_reference_target_id' => '3',
@@ -7652,7 +7652,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '5',
-  'revision_id' => '5',
+  'revision_id' => '14',
   'language' => 'und',
   'delta' => '0',
   'field_reference_target_id' => '2',
@@ -7758,7 +7758,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'field_reference_2_target_id' => '5',
@@ -7768,7 +7768,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
   'field_reference_2_target_id' => '4',
@@ -7778,7 +7778,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '4',
-  'revision_id' => '4',
+  'revision_id' => '13',
   'language' => 'und',
   'delta' => '0',
   'field_reference_2_target_id' => '3',
@@ -7788,7 +7788,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '5',
-  'revision_id' => '5',
+  'revision_id' => '14',
   'language' => 'und',
   'delta' => '0',
   'field_reference_2_target_id' => '2',
@@ -7871,7 +7871,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'field_tags_tid' => '9',
@@ -7881,7 +7881,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
   'field_tags_tid' => '9',
@@ -7891,7 +7891,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '1',
   'field_tags_tid' => '14',
@@ -7901,7 +7901,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '1',
   'field_tags_tid' => '14',
@@ -7911,7 +7911,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '2',
   'field_tags_tid' => '17',
@@ -7921,7 +7921,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '2',
   'field_tags_tid' => '17',
@@ -8579,6 +8579,63 @@
   ),
   'mysql_character_set' => 'utf8',
 ));
+$connection->insert('field_data_field_text_long_plain')
+->fields(array(
+  'entity_type',
+  'bundle',
+  'deleted',
+  'entity_id',
+  'revision_id',
+  'language',
+  'delta',
+  'field_text_long_plain_value',
+  'field_text_long_plain_format',
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'DS9 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'is - DS9 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '4',
+  'revision_id' => '13',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'is - Firefly 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '5',
+  'revision_id' => '14',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'Firefly 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->execute();
 
 $connection->schema()->createTable('field_data_field_text_long_plain_filtered', array(
   'fields' => array(
@@ -8779,7 +8836,7 @@
     'bundle' => 'article',
     'deleted' => '0',
     'entity_id' => '2',
-    'revision_id' => '2',
+    'revision_id' => '11',
     'language' => 'und',
     'delta' => '0',
     'field_text_plain_value' => 'Kai Opaka',
@@ -8790,7 +8847,7 @@
     'bundle' => 'article',
     'deleted' => '0',
     'entity_id' => '3',
-    'revision_id' => '3',
+    'revision_id' => '12',
     'language' => 'und',
     'delta' => '0',
     'field_text_plain_value' => 'Kai Opaka',
@@ -9382,7 +9439,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'field_vocab_fixed_tid' => '24',
@@ -9488,7 +9545,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'field_vocab_localize_tid' => '20',
@@ -9498,7 +9555,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
   'field_vocab_localize_tid' => '20',
@@ -9604,7 +9661,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '2',
-  'revision_id' => '2',
+  'revision_id' => '11',
   'language' => 'und',
   'delta' => '0',
   'field_vocab_translate_tid' => '21',
@@ -9614,7 +9671,7 @@
   'bundle' => 'article',
   'deleted' => '0',
   'entity_id' => '3',
-  'revision_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
   'field_vocab_translate_tid' => '23',
@@ -10275,6 +10332,18 @@
   'body_summary' => '',
   'body_format' => 'filtered_html',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'body_value' => "...is that it's the absolute best show ever. Trust me, I would know.",
+  'body_summary' => '',
+  'body_format' => 'filtered_html',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -10291,11 +10360,11 @@
   'entity_type' => 'node',
   'bundle' => 'article',
   'deleted' => '0',
-  'entity_id' => '4',
-  'revision_id' => '4',
+  'entity_id' => '3',
+  'revision_id' => '12',
   'language' => 'und',
   'delta' => '0',
-  'body_value' => 'is - Is that is it awesome.',
+  'body_value' => "is - ...is that it's the absolute best show ever. Trust me, I would know.",
   'body_summary' => '',
   'body_format' => 'filtered_html',
 ))
@@ -10303,11 +10372,11 @@
   'entity_type' => 'node',
   'bundle' => 'article',
   'deleted' => '0',
-  'entity_id' => '5',
-  'revision_id' => '5',
+  'entity_id' => '4',
+  'revision_id' => '4',
   'language' => 'und',
   'delta' => '0',
-  'body_value' => 'en - Is that is it awesome.',
+  'body_value' => 'is - Is that is it awesome.',
   'body_summary' => '',
   'body_format' => 'filtered_html',
 ))
@@ -12180,8 +12249,20 @@
   'language' => 'und',
   'delta' => '0',
   'field_link_url' => '<front>',
+  'field_link_title' => 'Home;',
+  'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}',
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_link_url' => '<front>',
   'field_link_title' => 'Home',
-  'field_link_attributes' => 'a:0:{}',
+  'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}',
 ))
 ->values(array(
   'entity_type' => 'node',
@@ -12195,6 +12276,18 @@
   'field_link_title' => 'Home',
   'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_link_url' => '<front>',
+  'field_link_title' => 'Home',
+  'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}',
+))
 ->execute();
 $connection->schema()->createTable('field_revision_field_long_text', array(
   'fields' => array(
@@ -12825,6 +12918,16 @@
   'delta' => '0',
   'field_reference_target_id' => '5',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_target_id' => '5',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -12835,6 +12938,16 @@
   'delta' => '0',
   'field_reference_target_id' => '4',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_target_id' => '4',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -12845,6 +12958,16 @@
   'delta' => '0',
   'field_reference_target_id' => '3',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '4',
+  'revision_id' => '13',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_target_id' => '3',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -12855,6 +12978,16 @@
   'delta' => '0',
   'field_reference_target_id' => '2',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '5',
+  'revision_id' => '14',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_target_id' => '2',
+))
 ->execute();
 $connection->schema()->createTable('field_revision_field_reference_2', array(
   'fields' => array(
@@ -12962,6 +13095,16 @@
   'delta' => '0',
   'field_reference_2_target_id' => '5',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_2_target_id' => '5',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -12972,6 +13115,16 @@
   'delta' => '0',
   'field_reference_2_target_id' => '4',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_2_target_id' => '4',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -12982,6 +13135,16 @@
   'delta' => '0',
   'field_reference_2_target_id' => '3',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '4',
+  'revision_id' => '13',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_2_target_id' => '3',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -12992,6 +13155,16 @@
   'delta' => '0',
   'field_reference_2_target_id' => '2',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '5',
+  'revision_id' => '14',
+  'language' => 'und',
+  'delta' => '0',
+  'field_reference_2_target_id' => '2',
+))
 ->execute();
 $connection->schema()->createTable('field_revision_field_tags', array(
   'fields' => array(
@@ -13066,6 +13239,16 @@
   'delta',
   'field_tags_tid',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_tags_tid' => '9',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -13076,6 +13259,16 @@
   'delta' => '0',
   'field_tags_tid' => '9',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_tags_tid' => '9',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -13086,6 +13279,16 @@
   'delta' => '0',
   'field_tags_tid' => '9',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '1',
+  'field_tags_tid' => '14',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -13096,6 +13299,16 @@
   'delta' => '1',
   'field_tags_tid' => '14',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '1',
+  'field_tags_tid' => '14',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -13116,6 +13329,16 @@
   'delta' => '2',
   'field_tags_tid' => '17',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '2',
+  'field_tags_tid' => '17',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -13126,6 +13349,16 @@
   'delta' => '2',
   'field_tags_tid' => '17',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '2',
+  'field_tags_tid' => '17',
+))
 ->execute();
 $connection->schema()->createTable('field_revision_field_term_entityreference', array(
   'fields' => array(
@@ -13786,6 +14019,96 @@
   ),
   'mysql_character_set' => 'utf8',
 ));
+$connection->insert('field_revision_field_text_long_plain')
+->fields(array(
+  'entity_type',
+  'bundle',
+  'deleted',
+  'entity_id',
+  'revision_id',
+  'language',
+  'delta',
+  'field_text_long_plain_value',
+  'field_text_long_plain_format',
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '2',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'DS9 1st rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'DS9 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '3',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'is - DS9 1st rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'is - DS9 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '4',
+  'revision_id' => '13',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'is - Firefly 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '5',
+  'revision_id' => '5',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'Firefly 1st rev',
+  'field_text_long_plain_format' => NULL,
+))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '5',
+  'revision_id' => '14',
+  'language' => 'und',
+  'delta' => '0',
+  'field_text_long_plain_value' => 'Firefly 2nd rev',
+  'field_text_long_plain_format' => NULL,
+))
+->execute();
 
 $connection->schema()->createTable('field_revision_field_text_long_plain_filtered', array(
   'fields' => array(
@@ -13987,7 +14310,7 @@
     'bundle' => 'article',
     'deleted' => '0',
     'entity_id' => '2',
-    'revision_id' => '2',
+    'revision_id' => '11',
     'language' => 'und',
     'delta' => '0',
     'field_text_plain_value' => 'Kai Opaka',
@@ -13998,7 +14321,7 @@
     'bundle' => 'article',
     'deleted' => '0',
     'entity_id' => '3',
-    'revision_id' => '3',
+    'revision_id' => '12',
     'language' => 'und',
     'delta' => '0',
     'field_text_plain_value' => 'Kai Opaka',
@@ -14579,6 +14902,16 @@
   'delta' => '0',
   'field_vocab_fixed_tid' => '24',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_vocab_fixed_tid' => '24',
+))
 ->execute();
 $connection->schema()->createTable('field_revision_field_vocab_localize', array(
   'fields' => array(
@@ -14686,6 +15019,16 @@
   'delta' => '0',
   'field_vocab_localize_tid' => '20',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_vocab_localize_tid' => '20',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -14696,6 +15039,16 @@
   'delta' => '0',
   'field_vocab_localize_tid' => '20',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_vocab_localize_tid' => '20',
+))
 ->execute();
 $connection->schema()->createTable('field_revision_field_vocab_translate', array(
   'fields' => array(
@@ -14803,6 +15156,16 @@
   'delta' => '0',
   'field_vocab_translate_tid' => '21',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '2',
+  'revision_id' => '11',
+  'language' => 'und',
+  'delta' => '0',
+  'field_vocab_translate_tid' => '21',
+))
 ->values(array(
   'entity_type' => 'node',
   'bundle' => 'article',
@@ -14813,6 +15176,16 @@
   'delta' => '0',
   'field_vocab_translate_tid' => '23',
 ))
+->values(array(
+  'entity_type' => 'node',
+  'bundle' => 'article',
+  'deleted' => '0',
+  'entity_id' => '3',
+  'revision_id' => '12',
+  'language' => 'und',
+  'delta' => '0',
+  'field_vocab_translate_tid' => '23',
+))
 ->execute();
 $connection->schema()->createTable('field_revision_name_field', array(
   'fields' => array(
@@ -40720,14 +41093,14 @@
 ))
 ->values(array(
   'nid' => '2',
-  'vid' => '2',
+  'vid' => '11',
   'type' => 'article',
   'language' => 'en',
   'title' => 'The thing about Deep Space 9',
   'uid' => '2',
   'status' => '1',
   'created' => '1441306772',
-  'changed' => '1441306832',
+  'changed' => '1564543637',
   'comment' => '2',
   'promote' => '1',
   'sticky' => '0',
@@ -40736,14 +41109,14 @@
 ))
 ->values(array(
   'nid' => '3',
-  'vid' => '3',
+  'vid' => '12',
   'type' => 'article',
   'language' => 'is',
   'title' => 'is - The thing about Deep Space 9',
   'uid' => '1',
   'status' => '1',
   'created' => '1471428152',
-  'changed' => '1471428152',
+  'changed' => '1564543706',
   'comment' => '2',
   'promote' => '1',
   'sticky' => '0',
@@ -40752,14 +41125,14 @@
 ))
 ->values(array(
   'nid' => '4',
-  'vid' => '4',
+  'vid' => '13',
   'type' => 'article',
   'language' => 'is',
   'title' => 'is - The thing about Firefly',
   'uid' => '1',
   'status' => '1',
   'created' => '1478755274',
-  'changed' => '1478755274',
+  'changed' => '1564543810',
   'comment' => '1',
   'promote' => '1',
   'sticky' => '0',
@@ -40768,14 +41141,14 @@
 ))
 ->values(array(
   'nid' => '5',
-  'vid' => '5',
+  'vid' => '14',
   'type' => 'article',
   'language' => 'en',
   'title' => 'en - The thing about Firefly',
   'uid' => '1',
   'status' => '1',
   'created' => '1478755314',
-  'changed' => '1478755314',
+  'changed' => '1564543929',
   'comment' => '1',
   'promote' => '1',
   'sticky' => '0',
@@ -41237,9 +41610,9 @@
   'nid' => '2',
   'vid' => '2',
   'uid' => '1',
-  'title' => 'The thing about Deep Space 9',
-  'log' => '',
-  'timestamp' => '1441306832',
+  'title' => 'The thing about Deep Space 9 (1st rev)',
+  'log' => 'DS9 1st rev',
+  'timestamp' => '1564543588',
   'status' => '1',
   'comment' => '2',
   'promote' => '1',
@@ -41249,9 +41622,9 @@
   'nid' => '3',
   'vid' => '3',
   'uid' => '1',
-  'title' => 'is - The thing about Deep Space 9',
-  'log' => '',
-  'timestamp' => '1471428152',
+  'title' => 'is - The thing about Deep Space 9 (1st rev)',
+  'log' => 'is - DS9 1st rev',
+  'timestamp' => '1564543677',
   'status' => '1',
   'comment' => '2',
   'promote' => '1',
@@ -41261,8 +41634,8 @@
   'nid' => '4',
   'vid' => '4',
   'uid' => '1',
-  'title' => 'is - The thing about Firefly',
-  'log' => '',
+  'title' => 'is - The thing about Firefly (1st rev)',
+  'log' => 'is - Firefly 1st rev',
   'timestamp' => '1478755274',
   'status' => '1',
   'comment' => '1',
@@ -41273,9 +41646,9 @@
   'nid' => '5',
   'vid' => '5',
   'uid' => '1',
-  'title' => 'en - The thing about Firefly',
-  'log' => '',
-  'timestamp' => '1478755314',
+  'title' => 'en - The thing about Firefly (1st rev)',
+  'log' => 'Firefly 1st rev',
+  'timestamp' => '1564543887',
   'status' => '1',
   'comment' => '1',
   'promote' => '1',
@@ -41341,6 +41714,54 @@
   'promote' => '1',
   'sticky' => '0',
 ))
+->values(array(
+  'nid' => '2',
+  'vid' => '11',
+  'uid' => '1',
+  'title' => 'The thing about Deep Space 9',
+  'log' => 'DS9 2nd rev',
+  'timestamp' => '1564543637',
+  'status' => '1',
+  'comment' => '2',
+  'promote' => '1',
+  'sticky' => '0',
+))
+->values(array(
+  'nid' => '3',
+  'vid' => '12',
+  'uid' => '1',
+  'title' => 'is - The thing about Deep Space 9',
+  'log' => 'is - DS9 2nd rev',
+  'timestamp' => '1564543706',
+  'status' => '1',
+  'comment' => '2',
+  'promote' => '1',
+  'sticky' => '0',
+))
+->values(array(
+  'nid' => '4',
+  'vid' => '13',
+  'uid' => '1',
+  'title' => 'is - The thing about Firefly',
+  'log' => 'is - Firefly 2nd rev',
+  'timestamp' => '1564543810',
+  'status' => '1',
+  'comment' => '1',
+  'promote' => '1',
+  'sticky' => '0',
+))
+->values(array(
+  'nid' => '5',
+  'vid' => '14',
+  'uid' => '1',
+  'title' => 'en - The thing about Firefly',
+  'log' => 'Firefly 2nd rev',
+  'timestamp' => '1564543929',
+  'status' => '1',
+  'comment' => '1',
+  'promote' => '1',
+  'sticky' => '0',
+))
 ->execute();
 $connection->schema()->createTable('node_type', array(
   'fields' => array(
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php b/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php
deleted file mode 100644
index 335c44cab7..0000000000
--- a/core/modules/migrate_drupal/tests/src/Kernel/MigrationPluginAlterTest.php
+++ /dev/null
@@ -1,377 +0,0 @@
-<?php
-
-namespace Drupal\Tests\migrate_drupal\Kernel;
-
-use Drupal\Tests\migrate\Kernel\MigrateTestBase;
-
-/**
- * Tests migrate_drupal_migrations_plugin_alter for d6 term node migrations.
- *
- * @group migrate_drupal
- */
-class MigrationPluginAlterTest extends MigrateTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['migrate_drupal', 'taxonomy'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->setupDb();
-  }
-
-  /**
-   * Tests migrate_drupal_migrations_plugin_alter without content_translation.
-   *
-   * @dataProvider providerMigrationPluginAlter
-   */
-  public function testMigrationPluginAlterNoTranslation($source, $expected) {
-    $definitions = $source;
-    migrate_drupal_migration_plugins_alter($definitions);
-    // Ensure the results have an 'id' key.
-    foreach ($definitions as $definition) {
-      $this->assertArrayHasKey('id', $definition);
-    }
-    $this->assertSame($expected, $definitions);
-  }
-
-  /**
-   * Data provider for testMigrationPluginAlter().
-   */
-  public function providerMigrationPluginAlter() {
-    $tests = [];
-
-    // Test without a d6_taxonomy_vocabulary definition.
-    $tests[0]['source_data'] = [
-      'test' => [
-        'id' => 'test',
-        'process' => [
-          'nid' => 'nid',
-        ],
-      ],
-    ];
-    $tests[0]['expected_data'] = $tests[0]['source_data'];
-
-    // Test with a d6_taxonomy_vocabulary definition.
-    $tests[1]['source_data'] = [
-      'd6_taxonomy_vocabulary' => [
-        'id' => 'd6_taxonomy_vocabulary',
-        'process' => [
-          'vid' => [
-            'plugin' => 'machine_name',
-          ],
-        ],
-      ],
-      'test' => [
-        'id' => 'test',
-        'process' => [
-          'nid' => 'nid',
-        ],
-      ],
-    ];
-    $tests[1]['expected_data'] = $tests[1]['source_data'];
-
-    // Test with a d6_taxonomy_vocabulary and term_node definitions.
-    $tests[2] = $tests[1];
-    $tests[2]['source_data']['d6_term_node:2'] = [
-      'id' => 'd6_term_node:2',
-      'process' => [
-        'vid' => [
-          'plugin' => 'machine_name',
-        ],
-      ],
-    ];
-    $tests[2]['source_data']['d6_term_node_revision:4'] = [
-      'id' => 'd6_term_node_revision:4',
-      'process' => [
-        'vid' => [
-          'plugin' => 'machine_name',
-        ],
-      ],
-    ];
-
-    $tests[2]['expected_data'] = $tests[2]['source_data'];
-    $tests[2]['expected_data']['d6_term_node:2']['process']['taxonomy_forums'] = 'tid';
-    $tests[2]['expected_data']['d6_term_node_revision:4']['process']['field_'] = 'tid';
-
-    // Test with a d6_taxonomy_vocabulary and term_node_translation definition.
-    $tests[3] = $tests[1];
-    $tests[3]['source_data']['d6_term_node_translation:2'] = [
-      'id' => 'd6_term_node_translation:2',
-      'process' => [
-        'vid' => [
-          'plugin' => 'machine_name',
-        ],
-      ],
-    ];
-
-    $tests[3]['expected_data'] = $tests[3]['source_data'];
-    return $tests;
-  }
-
-  /**
-   * Tests migrate_drupal_migrations_plugin_alter.
-   *
-   * @dataProvider providerMigrationPluginAlterTranslation
-   */
-  public function testMigrationPluginAlterTranslation($source, $expected) {
-    /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */
-    $module_installer = \Drupal::service('module_installer');
-    $module_installer->install(['content_translation']);
-    $definitions = $source;
-    migrate_drupal_migration_plugins_alter($definitions);
-    // Ensure the results have an 'id' key.
-    foreach ($definitions as $definition) {
-      $this->assertArrayHasKey('id', $definition);
-    }
-    $this->assertSame($expected, $definitions);
-
-  }
-
-  /**
-   * Data provider for providerMigrationPluginAlterTranslation().
-   */
-  public function providerMigrationPluginAlterTranslation() {
-    $tests = [];
-
-    // Test with a d6_taxonomy_vocabulary definition and
-    // d6_term_node_translation definitions.
-    $tests[0]['source_data'] = [
-      'd6_taxonomy_vocabulary' => [
-        'id' => 'd6_taxonomy_vocabulary',
-        'process' => [
-          'vid' => [
-            'plugin' => 'machine_name',
-          ],
-        ],
-      ],
-      'test' => [
-        'id' => 'test',
-        'process' => [
-          'nid' => 'nid',
-        ],
-      ],
-      'd6_term_node_translation:2' => [
-        'id' => 'd6_term_node_translation:2',
-        'process' => [
-          'vid' => [
-            'plugin' => 'machine_name',
-          ],
-        ],
-      ],
-      'd6_term_node_translation:4' => [
-        'id' => 'd6_term_node_translation:4',
-        'process' => [
-          'vid' => [
-            'plugin' => 'machine_name',
-          ],
-        ],
-      ],
-    ];
-
-    $tests[0]['expected_data'] = $tests[0]['source_data'];
-    $tests[0]['expected_data']['d6_term_node_translation:2']['process']['taxonomy_forums'] = 'tid';
-    $tests[0]['expected_data']['d6_term_node_translation:4']['process']['field_'] = 'tid';
-    return $tests;
-  }
-
-  /**
-   * Creates data in the source database.
-   */
-  protected function setupDb() {
-    $this->sourceDatabase->schema()->createTable('system', [
-      'fields' => [
-        'name' => [
-          'type' => 'varchar',
-          'not null' => TRUE,
-          'length' => '255',
-          'default' => '',
-        ],
-        'type' => [
-          'type' => 'varchar',
-          'not null' => TRUE,
-          'length' => '255',
-          'default' => '',
-        ],
-        'status' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-        ],
-      ],
-    ]);
-    $this->sourceDatabase->insert('system')
-      ->fields([
-        'name',
-        'type',
-        'status',
-      ])
-      ->values([
-        'name' => 'taxonomy',
-        'type' => 'module',
-        'status' => '1',
-      ])
-      ->execute();
-
-    $this->sourceDatabase->schema()->createTable('variable', [
-      'fields' => [
-        'name' => [
-          'type' => 'varchar',
-          'not null' => TRUE,
-          'length' => '128',
-          'default' => '',
-        ],
-        'value' => [
-          'type' => 'text',
-          'not null' => TRUE,
-          'size' => 'normal',
-        ],
-      ],
-    ]);
-    $this->sourceDatabase->insert('variable')
-      ->fields([
-        'name',
-        'value',
-      ])
-      ->values([
-        'name' => 'forum_nav_vocabulary',
-        'value' => 's:1:"2";',
-      ])
-      ->execute();
-
-    $this->sourceDatabase->schema()->createTable('vocabulary', [
-      'fields' => [
-        'vid' => [
-          'type' => 'serial',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'unsigned' => TRUE,
-        ],
-        'name' => [
-          'type' => 'varchar',
-          'not null' => TRUE,
-          'length' => '255',
-          'default' => '',
-        ],
-        'description' => [
-          'type' => 'text',
-          'not null' => FALSE,
-          'size' => 'normal',
-        ],
-        'help' => [
-          'type' => 'varchar',
-          'not null' => TRUE,
-          'length' => '255',
-          'default' => '',
-        ],
-        'relations' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-          'unsigned' => TRUE,
-        ],
-        'hierarchy' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-          'unsigned' => TRUE,
-        ],
-        'multiple' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-          'unsigned' => TRUE,
-        ],
-        'required' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-          'unsigned' => TRUE,
-        ],
-        'tags' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-          'unsigned' => TRUE,
-        ],
-        'module' => [
-          'type' => 'varchar',
-          'not null' => TRUE,
-          'length' => '255',
-          'default' => '',
-        ],
-        'weight' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-        ],
-      ],
-      'primary key' => ['vid'],
-    ]);
-
-    $this->sourceDatabase->insert('vocabulary')
-      ->fields([
-        'vid',
-        'name',
-      ])
-      ->values([
-        'vid' => '4',
-        'name' => 'Tags',
-      ])
-      ->values([
-        'vid' => '2',
-        'name' => 'Forums',
-      ])
-      ->execute();
-
-    $this->sourceDatabase->schema()->createTable('vocabulary_node_types', [
-      'fields' => [
-        'vid' => [
-          'type' => 'int',
-          'not null' => TRUE,
-          'size' => 'normal',
-          'default' => '0',
-          'unsigned' => TRUE,
-        ],
-        'type' => [
-          'type' => 'varchar',
-          'not null' => TRUE,
-          'length' => '32',
-          'default' => '',
-        ],
-      ],
-      'primary key' => [
-        'vid',
-        'type',
-      ],
-      'mysql_character_set' => 'utf8',
-    ]);
-
-    $this->sourceDatabase->insert('vocabulary_node_types')
-      ->fields([
-        'vid',
-        'type',
-      ])
-      ->values([
-        'vid' => '4',
-        'type' => 'article',
-      ])
-      ->values([
-        'vid' => '2',
-        'type' => 'forum',
-      ])
-      ->execute();
-  }
-
-}
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php
index 84bb7cae3b..2bcf11ff03 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php
@@ -321,6 +321,7 @@ public function testNodeSource() {
     $values = $node_source->current()->getSource();
     $this->assertEquals($this->bundle, $values['type'][0]['target_id']);
     $this->assertEquals(1, $values['nid']);
+    $this->assertEquals(1, $values['vid']);
     $this->assertEquals('en', $values['langcode']);
     $this->assertEquals(1, $values['status'][0]['value']);
     $this->assertEquals('Apples', $values['title'][0]['value']);
@@ -330,6 +331,7 @@ public function testNodeSource() {
     $values = $node_source->current()->getSource();
     $this->assertEquals($this->bundle, $values['type'][0]['target_id']);
     $this->assertEquals(1, $values['nid']);
+    $this->assertEquals(1, $values['vid']);
     $this->assertEquals('fr', $values['langcode']);
     $this->assertEquals(1, $values['status'][0]['value']);
     $this->assertEquals('Pommes', $values['title'][0]['value']);
@@ -369,11 +371,13 @@ public function testMediaSource() {
     $fields = $media_source->fields();
     $this->assertArrayHasKey('bundle', $fields);
     $this->assertArrayHasKey('mid', $fields);
+    $this->assertArrayHasKey('vid', $fields);
     $this->assertArrayHasKey('name', $fields);
     $this->assertArrayHasKey('status', $fields);
     $media_source->rewind();
     $values = $media_source->current()->getSource();
     $this->assertEquals(1, $values['mid']);
+    $this->assertEquals(1, $values['vid']);
     $this->assertEquals('Foo media', $values['name'][0]['value']);
     $this->assertNull($values['thumbnail'][0]['title']);
     $this->assertEquals(1, $values['uid'][0]['target_id']);
@@ -402,9 +406,11 @@ public function testTermSource() {
     $this->assertEquals(2, $term_source->count());
     $ids = $term_source->getIds();
     $this->assertArrayHasKey('langcode', $ids);
+    $this->assertArrayHasKey('revision_id', $ids);
     $this->assertArrayHasKey('tid', $ids);
     $fields = $term_source->fields();
     $this->assertArrayHasKey('vid', $fields);
+    $this->assertArrayHasKey('revision_id', $fields);
     $this->assertArrayHasKey('tid', $fields);
     $this->assertArrayHasKey('name', $fields);
     $term_source->rewind();
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php b/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php
index 3620f0c3bf..d1acc0cc33 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php
@@ -138,6 +138,7 @@ function (AuditResult $result) {
       'd6_file',
       'd6_menu_links',
       'd6_node',
+      'd6_node_complete',
       'd6_node_revision',
       'd6_taxonomy_term',
       'd6_term_node_revision',
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php b/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php
index 0b2735c8ea..014bc32335 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php
@@ -2,13 +2,16 @@
 
 namespace Drupal\Tests\migrate_drupal\Kernel\d6;
 
+use Drupal\migrate_drupal\NodeMigrateType;
 use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
+use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait;
 
 /**
  * Base class for Drupal 6 migration tests.
  */
 abstract class MigrateDrupal6TestBase extends MigrateDrupalTestBase {
 
+  use NodeMigrateTypeTestTrait;
   /**
    * {@inheritdoc}
    */
@@ -21,6 +24,7 @@ abstract class MigrateDrupal6TestBase extends MigrateDrupalTestBase {
     'options',
     'telephone',
     'text',
+    'migrate_drupal',
   ];
 
   /**
@@ -28,6 +32,9 @@ abstract class MigrateDrupal6TestBase extends MigrateDrupalTestBase {
    */
   protected function setUp() {
     parent::setUp();
+    // Add a node classic migrate table to the destination site so that tests
+    // run by default with the classic node migrations.
+    $this->makeNodeMigrateMapTable(NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC, '6');
     $this->loadFixture($this->getFixtureFilePath());
   }
 
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php b/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php
index b53ffa4d78..79f22739db 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php
@@ -138,6 +138,7 @@ function (AuditResult $result) {
       'd7_file_private',
       'd7_menu_links',
       'd7_node',
+      'd7_node_complete',
       'd7_node_revision',
       'd7_taxonomy_term',
       'd7_user',
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7TestBase.php b/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7TestBase.php
index 535421cd84..d3cc3ead90 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7TestBase.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7TestBase.php
@@ -2,18 +2,25 @@
 
 namespace Drupal\Tests\migrate_drupal\Kernel\d7;
 
+use Drupal\migrate_drupal\NodeMigrateType;
 use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
+use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait;
 
 /**
  * Base class for Drupal 7 migration tests.
  */
 abstract class MigrateDrupal7TestBase extends MigrateDrupalTestBase {
 
+  use NodeMigrateTypeTestTrait;
+
   /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
+    // Add a node classic migrate table to the destination site so that tests
+    // run by default with the classic node migrations.
+    $this->makeNodeMigrateMapTable(NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC, '7');
     $this->loadFixture($this->getFixtureFilePath());
   }
 
diff --git a/core/modules/migrate_drupal/tests/src/Traits/NodeMigrateTypeTestTrait.php b/core/modules/migrate_drupal/tests/src/Traits/NodeMigrateTypeTestTrait.php
new file mode 100644
index 0000000000..21cba11551
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/src/Traits/NodeMigrateTypeTestTrait.php
@@ -0,0 +1,209 @@
+<?php
+
+namespace Drupal\Tests\migrate_drupal\Traits;
+
+use Drupal\migrate_drupal\NodeMigrateType;
+
+/**
+ * Helper functions to test complete and classic node migrations.
+ */
+trait NodeMigrateTypeTestTrait {
+
+  /**
+   * The migrate_map table name.
+   *
+   * @var string
+   */
+  public $tableName = NULL;
+
+  /**
+   * Gets the numbers of complete and classic node migrate_map tables.
+   *
+   * @param string $version
+   *   The source database version.
+   *
+   * @return array
+   *   An associative array with the total number of complete and classic
+   *   node migrate_map tables.
+   */
+  protected function nodeMigrateMapTableCount($version) {
+    $results = [];
+    $bases = ['node', 'node_complete'];
+    $tables = \Drupal::database()->schema()
+      ->findTables('migrate_map_d' . $version . '_node%');
+
+    foreach ($bases as $base) {
+      $base_tables = preg_grep('/^migrate_map_d' . $version . '_' . $base . '_{2}.*$/', $tables);
+      $results[$base] = count($base_tables);
+    }
+    return $results;
+  }
+
+  /**
+   * Remove the node migrate map table.
+   *
+   * @param string $type
+   *   The type of node migration, 'complete' or 'classic'.
+   * @param string $version
+   *   The source database version.
+   *
+   * @throws \Exception
+   */
+  protected function removeNodeMigrateMapTable($type, $version) {
+    $name = $this->getTableName($type, $version);
+    \Drupal::database()->schema()->dropTable($name);
+  }
+
+  /**
+   * Gets the migrate_map table name.
+   *
+   * @param string $type
+   *   The type of node migration, 'complete' or 'classic'.
+   * @param string $version
+   *   The source database version.
+   *
+   * @return string
+   *   The migrate_map table name.
+   */
+  protected function getTableName($type, $version) {
+    if (!$this->tableName) {
+      // PostgreSQL table names are automatically converted lowercase. If this
+      // string is not lowercase then we can't remove the table in
+      // \Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait::removeNodeMigrateMapTable().
+      $content_type = strtolower($this->randomMachineName());
+      $this->tableName = 'migrate_map_d' . $version . '_node_complete__' . $content_type;
+      if ($type == NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC) {
+        $this->tableName = 'migrate_map_d' . $version . '_node__' . $content_type;
+      }
+    }
+    return $this->tableName;
+  }
+
+  /**
+   * Create a node migrate_map table.
+   *
+   * @param string $type
+   *   The type of node migration, 'complete' or 'classic'.
+   * @param string $version
+   *   The source database version.
+   *
+   * @throws \Exception
+   */
+  protected function makeNodeMigrateMapTable($type, $version) {
+    $name = $this->getTableName($type, $version);
+    $fields = [
+      'source_ids_hash' => [
+        'type' => 'varchar',
+        'not null' => TRUE,
+        'length' => '64',
+      ],
+      'sourceid1' => [
+        'type' => 'int',
+        'not null' => TRUE,
+        'size' => 'normal',
+      ],
+      'sourceid2' => [
+        'type' => 'int',
+        'not null' => TRUE,
+        'size' => 'normal',
+      ],
+      'sourceid3' => [
+        'type' => 'varchar',
+        'not null' => TRUE,
+        'length' => '255',
+      ],
+      'destid1' => [
+        'type' => 'int',
+        'not null' => FALSE,
+        'size' => 'normal',
+        'unsigned' => TRUE,
+      ],
+      'destid2' => [
+        'type' => 'int',
+        'not null' => FALSE,
+        'size' => 'normal',
+        'unsigned' => TRUE,
+      ],
+      'destid3' => [
+        'type' => 'varchar_ascii',
+        'not null' => FALSE,
+        'length' => '12',
+      ],
+      'source_row_status' => [
+        'type' => 'int',
+        'not null' => TRUE,
+        'size' => 'tiny',
+        'default' => '0',
+        'unsigned' => TRUE,
+      ],
+      'rollback_action' => [
+        'type' => 'int',
+        'not null' => TRUE,
+        'size' => 'tiny',
+        'default' => '0',
+        'unsigned' => TRUE,
+      ],
+      'last_imported' => [
+        'type' => 'int',
+        'not null' => TRUE,
+        'size' => 'normal',
+        'default' => '0',
+        'unsigned' => TRUE,
+      ],
+      'hash' => [
+        'type' => 'varchar',
+        'not null' => FALSE,
+        'length' => '64',
+      ],
+    ];
+    $values = [
+      'source_ids_hash' => '123',
+      'sourceid1' => '4242',
+      'sourceid2' => '4242',
+      'sourceid3' => 'en',
+      'destid1' => '4242',
+      'destid2' => '4242',
+      'destid3' => 'en',
+      'source_row_status' => '1',
+      'rollback_action' => '1',
+      'last_imported' => time(),
+      'hash' => 'abc',
+    ];
+    $indexes = [
+      'source' => [
+        'sourceid1',
+        'sourceid2',
+        'sourceid3',
+      ],
+    ];
+
+    // Remove keys not used.
+    if ($type == NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC) {
+      $keys = ['sourceid2', 'sourceid3', 'destid2', 'destid3'];
+      foreach ($keys as $key) {
+        unset($fields[$key]);
+        unset($values[$key]);
+        if (strstr($key, 'sourceid')) {
+          $index_key = substr($key, -1) - 1;
+          unset($indexes['source'][$index_key]);
+        }
+      }
+    }
+    $connection = \Drupal::database();
+    $connection->schema()->createTable($name, [
+      'fields' => $fields,
+      'primary key' => [
+        'source_ids_hash',
+      ],
+      'indexes' => $indexes,
+      'mysql_character_set' => 'utf8mb4',
+    ]);
+
+    $field_names = array_keys($fields);
+    $connection->insert($name)
+      ->fields($field_names)
+      ->values($values)
+      ->execute();
+  }
+
+}
diff --git a/core/modules/migrate_drupal_ui/src/Form/IdConflictForm.php b/core/modules/migrate_drupal_ui/src/Form/IdConflictForm.php
index ec58b94081..4146bb41d8 100644
--- a/core/modules/migrate_drupal_ui/src/Form/IdConflictForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/IdConflictForm.php
@@ -123,7 +123,7 @@ protected function formatConflicts(array $conflicts) {
     }
     sort($items, SORT_STRING);
 
-    return $items;
+    return array_unique($items);
   }
 
   /**
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
index 7038e7b378..8ca811ccb4 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
@@ -112,8 +112,6 @@ public function testMigrateUpgradeExecute() {
       'file',
       'taxonomy_term',
       'user',
-      'comment',
-      'node',
     ];
     $this->assertIdConflict($session, $entity_types);
 
@@ -148,9 +146,8 @@ public function testMigrateUpgradeExecute() {
     $session->pageTextContains('WARNING: Content may be overwritten on your new site.');
     $session->pageTextContains('There is conflicting content of these types:');
     $session->pageTextContains('files');
-    $session->pageTextContains('content item revisions');
     $session->pageTextContains('There is translated content of these types:');
-    $session->pageTextContains('content items');
+    $session->pageTextContainsOnce('content items');
 
     $this->drupalPostForm(NULL, [], t('I acknowledge I may lose data. Continue anyway.'));
     $session->statusCodeEquals(200);
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
index db75e036a8..4b6754487c 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
@@ -196,17 +196,18 @@ protected function assertReviewPage(WebAssert $session, array $available_paths,
    * @param array $entity_types
    *   An array of entity types
    */
-  protected function assertIdConflict(WebAssert $session, $entity_types) {
+  protected function assertIdConflict(WebAssert $session, array $entity_types) {
     /** @var \Drupal\ $entity_type_manager */
     $entity_type_manager = \Drupal::service('entity_type.manager');
 
     $session->pageTextContains('WARNING: Content may be overwritten on your new site.');
     $session->pageTextContains('There is conflicting content of these types:');
+    $this->assertNotEmpty($entity_types, 'No entity types provided to \Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeTestBase::assertIdConflict()');
     foreach ($entity_types as $entity_type) {
       $label = $entity_type_manager->getDefinition($entity_type)->getPluralLabel();
       $session->pageTextContains($label);
     }
-    $session->pageTextContains('content item revisions');
+    $session->pageTextContainsOnce('content items');
     $session->pageTextContains('There is translated content of these types:');
   }
 
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/NoMultilingualReviewPageTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/NoMultilingualReviewPageTestBase.php
index d5e41ed293..81f618ce6c 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/NoMultilingualReviewPageTestBase.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/NoMultilingualReviewPageTestBase.php
@@ -23,8 +23,8 @@ public function testMigrateUpgradeReviewPage() {
     $session->pageTextContains('WARNING: Content may be overwritten on your new site.');
     $session->pageTextContains('There is conflicting content of these types:');
     $session->pageTextContains('taxonomy terms');
-    $session->pageTextNotContains('There is translated content of these types:');
-    $session->pageTextNotContains('custom menu links');
+    $session->pageTextContains('There is translated content of these types:');
+    $session->pageTextContainsOnce('content items');
 
     $this->drupalPostForm(NULL, [], t('I acknowledge I may lose data. Continue anyway.'));
     $session->statusCodeEquals(200);
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php
index dc3a6d68eb..5ea6badda6 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MultilingualReviewPageTest.php
@@ -109,6 +109,7 @@ protected function getAvailablePaths() {
       'jquery_ui',
       'link',
       'menu',
+      'node',
       'nodeaccess',
       'nodereference',
       'number',
@@ -158,7 +159,6 @@ protected function getMissingPaths() {
       'i18nviews',
       'locale',
       'migrate_status_active_test',
-      'node',
       'views',
     ];
   }
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NodeClassicTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NodeClassicTest.php
new file mode 100644
index 0000000000..93aed6dbcd
--- /dev/null
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/NodeClassicTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace Drupal\Tests\migrate_drupal_ui\Functional\d6;
+
+use Drupal\migrate_drupal\NodeMigrateType;
+use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait;
+use Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeExecuteTestBase;
+
+/**
+ * Tests the classic node migration runs.
+ *
+ * The classic node migration will run and not the complete node migration
+ * when there is a pre-existing classic node migrate map table.
+ *
+ * @group migrate_drupal_ui
+ */
+class NodeClassicTest extends MigrateUpgradeExecuteTestBase {
+
+  use NodeMigrateTypeTestTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'language',
+    'content_translation',
+    'config_translation',
+    'migrate_drupal_ui',
+    'telephone',
+    'aggregator',
+    'book',
+    'forum',
+    'statistics',
+    // Required for translation migrations.
+    'migrate_drupal_multilingual',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->loadFixture(drupal_get_path('module', 'migrate_drupal') . '/tests/fixtures/drupal6.php');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSourceBasePath() {
+    return __DIR__ . '/files';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntityCounts() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntityCountsIncremental() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getAvailablePaths() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getMissingPaths() {
+  }
+
+  /**
+   * Tests ID Conflict form.
+   */
+  public function testMigrateUpgradeExecute() {
+    // Add a node classic migrate table to d8.
+    $this->makeNodeMigrateMapTable(NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC, '6');
+
+    $connection_options = $this->sourceDatabase->getConnectionOptions();
+    $this->drupalGet('/upgrade');
+    $session = $this->assertSession();
+    $session->responseContains('Upgrade a site by importing its files and the data from its database into a clean and empty new install of Drupal 8.');
+
+    $this->drupalPostForm(NULL, [], t('Continue'));
+    $session->pageTextContains('Provide credentials for the database of the Drupal site you want to upgrade.');
+    $session->fieldExists('mysql[host]');
+
+    $driver = $connection_options['driver'];
+    $connection_options['prefix'] = $connection_options['prefix']['default'];
+
+    // Use the driver connection form to get the correct options out of the
+    // database settings. This supports all of the databases we test against.
+    $drivers = drupal_get_database_types();
+    $form = $drivers[$driver]->getFormOptions($connection_options);
+    $connection_options = array_intersect_key($connection_options, $form + $form['advanced_options']);
+    $version = $this->getLegacyDrupalVersion($this->sourceDatabase);
+    $edit = [
+      $driver => $connection_options,
+      'source_private_file_path' => $this->getSourceBasePath(),
+      'version' => $version,
+    ];
+    $edit['d6_source_base_path'] = $this->getSourceBasePath();
+    if (count($drivers) !== 1) {
+      $edit['driver'] = $driver;
+    }
+    $edits = $this->translatePostValues($edit);
+
+    // Start the upgrade process.
+    $this->drupalGet('/upgrade');
+    $session->responseContains('Upgrade a site by importing its files and the data from its database into a clean and empty new install of Drupal 8.');
+
+    $this->drupalPostForm(NULL, [], t('Continue'));
+    $session->pageTextContains('Provide credentials for the database of the Drupal site you want to upgrade.');
+    $session->fieldExists('mysql[host]');
+
+    // When the Credential form is submitted the migrate map tables are created.
+    $this->drupalPostForm(NULL, $edits, t('Review upgrade'));
+
+    // Confirm there are only classic node migration map tables. This shows
+    // that only the classic migration will run.
+    $results = $this->nodeMigrateMapTableCount('6');
+    $this->assertSame(13, $results['node']);
+    $this->assertSame(0, $results['node_complete']);
+  }
+
+}
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php
index 0731f12aff..b0061da3ff 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/Upgrade6Test.php
@@ -37,11 +37,28 @@ class Upgrade6Test extends MigrateUpgradeExecuteTestBase {
     'migrate_drupal_multilingual',
   ];
 
+  /**
+   * The entity storage for node.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $nodeStorage;
+
   /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
+
+    // Delete the existing content made to test the ID Conflict form. Migrations
+    // are to be done on a site without content. The test of the ID Conflict
+    // form is being moved to its own issue which will remove the deletion
+    // of the created nodes.
+    // See https://www.drupal.org/project/drupal/issues/3087061.
+    $this->nodeStorage = $this->container->get('entity_type.manager')
+      ->getStorage('node');
+    $this->nodeStorage->delete($this->nodeStorage->loadMultiple());
+
     $this->loadFixture(drupal_get_path('module', 'migrate_drupal') . '/tests/fixtures/drupal6.php');
   }
 
@@ -145,6 +162,7 @@ protected function getAvailablePaths() {
       'imagecache',
       'imagefield',
       'menu',
+      'node',
       'nodereference',
       'optionwidgets',
       'path',
@@ -180,7 +198,6 @@ protected function getMissingPaths() {
       'i18nstrings',
       'i18ntaxonomy',
       'locale',
-      'node',
     ];
   }
 
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php
index b5fdc0239b..c25ec43223 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MultilingualReviewPageTest.php
@@ -103,6 +103,7 @@ protected function getAvailablePaths() {
       'locale',
       'menu',
       'number',
+      'node',
       'openid',
       'options',
       'overlay',
@@ -168,7 +169,6 @@ protected function getMissingPaths() {
       'i18n_translation',
       'i18n_user',
       'i18n_variable',
-      'node',
       'picture',
       'migrate_status_active_test',
       'variable',
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
index f5178bc545..2056c0e3cb 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
@@ -39,11 +39,28 @@ class Upgrade7Test extends MigrateUpgradeExecuteTestBase {
     'migrate_drupal_multilingual',
   ];
 
+  /**
+   * The entity storage for node.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $nodeStorage;
+
   /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
+
+    // Delete the existing content made to test the ID Conflict form. Migrations
+    // are to be done on a site without content. The test of the ID Conflict
+    // form is being moved to its own issue which will remove the deletion
+    // of the created nodes.
+    // See https://www.drupal.org/project/drupal/issues/3087061.
+    $this->nodeStorage = $this->container->get('entity_type.manager')
+      ->getStorage('node');
+    $this->nodeStorage->delete($this->nodeStorage->loadMultiple());
+
     $this->loadFixture(drupal_get_path('module', 'migrate_drupal') . '/tests/fixtures/drupal7.php');
   }
 
@@ -149,6 +166,7 @@ protected function getAvailablePaths() {
       'link',
       'list',
       'menu',
+      'node',
       'number',
       'options',
       'path',
@@ -189,7 +207,6 @@ protected function getMissingPaths() {
       'i18n_taxonomy',
       'i18n_translation',
       'locale',
-      'node',
       'variable',
       'variable_realm',
       'variable_store',
diff --git a/core/modules/node/migrations/d6_node_complete.yml b/core/modules/node/migrations/d6_node_complete.yml
new file mode 100644
index 0000000000..84ef465bec
--- /dev/null
+++ b/core/modules/node/migrations/d6_node_complete.yml
@@ -0,0 +1,58 @@
+# Migrates all revisions and all revision translations.
+id: d6_node_complete
+label: Node Complete
+audit: true
+migration_tags:
+  - Drupal 6
+  - Content
+class: Drupal\node\Plugin\migrate\D6NodeTranslation
+deriver: Drupal\node\Plugin\migrate\D6NodeDeriver
+source:
+  plugin: d6_node_complete
+process:
+  # If you are using this file to build a custom migration consider removing
+  # the nid and vid fields to allow incremental migrations.
+  # In D6, nodes always have a tnid, but it's zero for untranslated nodes.
+  # We normalize it to equal the nid in that case.
+  # @see \Drupal\node\Plugin\migrate\source\d6\Node::prepareRow().
+  nid: tnid
+  vid: vid
+  langcode:
+    plugin: default_value
+    source: language
+    default_value: "und"
+  title: title
+  uid: node_uid
+  status: status
+  created: created
+  changed: timestamp
+  promote: promote
+  sticky: sticky
+  'body/format':
+    plugin: migration_lookup
+    migration: d6_filter_format
+    source: format
+  'body/value': body
+  'body/summary': teaser
+  revision_uid: revision_uid
+  revision_log: log
+  revision_timestamp: timestamp
+  content_translation_source: source_langcode
+  #  unmapped d6 fields.
+  #  translate
+  #  moderate
+  #  comment
+destination:
+  plugin: entity_complete:node
+  translations: true
+migration_dependencies:
+  required:
+    - d6_user
+    - d6_node_type
+    - d6_node_settings
+    - d6_filter_format
+    - language
+  optional:
+    - d6_field_instance_widget_settings
+    - d6_field_formatter_settings
+    - d6_upload_field_instance
diff --git a/core/modules/node/migrations/d7_node_complete.yml b/core/modules/node/migrations/d7_node_complete.yml
new file mode 100644
index 0000000000..fb52819d59
--- /dev/null
+++ b/core/modules/node/migrations/d7_node_complete.yml
@@ -0,0 +1,48 @@
+# Migrates all revisions and all revision translations.
+id: d7_node_complete
+label: Node complete
+audit: true
+migration_tags:
+  - Drupal 7
+  - Content
+class: Drupal\node\Plugin\migrate\D7NodeTranslation
+deriver: Drupal\node\Plugin\migrate\D7NodeDeriver
+source:
+  plugin: d7_node_complete
+process:
+  # If you are using this file to build a custom migration consider removing
+  # the nid and vid fields to allow incremental migrations.
+  # In D7, nodes always have a tnid, but it's zero for untranslated nodes.
+  # We normalize it to equal the nid in that case.
+  # @see \Drupal\node\Plugin\migrate\source\d7\Node::prepareRow().
+  nid: tnid
+  vid: vid
+  langcode:
+    plugin: default_value
+    source: language
+    default_value: "und"
+  title: title
+  uid: node_uid
+  status: status
+  created: created
+  changed: timestamp
+  promote: promote
+  sticky: sticky
+  revision_uid: revision_uid
+  revision_log: log
+  revision_timestamp: timestamp
+  content_translation_source: source_langcode
+  #  unmapped d6 fields.
+  #  translate
+  #  comment
+destination:
+  plugin: entity_complete:node
+  translations: true
+migration_dependencies:
+  required:
+    - d7_user
+    - d7_node_type
+    - language
+  optional:
+    - d7_field_instance
+    - d7_comment_field_instance
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 4899ddce67..4377d8cb34 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -26,6 +26,8 @@
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\language\ConfigurableLanguageInterface;
+use Drupal\migrate_drupal\MigrationConfigurationTrait;
+use Drupal\migrate_drupal\NodeMigrateType;
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
 use Drupal\node\NodeInterface;
@@ -1461,3 +1463,55 @@ function node_comment_delete($comment) {
 function node_config_translation_info_alter(&$info) {
   $info['node_type']['class'] = 'Drupal\node\ConfigTranslation\NodeTypeMapper';
 }
+
+/**
+ * Implements hook_migration_plugins_alter().
+ */
+function node_migration_plugins_alter(array &$definitions) {
+  // Don't alter the node migrations unless migrate_drupal is installed.
+  if (!\Drupal::moduleHandler()->moduleExists('migrate_drupal')) {
+    return;
+  }
+  $version = FALSE;
+  $connection = \Drupal::database();
+  // We need to get the version of the source database in order to check
+  // if the classic or complete node tables have been used in a migration.
+  if (isset($definitions['system_site'])) {
+    // Use the source plugin of the system_site migration to get the
+    // database connection.
+    $migration = $definitions['system_site'];
+    /** @var \Drupal\migrate\Plugin\migrate\source\SqlBase $source_plugin */
+    $source_plugin = \Drupal::service('plugin.manager.migration')
+      ->createStubMigration($migration)
+      ->getSourcePlugin();
+    $source_connection = NULL;
+
+    try {
+      $source_connection = $source_plugin->getDatabase();
+      $version = MigrationConfigurationTrait::getLegacyDrupalVersion($source_connection);
+    }
+    catch (\Exception $e) {
+      \Drupal::messenger()->addError(t('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist, and have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', ['%error' => $e->getMessage()]));
+    }
+  }
+  // If this is a complete node migration then for all migrations, except the
+  // classic node migrations, replace any dependency on a classic node migration
+  // with a dependency on the complete node migration.
+  if (NodeMigrateType::getNodeMigrateType($connection, $version) === NodeMigrateType::NODE_MIGRATE_TYPE_COMPLETE) {
+    // Anonymous function to replace classic node migration plugin IDs with the
+    // node complete plugin ID.
+    $replace_with_complete_migration = function (&$value) {
+      if (is_string($value)) {
+        $value = preg_replace('/d([67])_(node|node_translation|node_revision|node_entity_translation)($|:.*)/', 'd$1_node_complete$3', $value);
+      }
+      return $value;
+    };
+
+    foreach ($definitions as &$definition) {
+      $is_node_classic_migration = preg_match('/d([67])_(node|node_translation|node_revision|node_entity_translation)($|:.*)/', $definition['id']);
+      if (!$is_node_classic_migration && isset($definition['migration_dependencies'])) {
+        array_walk_recursive($definition['migration_dependencies'], $replace_with_complete_migration);
+      }
+    }
+  }
+}
diff --git a/core/modules/node/src/Plugin/migrate/source/d6/NodeComplete.php b/core/modules/node/src/Plugin/migrate/source/d6/NodeComplete.php
new file mode 100644
index 0000000000..96d6d29db9
--- /dev/null
+++ b/core/modules/node/src/Plugin/migrate/source/d6/NodeComplete.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\node\Plugin\migrate\source\d6;
+
+/**
+ * Gets all node revisions from the source, including translation revisions.
+ *
+ * @MigrateSource(
+ *   id = "d6_node_complete",
+ *   source_module = "node"
+ * )
+ */
+class NodeComplete extends NodeRevision {
+
+  /**
+   * The join options between the node and the node_revisions_table.
+   */
+  const JOIN = 'n.nid = nr.nid';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = parent::query();
+    $query->orderBy('nr.vid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return [
+      'nid' => [
+        'type' => 'integer',
+        'alias' => 'n',
+      ],
+      'vid' => [
+        'type' => 'integer',
+        'alias' => 'nr',
+      ],
+      'language' => [
+        'type' => 'string',
+        'alias' => 'n',
+      ],
+    ];
+  }
+
+}
diff --git a/core/modules/node/src/Plugin/migrate/source/d7/NodeComplete.php b/core/modules/node/src/Plugin/migrate/source/d7/NodeComplete.php
new file mode 100644
index 0000000000..91369d0f84
--- /dev/null
+++ b/core/modules/node/src/Plugin/migrate/source/d7/NodeComplete.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\node\Plugin\migrate\source\d7;
+
+use Drupal\Core\Database\Query\SelectInterface;
+
+/**
+ * Gets all node revisions from the source, including translation revisions.
+ *
+ * @MigrateSource(
+ *   id = "d7_node_complete",
+ *   source_module = "node"
+ * )
+ */
+class NodeComplete extends NodeRevision {
+
+  /**
+   * The join options between the node and the node_revisions_table.
+   */
+  const JOIN = 'n.nid = nr.nid';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = parent::query();
+    $query->orderBy('nr.vid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return [
+      'nid' => [
+        'type' => 'integer',
+        'alias' => 'n',
+      ],
+      'vid' => [
+        'type' => 'integer',
+        'alias' => 'nr',
+      ],
+      'language' => [
+        'type' => 'string',
+        'alias' => 'n',
+      ],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function handleTranslations(SelectInterface $query) {}
+
+}
diff --git a/core/modules/node/tests/src/Kernel/Migrate/MigrationPluginAlterTest.php b/core/modules/node/tests/src/Kernel/Migrate/MigrationPluginAlterTest.php
new file mode 100644
index 0000000000..da7750db84
--- /dev/null
+++ b/core/modules/node/tests/src/Kernel/Migrate/MigrationPluginAlterTest.php
@@ -0,0 +1,171 @@
+<?php
+
+namespace Drupal\Tests\node\Kernel\Migrate;
+
+use Drupal\migrate_drupal\NodeMigrateType;
+use Drupal\Tests\migrate\Kernel\MigrateTestBase;
+use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait;
+
+/**
+ * Tests node_migrations_plugin_alter.
+ *
+ * @group node
+ */
+class MigrationPluginAlterTest extends MigrateTestBase {
+
+  use NodeMigrateTypeTestTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'migrate_drupal',
+    'node',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->setupDb();
+  }
+
+  /**
+   * Tests migrate_drupal_migrations_plugin_alter.
+   *
+   * @param string $type
+   *   The type of node migration, 'classic' or 'complete'.
+   * @param array $migration_definitions
+   *   An array of migration definitions.
+   * @param array $expected
+   *   The expected results.
+   *
+   * @dataProvider providerMigrationPluginAlter
+   */
+  public function testMigrationPluginAlter($type, array $migration_definitions, array $expected) {
+    // Version 6 is used so that term node migrations are tested.
+    $this->makeNodeMigrateMapTable($type, '7');
+    node_migration_plugins_alter($migration_definitions);
+    $this->assertSame($expected, $migration_definitions);
+  }
+
+  /**
+   * Data provider for testMigrationPluginAlter().
+   */
+  public function providerMigrationPluginAlter() {
+    $tests = [];
+
+    $migrations = [
+      // The 'system_site' migration is needed to get the legacy Drupal version.
+      'system_site' => [
+        'id' => 'system_site',
+        'source' => [
+          'plugin' => 'variable',
+          'variables' => [
+            'site_name',
+            'site_mail',
+          ],
+          'source_module' => 'system',
+        ],
+        'process' => [],
+      ],
+      'no_dependencies_not_altered' => [
+        'id' => 'no_dependencies_not_altered',
+        'no_dependencies' => 'test',
+        'process' => [
+          'nid' => 'nid',
+        ],
+      ],
+      'dependencies_altered_if_complete' => [
+        'id' => 'test',
+        'migration_dependencies' => [
+          'required' => [
+            'd7_node',
+          ],
+          'optional' => [
+            'd7_node_translation',
+          ],
+        ],
+      ],
+      'dependencies_not_altered' => [
+        'id' => 'd7_node',
+        'migration_dependencies' => [
+          'required' => [
+            'd7_node',
+          ],
+          'optional' => [
+            'd7_node_translation',
+          ],
+        ],
+      ],
+    ];
+
+    // Test migrations are not altered when classic node migrations is in use.
+    $tests[0]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC;
+    $tests[0]['migrations'] = $migrations;
+    $tests[0]['expected_data'] = $tests[0]['migrations'];
+
+    // Test migrations are altered when complete node migrations is in use.
+    $tests[1] = $tests[0];
+    $tests[1]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_COMPLETE;
+    $tests[1]['expected_data']['dependencies_altered_if_complete']['migration_dependencies'] = [
+      'required' => [
+        'd7_node_complete',
+      ],
+      'optional' => [
+        'd7_node_complete',
+      ],
+    ];
+    return $tests;
+  }
+
+  /**
+   * Creates data in the source database.
+   */
+  protected function setupDb() {
+    $this->sourceDatabase->schema()->createTable('system', [
+      'fields' => [
+        'name' => [
+          'type' => 'varchar',
+          'not null' => TRUE,
+          'length' => '255',
+          'default' => '',
+        ],
+        'type' => [
+          'type' => 'varchar',
+          'not null' => TRUE,
+          'length' => '255',
+          'default' => '',
+        ],
+        'status' => [
+          'type' => 'int',
+          'not null' => TRUE,
+          'size' => 'normal',
+          'default' => '0',
+        ],
+        'schema_version' => [
+          'type' => 'int',
+          'not null' => TRUE,
+          'size' => 'normal',
+          'default' => '-1',
+        ],
+      ],
+    ]);
+    $this->sourceDatabase->insert('system')
+      ->fields([
+        'name',
+        'type',
+        'status',
+        'schema_version',
+      ])
+      ->values([
+        'name' => 'system',
+        'type' => 'module',
+        'status' => '1',
+        'schema_version' => '7001',
+      ])
+      ->execute();
+  }
+
+}
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeCompleteTest.php b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeCompleteTest.php
new file mode 100644
index 0000000000..704d7eb230
--- /dev/null
+++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeCompleteTest.php
@@ -0,0 +1,1257 @@
+<?php
+
+namespace Drupal\Tests\node\Kernel\Migrate\d6;
+
+use Drupal\node\NodeInterface;
+use Drupal\Tests\file\Kernel\Migrate\d6\FileMigrationTestTrait;
+use Drupal\Tests\migrate_drupal\Traits\CreateTestContentEntitiesTrait;
+
+/**
+ * Test class for a complete node migration for Drupal 6.
+ *
+ * @group migrate_drupal_6
+ */
+class MigrateNodeCompleteTest extends MigrateNodeTestBase {
+
+  use FileMigrationTestTrait;
+  use CreateTestContentEntitiesTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'language',
+    'content_translation',
+    'menu_ui',
+    // Required for translation migrations.
+    'migrate_drupal_multilingual',
+  ];
+
+  /**
+   * The entity storage for node.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $nodeStorage;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->setUpMigratedFiles();
+
+    $this->createContent();
+
+    $this->nodeStorage = $this->container->get('entity_type.manager')
+      ->getStorage('node');
+    $this->nodeStorage->delete($this->nodeStorage->loadMultiple());
+
+    $this->installSchema('file', ['file_usage']);
+    $this->executeMigrations([
+      'language',
+      'd6_language_content_settings',
+      'd6_node_complete',
+    ]);
+  }
+
+  /**
+   * Tests the complete node migration.
+   */
+  public function testNodeCompleteMigration() {
+    $db = \Drupal::database();
+    $this->assertEquals($this->expectedNodeFieldRevisionTable(), $db->select('node_field_revision', 'nr')
+      ->fields('nr')
+      ->orderBy('vid')
+      ->orderBy('langcode')
+      ->execute()
+      ->fetchAll(\PDO::FETCH_ASSOC));
+    $this->assertEquals($this->expectedNodeFieldDataTable(), $db->select('node_field_data', 'nr')
+      ->fields('nr')
+      ->orderBy('nid')
+      ->orderBy('vid')
+      ->orderBy('langcode')
+      ->execute()
+      ->fetchAll(\PDO::FETCH_ASSOC));
+
+    // Now load and test each revision, including the field 'field_text_plain'
+    // which has text reflecting the revision.
+    $data = $this->expectedRevisionEntityData()[0];
+    foreach ($this->expectedNodeFieldRevisionTable() as $key => $revision) {
+      $this->assertRevision($revision, $data[$key]);
+    }
+  }
+
+  /**
+   * Asserts various aspects of a node revision.
+   *
+   * @param array $revision
+   *   An array of revision data matching a node_field_revision table row.
+   * @param array $data
+   *   An array of revision data.
+   */
+  protected function assertRevision(array $revision, array $data) {
+    /* @var  \Drupal\node\NodeInterface $actual */
+    $actual = $this->nodeStorage->loadRevision($revision['vid'])
+      ->getTranslation($revision['langcode']);
+    $this->assertInstanceOf(NodeInterface::class, $actual);
+    $this->assertSame($revision['title'], $actual->getTitle(), sprintf("Title '%s' does not match actual '%s' for revision '%d' langcode '%s'", $revision['title'], $actual->getTitle(), $revision['vid'], $revision['langcode']));
+    $this->assertSame($revision['revision_translation_affected'], $actual->get('revision_translation_affected')->value, sprintf("revision_translation_affected '%s' does not match actual '%s' for revision '%d' langcode '%s'", $revision['revision_translation_affected'], $actual->get('revision_translation_affected')->value, $revision['vid'], $revision['langcode']));
+
+    $this->assertSame($data['created'], $actual->getRevisionCreationTime(), sprintf("Creation time '%s' does not match actual '%s' for revision '%d' langcode '%s'", $data['created'], $actual->getRevisionCreationTime(), $revision['vid'], $revision['langcode']));
+    $this->assertSame($data['changed'], $actual->getChangedTime(), sprintf("Changed time '%s' does not match actual '%s' for revision '%d' langcode '%s'", $data['changed'], $actual->getChangedTime(), $revision['vid'], $revision['langcode']));
+    $this->assertSame($data['log'], $actual->getRevisionLogMessage(), sprintf("Revision log '%s' does not match actual '%s' for revision '%d' langcode '%s'", var_export($data['log'], TRUE), $actual->getRevisionLogMessage(), $revision['vid'], $revision['langcode']));
+  }
+
+  /**
+   * Provides the expected node_field_data table.
+   *
+   * @return array
+   *   The expected table rows.
+   */
+  protected function expectedNodeFieldDataTable() {
+    return [
+      0 =>
+        [
+          'nid' => '1',
+          'vid' => '2001',
+          'type' => 'story',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test title rev 3',
+          'created' => '1390095702',
+          'changed' => '1420861423',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      1 =>
+        [
+          'nid' => '2',
+          'vid' => '3',
+          'type' => 'story',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test title rev 3',
+          'created' => '1388271197',
+          'changed' => '1420718386',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      2 =>
+        [
+          'nid' => '3',
+          'vid' => '4',
+          'type' => 'test_planet',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test page title rev 4',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      3 =>
+        [
+          'nid' => '4',
+          'vid' => '6',
+          'type' => 'test_planet',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 4',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      4 =>
+        [
+          'nid' => '5',
+          'vid' => '7',
+          'type' => 'test_planet',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 5',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      5 =>
+        [
+          'nid' => '6',
+          'vid' => '8',
+          'type' => 'test_planet',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 6',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      6 =>
+        [
+          'nid' => '7',
+          'vid' => '9',
+          'type' => 'test_planet',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 7',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      7 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'type' => 'test_planet',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 8',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      8 =>
+        [
+          'nid' => '9',
+          'vid' => '12',
+          'type' => 'story',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Once upon a time',
+          'created' => '1444671588',
+          'changed' => '1444671588',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      9 =>
+        [
+          'nid' => '10',
+          'vid' => '14',
+          'type' => 'page',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The Real McCoy',
+          'created' => '1444238800',
+          'changed' => '1444238808',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      10 =>
+        [
+          'nid' => '10',
+          'vid' => '14',
+          'type' => 'page',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Le Vrai McCoy',
+          'created' => '1444239050',
+          'changed' => '1444239050',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      11 =>
+        [
+          'nid' => '12',
+          'vid' => '23',
+          'type' => 'page',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The Zulu People',
+          'created' => '1444239050',
+          'changed' => '1444239050',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      12 =>
+        [
+          'nid' => '12',
+          'vid' => '23',
+          'type' => 'page',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Le peuple zoulou',
+          'created' => '1520613038',
+          'changed' => '1520613305',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      13 =>
+        [
+          'nid' => '12',
+          'vid' => '23',
+          'type' => 'page',
+          'langcode' => 'zu',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Abantu zulu',
+          'created' => '1444238800',
+          'changed' => '1444238808',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      14 =>
+        [
+          'nid' => '14',
+          'vid' => '17',
+          'type' => 'company',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'United Federation of Planets',
+          'created' => '1493066668',
+          'changed' => '1493066668',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      15 =>
+        [
+          'nid' => '15',
+          'vid' => '18',
+          'type' => 'company',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Klingon Empire',
+          'created' => '1493066677',
+          'changed' => '1493066677',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      16 =>
+        [
+          'nid' => '16',
+          'vid' => '19',
+          'type' => 'company',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Romulan Empire',
+          'created' => '1493066684',
+          'changed' => '1493066684',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      17 =>
+        [
+          'nid' => '17',
+          'vid' => '20',
+          'type' => 'company',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Ferengi Commerce Authority',
+          'created' => '1493066693',
+          'changed' => '1493066693',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      18 =>
+        [
+          'nid' => '18',
+          'vid' => '21',
+          'type' => 'employee',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Ambassador Sarek',
+          'created' => '1493066711',
+          'changed' => '1494966544',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      19 =>
+        [
+          'nid' => '19',
+          'vid' => '22',
+          'type' => 'forum',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'New Forum Topic',
+          'created' => '1501955771',
+          'changed' => '1501955771',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      20 =>
+        [
+          'nid' => '21',
+          'vid' => '2003',
+          'type' => 'employee',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'John Smith - EN',
+          'created' => '1534014650',
+          'changed' => '1534014650',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      21 =>
+        [
+          'nid' => '21',
+          'vid' => '2003',
+          'type' => 'employee',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'John Smith - FR',
+          'created' => '1534014687',
+          'changed' => '1534014687',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+    ];
+  }
+
+  /**
+   * Provides the expected node_field_revision table.
+   *
+   * @return array
+   *   The table.
+   */
+  protected function expectedNodeFieldRevisionTable() {
+    return [
+      0 =>
+        [
+          'nid' => '1',
+          'vid' => '1',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test title',
+          'created' => '1390095702',
+          'changed' => '1390095702',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      1 =>
+        [
+          'nid' => '2',
+          'vid' => '3',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test title rev 3',
+          'created' => '1388271197',
+          'changed' => '1420718386',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      2 =>
+        [
+          'nid' => '3',
+          'vid' => '4',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test page title rev 4',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      3 =>
+        [
+          'nid' => '1',
+          'vid' => '5',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test title rev 2',
+          'created' => '1390095702',
+          'changed' => '1390095703',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      4 =>
+        [
+          'nid' => '4',
+          'vid' => '6',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 4',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      5 =>
+        [
+          'nid' => '5',
+          'vid' => '7',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 5',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      6 =>
+        [
+          'nid' => '6',
+          'vid' => '8',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 6',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      7 =>
+        [
+          'nid' => '7',
+          'vid' => '9',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 7',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      8 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 8',
+          'created' => '1388271527',
+          'changed' => '1390095701',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      9 =>
+        [
+          'nid' => '9',
+          'vid' => '11',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Node 9',
+          'created' => '1444671588',
+          'changed' => '1390095701',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      10 =>
+        [
+          'nid' => '9',
+          'vid' => '12',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Once upon a time',
+          'created' => '1444671588',
+          'changed' => '1444671588',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      11 =>
+        [
+          'nid' => '10',
+          'vid' => '13',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The Real McCoy',
+          'created' => '1444238800',
+          'changed' => '1444238808',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      12 =>
+        [
+          'nid' => '10',
+          'vid' => '14',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The Real McCoy',
+          'created' => '1444238800',
+          'changed' => '1444238808',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      13 =>
+        [
+          'nid' => '10',
+          'vid' => '14',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Le Vrai McCoy',
+          'created' => '1444239050',
+          'changed' => '1444239050',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      14 =>
+        [
+          'nid' => '12',
+          'vid' => '15',
+          'langcode' => 'zu',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Abantu zulu',
+          'created' => '1444238800',
+          'changed' => '1444238808',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      15 =>
+        [
+          'nid' => '12',
+          'vid' => '16',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The Zulu People',
+          'created' => '1444239050',
+          'changed' => '1444239050',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      16 =>
+        [
+          'nid' => '12',
+          'vid' => '16',
+          'langcode' => 'zu',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Abantu zulu',
+          'created' => '1444238800',
+          'changed' => '1444238808',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      17 =>
+        [
+          'nid' => '14',
+          'vid' => '17',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'United Federation of Planets',
+          'created' => '1493066668',
+          'changed' => '1493066668',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      18 =>
+        [
+          'nid' => '15',
+          'vid' => '18',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Klingon Empire',
+          'created' => '1493066677',
+          'changed' => '1493066677',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      19 =>
+        [
+          'nid' => '16',
+          'vid' => '19',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Romulan Empire',
+          'created' => '1493066684',
+          'changed' => '1493066684',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      20 =>
+        [
+          'nid' => '17',
+          'vid' => '20',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Ferengi Commerce Authority',
+          'created' => '1493066693',
+          'changed' => '1493066693',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      21 =>
+        [
+          'nid' => '18',
+          'vid' => '21',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Ambassador Sarek',
+          'created' => '1493066711',
+          'changed' => '1494966544',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      22 =>
+        [
+          'nid' => '19',
+          'vid' => '22',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'New Forum Topic',
+          'created' => '1501955771',
+          'changed' => '1501955771',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      23 =>
+        [
+          'nid' => '12',
+          'vid' => '23',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The Zulu People',
+          'created' => '1444239050',
+          'changed' => '1444239050',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      24 =>
+        [
+          'nid' => '12',
+          'vid' => '23',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Le peuple zoulou',
+          'created' => '1520613038',
+          'changed' => '1520613305',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      25 =>
+        [
+          'nid' => '12',
+          'vid' => '23',
+          'langcode' => 'zu',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Abantu zulu',
+          'created' => '1444238800',
+          'changed' => '1444238808',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'zu',
+          'content_translation_outdated' => '0',
+        ],
+      26 =>
+        [
+          'nid' => '1',
+          'vid' => '2001',
+          'langcode' => 'und',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Test title rev 3',
+          'created' => '1390095702',
+          'changed' => '1420861423',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      27 =>
+        [
+          'nid' => '21',
+          'vid' => '2002',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'John Smith - EN',
+          'created' => '1534014650',
+          'changed' => '1534014650',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      28 =>
+        [
+          'nid' => '21',
+          'vid' => '2003',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'John Smith - EN',
+          'created' => '1534014650',
+          'changed' => '1534014650',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      29 =>
+        [
+          'nid' => '21',
+          'vid' => '2003',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'John Smith - FR',
+          'created' => '1534014687',
+          'changed' => '1534014687',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+    ];
+  }
+
+  /**
+   * Provides the expected node_field_revision table.
+   *
+   * @return array
+   *   Selected properties and fields on the revision.
+   */
+  protected function expectedRevisionEntityData() {
+    return [
+      $revision_data = [
+        // Node 1, revision 1, und.
+        0 =>
+          [
+            'log' => NULL,
+            'created' => '1390095702',
+            'changed' => '1390095702',
+          ],
+        // Node 2, revision 3, und.
+        1 =>
+          [
+            'log' => NULL,
+            'created' => '1420718386',
+            'changed' => '1420718386',
+          ],
+        // Node 3, revision 4, und.
+        2 =>
+          [
+            'log' => NULL,
+            'created' => '1390095701',
+            'changed' => '1390095701',
+          ],
+        // Node 1, revision 5, und.
+        3 =>
+          [
+            'log' => 'modified rev 2',
+            'created' => '1390095703',
+            'changed' => '1390095703',
+          ],
+        // Node 4, revision 6, und.
+        4 =>
+          [
+            'log' => NULL,
+            'created' => '1390095701',
+            'changed' => '1390095701',
+          ],
+        // Node 5, revision 7, und.
+        5 =>
+          [
+            'log' => NULL,
+            'created' => '1390095701',
+            'changed' => '1390095701',
+          ],
+        // Node 6, revision 8, und.
+        6 =>
+          [
+            'log' => NULL,
+            'created' => '1390095701',
+            'changed' => '1390095701',
+          ],
+        // Node 7, revision 9, und.
+        7 =>
+          [
+            'log' => NULL,
+            'created' => '1390095701',
+            'changed' => '1390095701',
+          ],
+        // Node 8, revision 10, und.
+        8 =>
+          [
+            'log' => NULL,
+            'created' => '1390095701',
+            'changed' => '1390095701',
+          ],
+        // Node 9, revision 11, und.
+        9 =>
+          [
+            'log' => NULL,
+            'created' => '1390095701',
+            'changed' => '1390095701',
+          ],
+        // Node 9, revision 12, und.
+        10 =>
+          [
+            'log' => NULL,
+            'created' => '1444671588',
+            'changed' => '1444671588',
+          ],
+        // Node 10, revision 13, en.
+        11 =>
+          [
+            'log' => NULL,
+            'created' => '1444238808',
+            'changed' => '1444238808',
+          ],
+        // Node 10, revision 14, en.
+        12 =>
+          [
+            'log' => NULL,
+            'created' => '1444239050',
+            'changed' => '1444238808',
+          ],
+        // Node 10, revision 14, fr.
+        13 =>
+          [
+            'log' => NULL,
+            'created' => '1444239050',
+            'changed' => '1444239050',
+          ],
+        // Node 12, revision 15, zu.
+        14 =>
+          [
+            'log' => NULL,
+            'created' => '1444238808',
+            'changed' => '1444238808',
+          ],
+        // Node 12, revision 16, en.
+        15 =>
+          [
+            'log' => NULL,
+            'created' => '1444239050',
+            'changed' => '1444239050',
+          ],
+        // Node 12, revision 16, zu.
+        16 =>
+          [
+            'log' => NULL,
+            'created' => '1444239050',
+            'changed' => '1444238808',
+          ],
+        // Node 14, revision 17, und.
+        17 =>
+          [
+            'log' => NULL,
+            'created' => '1493066668',
+            'changed' => '1493066668',
+          ],
+        // Node 15, revision 18, und.
+        18 =>
+          [
+            'log' => NULL,
+            'created' => '1493066677',
+            'changed' => '1493066677',
+          ],
+        // Node 16, revision 19, und.
+        19 =>
+          [
+            'log' => NULL,
+            'created' => '1493066684',
+            'changed' => '1493066684',
+          ],
+        // Node 17, revision 20, und.
+        20 =>
+          [
+            'log' => NULL,
+            'created' => '1493066693',
+            'changed' => '1493066693',
+          ],
+        // Node 18, revision 21, und.
+        21 =>
+          [
+            'log' => NULL,
+            'created' => '1494966544',
+            'changed' => '1494966544',
+          ],
+        // Node 19, revision 22, und.
+        22 =>
+          [
+            'log' => NULL,
+            'created' => '1501955771',
+            'changed' => '1501955771',
+          ],
+        // Node 12, revision 23, en.
+        23 =>
+          [
+            'log' => NULL,
+            'created' => '1520613305',
+            'changed' => '1444239050',
+          ],
+        // Node 12, revision 23, fr.
+        24 =>
+          [
+            'log' => NULL,
+            'created' => '1520613305',
+            'changed' => '1520613305',
+          ],
+        // Node 12, revision 23, zu.
+        25 =>
+          [
+            'log' => NULL,
+            'created' => '1520613305',
+            'changed' => '1444238808',
+          ],
+        // Node 1, revision 2001, und.
+        26 =>
+          [
+            'log' => 'modified rev 3',
+            'created' => '1420861423',
+            'changed' => '1420861423',
+          ],
+        // Node 21, revision 2002, en.
+        27 =>
+          [
+            'log' => NULL,
+            'created' => '1534014650',
+            'changed' => '1534014650',
+          ],
+        // Node 21, revision 2003, en.
+        28 =>
+          [
+            'log' => NULL,
+            'created' => '1534014687',
+            'changed' => '1534014650',
+          ],
+        // Node 21, revision 2003, fr.
+        29 =>
+          [
+            'log' => NULL,
+            'created' => '1534014687',
+            'changed' => '1534014687',
+          ],
+      ],
+    ];
+  }
+
+}
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeRevisionTest.php b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeRevisionTest.php
index 9dbfb54126..31571be5cc 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeRevisionTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeRevisionTest.php
@@ -66,17 +66,17 @@ public function testNodeRevision() {
     $this->assertIdentical('1', $node->id());
     $this->assertIdentical('2001', $node->getRevisionId());
     $this->assertIdentical('und', $node->langcode->value);
-    $this->assertIdentical('Test title rev 2', $node->getTitle());
-    $this->assertIdentical('body test rev 2', $node->body->value);
-    $this->assertIdentical('teaser test rev 2', $node->body->summary);
+    $this->assertIdentical('Test title rev 3', $node->getTitle());
+    $this->assertIdentical('body test rev 3', $node->body->value);
+    $this->assertIdentical('teaser test rev 3', $node->body->summary);
     $this->assertIdentical('2', $node->getRevisionUser()->id());
-    $this->assertIdentical('modified rev 2', $node->revision_log->value);
-    $this->assertIdentical('1390095702', $node->getRevisionCreationTime());
+    $this->assertIdentical('modified rev 3', $node->revision_log->value);
+    $this->assertIdentical('1420861423', $node->getRevisionCreationTime());
 
-    $this->assertRevision(1, 'und', 'Test title', NULL, '1420861423');
+    $this->assertRevision(1, 'und', 'Test title', NULL, '1390095702');
     $this->assertRevision(3, 'und', 'Test title rev 3', NULL, '1420718386');
     $this->assertRevision(4, 'und', 'Test page title rev 4', NULL, '1390095701');
-    $this->assertRevision(5, 'und', 'Test title rev 3', 'modified rev 3', '1390095703');
+    $this->assertRevision(5, 'und', 'Test title rev 2', 'modified rev 2', '1390095703');
     $this->assertRevision(6, 'und', 'Node 4', NULL, '1390095701');
     $this->assertRevision(7, 'und', 'Node 5', NULL, '1390095701');
     $this->assertRevision(8, 'und', 'Node 6', NULL, '1390095701');
@@ -92,7 +92,7 @@ public function testNodeRevision() {
     $this->assertRevision(20, 'und', 'Ferengi Commerce Authority', NULL, '1493066693');
     $this->assertRevision(21, 'und', 'Ambassador Sarek', NULL, '1494966544');
     $this->assertRevision(22, 'und', 'New Forum Topic', NULL, '1501955771');
-    $this->assertRevision(2001, 'und', 'Test title rev 2', 'modified rev 2', '1390095702');
+    $this->assertRevision(2001, 'und', 'Test title rev 3', 'modified rev 3', '1420861423');
     $this->assertRevision(2002, 'en', 'John Smith - EN', NULL, '1534014650');
 
     // Test that the revision translations are not migrated and there should not
@@ -101,6 +101,7 @@ public function testNodeRevision() {
     foreach ($ids as $id) {
       $this->assertNull($this->nodeStorage->loadRevision($id));
     }
+
   }
 
 }
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php
index c390af2db4..4a2ec634d0 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php
@@ -46,6 +46,11 @@ protected function setUp() {
    * Test node migration from Drupal 6 to 8.
    */
   public function testNode() {
+    // Confirm there are only classic node migration map tables. This shows
+    // that only the classic migration ran.
+    $results = $this->nodeMigrateMapTableCount('6');
+    $this->assertSame(13, $results['node']);
+    $this->assertSame(0, $results['node_complete']);
     $node = Node::load(1);
     $this->assertIdentical('1', $node->id(), 'Node 1 loaded.');
     $this->assertIdentical('und', $node->langcode->value);
@@ -54,10 +59,10 @@ public function testNode() {
     $this->assertIdentical('filtered_html', $node->body->format);
     $this->assertIdentical('story', $node->getType(), 'Node has the correct bundle.');
     $this->assertIdentical('Test title', $node->getTitle(), 'Node has the correct title.');
-    $this->assertIdentical('1388271197', $node->getCreatedTime(), 'Node has the correct created time.');
+    $this->assertIdentical('1390095702', $node->getCreatedTime(), 'Node has the correct created time.');
     $this->assertIdentical(FALSE, $node->isSticky());
     $this->assertIdentical('1', $node->getOwnerId());
-    $this->assertIdentical('1420861423', $node->getRevisionCreationTime());
+    $this->assertIdentical('1390095702', $node->getRevisionCreationTime());
 
     /** @var \Drupal\node\NodeInterface $node_revision */
     $node_revision = \Drupal::entityTypeManager()->getStorage('node')->loadRevision(1);
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeCompleteTest.php b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeCompleteTest.php
new file mode 100644
index 0000000000..6525de07af
--- /dev/null
+++ b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeCompleteTest.php
@@ -0,0 +1,947 @@
+<?php
+
+namespace Drupal\Tests\node\Kernel\Migrate\d7;
+
+use Drupal\migrate_drupal\NodeMigrateType;
+use Drupal\node\NodeInterface;
+use Drupal\Tests\file\Kernel\Migrate\d7\FileMigrationSetupTrait;
+use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
+use Drupal\Tests\migrate_drupal\Traits\CreateTestContentEntitiesTrait;
+use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait;
+
+/**
+ * Test class for a complete node migration for Drupal 7.
+ *
+ * @group migrate_drupal_7
+ */
+class MigrateNodeCompleteTest extends MigrateDrupal7TestBase {
+
+  use FileMigrationSetupTrait;
+  use CreateTestContentEntitiesTrait;
+  use NodeMigrateTypeTestTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'content_translation',
+    'comment',
+    'datetime',
+    'image',
+    'language',
+    'link',
+    'menu_ui',
+    // Required for translation migrations.
+    'migrate_drupal_multilingual',
+    'node',
+    'taxonomy',
+    'telephone',
+    'text',
+  ];
+
+  /**
+   * The entity storage for node.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $nodeStorage;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // Remove the classic node table made in setup.
+    $this->removeNodeMigrateMapTable(NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC, '7');
+
+    $this->fileMigrationSetup();
+
+    $this->installEntitySchema('comment');
+    $this->installEntitySchema('taxonomy_term');
+    $this->installSchema('comment', ['comment_entity_statistics']);
+    $this->installSchema('node', ['node_access']);
+    $this->installSchema('system', ['sequences']);
+
+    $this->createContent();
+
+    $this->nodeStorage = $this->container->get('entity_type.manager')
+      ->getStorage('node');
+    $this->nodeStorage->delete($this->nodeStorage->loadMultiple());
+
+    $this->migrateUsers();
+    $this->migrateFields();
+    $this->executeMigrations([
+      'language',
+      'd7_language_content_settings',
+      'd7_comment_field',
+      'd7_comment_field_instance',
+      'd7_node_complete',
+    ]);
+    $this->nodeStorage = $this->container->get('entity_type.manager')
+      ->getStorage('node');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getFileMigrationInfo() {
+    return [
+      'path' => 'public://sites/default/files/cube.jpeg',
+      'size' => '3620',
+      'base_path' => 'public://',
+      'plugin_id' => 'd7_file',
+    ];
+  }
+
+  /**
+   * Tests the complete node migration.
+   */
+  public function testNodeCompleteMigration() {
+    // Confirm there are only complete node migration map tables. This shows
+    // that only the complete migration ran.
+    $results = $this->nodeMigrateMapTableCount('7');
+    $this->assertSame(0, $results['node']);
+    $this->assertSame(6, $results['node_complete']);
+
+    $db = \Drupal::database();
+    $this->assertEquals($this->expectedNodeFieldRevisionTable(), $db->select('node_field_revision', 'nr')
+      ->fields('nr')
+      ->orderBy('vid')
+      ->orderBy('langcode')
+      ->execute()
+      ->fetchAll(\PDO::FETCH_ASSOC));
+    $this->assertEquals($this->expectedNodeFieldDataTable(), $db->select('node_field_data', 'nr')
+      ->fields('nr')
+      ->orderBy('nid')
+      ->orderBy('vid')
+      ->orderBy('langcode')
+      ->execute()
+      ->fetchAll(\PDO::FETCH_ASSOC));
+
+    // Now load and test each revision,
+    // including the field 'field_text_long_plain' which has text reflecting the
+    // revision. Note that source node 1, uses entity translation which does
+    // not have a migration for revisions of translations.
+    // See https://www.drupal.org/project/drupal/issues/3076447.
+    $data = $this->expectedRevisionEntityData()[0];
+    foreach ($this->expectedNodeFieldRevisionTable() as $key => $revision) {
+      $this->assertRevision($revision, $data[$key]);
+    }
+  }
+
+  /**
+   * Asserts various aspects of a node revision.
+   *
+   * @param array $revision
+   *   An array of revision data matching a node_field_revision table row.
+   * @param array $data
+   *   An array of revision data.
+   */
+  protected function assertRevision(array $revision, array $data) {
+    /* @var  \Drupal\node\NodeInterface $actual */
+    $actual = $this->nodeStorage->loadRevision($revision['vid'])
+      ->getTranslation($revision['langcode']);
+    $this->assertInstanceOf(NodeInterface::class, $actual);
+    $this->assertSame($revision['title'], $actual->getTitle(), sprintf("Title '%s' does not match actual '%s' for revision '%d' langcode '%s'", $revision['title'], $actual->getTitle(), $revision['vid'], $revision['langcode']));
+    $this->assertSame($revision['revision_translation_affected'], $actual->get('revision_translation_affected')->value, sprintf("revision_translation_affected '%s' does not match actual '%s' for revision '%d' langcode '%s'", $revision['revision_translation_affected'], $actual->get('revision_translation_affected')->value, $revision['vid'], $revision['langcode']));
+
+    $this->assertSame($data['created'], $actual->getRevisionCreationTime(), sprintf("Creation time '%s' does not match actual '%s' for revision '%d' langcode '%s'", $data['created'], $actual->getRevisionCreationTime(), $revision['vid'], $revision['langcode']));
+    $this->assertSame($data['changed'], $actual->getChangedTime(), sprintf("Changed time '%s' does not match actual '%s' for revision '%d' langcode '%s'", $data['changed'], $actual->getChangedTime(), $revision['vid'], $revision['langcode']));
+    $this->assertSame($data['log'], $actual->getRevisionLogMessage(), sprintf("Revision log '%s' does not match actual '%s' for revision '%d' langcode '%s'", var_export($data['log'], TRUE), $actual->getRevisionLogMessage(), $revision['vid'], $revision['langcode']));
+    if ($data['field_text_long_plain']) {
+      $this->assertSame($data['field_text_long_plain'], $actual->field_text_long_plain->value, sprintf("field_text_long_plain value '%s' does not match actual '%s' for revision '%d' langcode '%s'", var_export($data['field_text_long_plain'], TRUE), $actual->field_text_long_plain->value, $revision['vid'], $revision['langcode']));
+    }
+  }
+
+  /**
+   * Provides the expected node_field_data table.
+   *
+   * @return array
+   *   The expected table rows.
+   */
+  protected function expectedNodeFieldDataTable() {
+    return [
+      0 =>
+        [
+          'nid' => '1',
+          'vid' => '1',
+          'type' => 'test_content_type',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '2',
+          'title' => 'An English Node',
+          'created' => '1421727515',
+          'changed' => '1441032132',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      1 =>
+        [
+          'nid' => '2',
+          'vid' => '12',
+          'type' => 'article',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '2',
+          'title' => 'The thing about Deep Space 9',
+          'created' => '1441306772',
+          'changed' => '1564543637',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      2 =>
+        [
+          'nid' => '2',
+          'vid' => '12',
+          'type' => 'article',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Deep Space 9',
+          'created' => '1471428152',
+          'changed' => '1564543706',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      3 =>
+        [
+          'nid' => '4',
+          'vid' => '14',
+          'type' => 'article',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'en - The thing about Firefly',
+          'created' => '1478755314',
+          'changed' => '1564543929',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      4 =>
+        [
+          'nid' => '4',
+          'vid' => '14',
+          'type' => 'article',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Firefly',
+          'created' => '1478755274',
+          'changed' => '1564543810',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      5 =>
+        [
+          'nid' => '6',
+          'vid' => '6',
+          'type' => 'forum',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Comments are closed :-(',
+          'created' => '1504715414',
+          'changed' => '1504715414',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      6 =>
+        [
+          'nid' => '7',
+          'vid' => '7',
+          'type' => 'forum',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Comments are open :-)',
+          'created' => '1504715432',
+          'changed' => '1504715432',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      7 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'type' => 'blog',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The number 47',
+          'created' => '1551000341',
+          'changed' => '1552126247',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      8 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'type' => 'blog',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'fr - The number 47',
+          'created' => '1552126296',
+          'changed' => '1552126296',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      9 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'type' => 'blog',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The number 47',
+          'created' => '1552126363',
+          'changed' => '1552126363',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+    ];
+  }
+
+  /**
+   * Provides the expected node_field_revision table.
+   *
+   * @return array
+   *   The table.
+   */
+  protected function expectedNodeFieldRevisionTable() {
+    return [
+      0 =>
+        [
+          'nid' => '1',
+          'vid' => '1',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '2',
+          'title' => 'An English Node',
+          'created' => '1421727515',
+          'changed' => '1441032132',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      1 =>
+        [
+          'nid' => '2',
+          'vid' => '2',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '2',
+          'title' => 'The thing about Deep Space 9 (1st rev)',
+          'created' => '1441306772',
+          'changed' => '1564543588',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      2 =>
+        [
+          'nid' => '2',
+          'vid' => '3',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '2',
+          'title' => 'The thing about Deep Space 9 (1st rev)',
+          'created' => '1441306772',
+          'changed' => '1564543588',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      3 =>
+        [
+          'nid' => '2',
+          'vid' => '3',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Deep Space 9 (1st rev)',
+          'created' => '1471428152',
+          'changed' => '1564543677',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      4 =>
+        [
+          'nid' => '4',
+          'vid' => '4',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Firefly (1st rev)',
+          'created' => '1478755274',
+          'changed' => '1478755274',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      5 =>
+        [
+          'nid' => '4',
+          'vid' => '5',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'en - The thing about Firefly (1st rev)',
+          'created' => '1478755314',
+          'changed' => '1564543887',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      6 =>
+        [
+          'nid' => '4',
+          'vid' => '5',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Firefly (1st rev)',
+          'created' => '1478755274',
+          'changed' => '1478755274',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      7 =>
+        [
+          'nid' => '6',
+          'vid' => '6',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Comments are closed :-(',
+          'created' => '1504715414',
+          'changed' => '1504715414',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      8 =>
+        [
+          'nid' => '7',
+          'vid' => '7',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'Comments are open :-)',
+          'created' => '1504715432',
+          'changed' => '1504715432',
+          'promote' => '0',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => NULL,
+          'content_translation_outdated' => '0',
+        ],
+      9 =>
+        [
+          'nid' => '8',
+          'vid' => '8',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The number 47',
+          'created' => '1551000341',
+          'changed' => '1552126247',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      10 =>
+        [
+          'nid' => '8',
+          'vid' => '9',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The number 47',
+          'created' => '1551000341',
+          'changed' => '1552126247',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      11 =>
+        [
+          'nid' => '8',
+          'vid' => '9',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'fr - The number 47',
+          'created' => '1552126296',
+          'changed' => '1552126296',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      12 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'The number 47',
+          'created' => '1551000341',
+          'changed' => '1552126247',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      13 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'langcode' => 'fr',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'fr - The number 47',
+          'created' => '1552126296',
+          'changed' => '1552126296',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      14 =>
+        [
+          'nid' => '8',
+          'vid' => '10',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The number 47',
+          'created' => '1552126363',
+          'changed' => '1552126363',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      15 =>
+        [
+          'nid' => '2',
+          'vid' => '11',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '2',
+          'title' => 'The thing about Deep Space 9',
+          'created' => '1441306772',
+          'changed' => '1564543637',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      16 =>
+        [
+          'nid' => '2',
+          'vid' => '11',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Deep Space 9 (1st rev)',
+          'created' => '1471428152',
+          'changed' => '1564543637',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      17 =>
+        [
+          'nid' => '2',
+          'vid' => '12',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '2',
+          'title' => 'The thing about Deep Space 9',
+          'created' => '1441306772',
+          'changed' => '1564543637',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      18 =>
+        [
+          'nid' => '2',
+          'vid' => '12',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Deep Space 9',
+          'created' => '1471428152',
+          'changed' => '1564543706',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'en',
+          'content_translation_outdated' => '0',
+        ],
+      19 =>
+        [
+          'nid' => '4',
+          'vid' => '13',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'en - The thing about Firefly (1st rev)',
+          'created' => '1478755314',
+          'changed' => '1564543887',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      20 =>
+        [
+          'nid' => '4',
+          'vid' => '13',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Firefly',
+          'created' => '1478755274',
+          'changed' => '1564543810',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      21 =>
+        [
+          'nid' => '4',
+          'vid' => '14',
+          'langcode' => 'en',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'en - The thing about Firefly',
+          'created' => '1478755314',
+          'changed' => '1564543929',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '0',
+          'revision_translation_affected' => '1',
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+      22 =>
+        [
+          'nid' => '4',
+          'vid' => '14',
+          'langcode' => 'is',
+          'status' => '1',
+          'uid' => '1',
+          'title' => 'is - The thing about Firefly',
+          'created' => '1478755274',
+          'changed' => '1564543810',
+          'promote' => '1',
+          'sticky' => '0',
+          'default_langcode' => '1',
+          'revision_translation_affected' => NULL,
+          'content_translation_source' => 'is',
+          'content_translation_outdated' => '0',
+        ],
+    ];
+  }
+
+  /**
+   * Provides the expected node_field_revision table.
+   *
+   * @return array
+   *   Selected properties and fields on the revision.
+   */
+  protected function expectedRevisionEntityData() {
+    return [
+      $revision_data = [
+        // Node 1, revision 1, en.
+        0 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1441032132',
+            'changed' => '1441032132',
+          ],
+        // Node 2, revision 2, en.
+        1 =>
+          [
+            'log' => 'DS9 1st rev',
+            'field_text_long_plain' => 'DS9 1st rev',
+            'created' => '1564543588',
+            'changed' => '1564543588',
+          ],
+        // Node 2, revision 3, en.
+        2 =>
+          [
+            'log' => 'is - DS9 1st rev',
+            'field_text_long_plain' => 'DS9 1st rev',
+            'created' => '1564543677',
+            'changed' => '1564543588',
+          ],
+        // Node 2, revision 3, is.
+        3 =>
+          [
+            'log' => 'is - DS9 1st rev',
+            'field_text_long_plain' => 'is - DS9 1st rev',
+            'created' => '1564543677',
+            'changed' => '1564543677',
+          ],
+        // Node 4, revision 4, is.
+        4 =>
+          [
+            'log' => 'is - Firefly 1st rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1478755274',
+            'changed' => '1478755274',
+          ],
+        // Node 4, revision 5, en.
+        5 =>
+          [
+            'log' => 'Firefly 1st rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543887',
+            'changed' => '1564543887',
+          ],
+        // Node 4, revision 5, is.
+        6 =>
+          [
+            'log' => 'Firefly 1st rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543887',
+            'changed' => '1478755274',
+          ],
+        // Node 6, revision 6, en.
+        7 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1504715414',
+            'changed' => '1504715414',
+          ],
+        // Node 7, revision 7, en.
+        8 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1504715432',
+            'changed' => '1504715432',
+          ],
+        // Node 8, revision 8, en.
+        9 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1552126247',
+            'changed' => '1552126247',
+          ],
+        // Node 8, revision 9, en.
+        10 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1552126296',
+            'changed' => '1552126247',
+          ],
+        // Node 8, revision 9, fr.
+        11 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1552126296',
+            'changed' => '1552126296',
+          ],
+        // Node 8, revision 10, en.
+        12 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1552126363',
+            'changed' => '1552126247',
+          ],
+        // Node 8, revision 10, fr.
+        13 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1552126363',
+            'changed' => '1552126296',
+          ],
+        // Node 8, revision 10, is.
+        14 =>
+          [
+            'log' => NULL,
+            'field_text_long_plain' => NULL,
+            'created' => '1552126363',
+            'changed' => '1552126363',
+          ],
+        // Node 2, revision 11, en.
+        15 =>
+          [
+            'log' => 'DS9 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543637',
+            'changed' => '1564543637',
+          ],
+        // Node 2, revision 11, is.
+        16 =>
+          [
+            'log' => 'DS9 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543637',
+            'changed' => '1564543637',
+          ],
+        // Node 2, revision 12, en.
+        17 =>
+          [
+            'log' => 'is - DS9 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543706',
+            'changed' => '1564543637',
+          ],
+        // Node 2, revision 12, is.
+        18 =>
+          [
+            'log' => 'is - DS9 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543706',
+            'changed' => '1564543706',
+          ],
+        // Node 4, revision 13, en.
+        19 =>
+          [
+            'log' => 'is - Firefly 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543810',
+            'changed' => '1564543887',
+          ],
+        // Node 4, revision 13, is.
+        20 =>
+          [
+            'log' => 'is - Firefly 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543810',
+            'changed' => '1564543810',
+          ],
+        // Node 4, revision 14, en.
+        21 =>
+          [
+            'log' => 'Firefly 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543929',
+            'changed' => '1564543929',
+          ],
+        // Node 4, revision 14, is.
+        22 =>
+          [
+            'log' => 'Firefly 2nd rev',
+            'field_text_long_plain' => NULL,
+            'created' => '1564543929',
+            'changed' => '1564543810',
+          ],
+      ],
+    ];
+  }
+
+}
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeRevisionTest.php b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeRevisionTest.php
index 563bcf9be2..8c04019bb0 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeRevisionTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeRevisionTest.php
@@ -112,8 +112,8 @@ protected function assertRevision($id, $langcode, $title, $log, $timestamp) {
    */
   public function testNodeRevisions() {
     $this->assertRevision(1, 'en', 'An English Node', NULL, '1441032132');
-    $this->assertRevision(2, 'en', 'The thing about Deep Space 9', NULL, '1471428152');
-    $this->assertRevision(4, 'is', 'is - The thing about Firefly', NULL, '1478755314');
+    $this->assertRevision(2, 'en', 'The thing about Deep Space 9 (1st rev)', 'DS9 1st rev', '1564543588');
+    $this->assertRevision(4, 'is', 'is - The thing about Firefly (1st rev)', 'is - Firefly 1st rev', '1478755274');
     $this->assertRevision(6, 'en', 'Comments are closed :-(', NULL, '1504715414');
     $this->assertRevision(7, 'en', 'Comments are open :-)', NULL, '1504715432');
     $this->assertRevision(8, 'en', 'The number 47', NULL, '1552126363');
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php
index 25aa75654f..8decc488b7 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php
@@ -149,6 +149,12 @@ protected function assertRevision($id, $title, $uid, $log, $timestamp) {
    * Test node migration from Drupal 7 to 8.
    */
   public function testNode() {
+    // Confirm there are only classic node migration map tables. This shows
+    // that only the classic migration ran.
+    $results = $this->nodeMigrateMapTableCount('7');
+    $this->assertSame(7, $results['node']);
+    $this->assertSame(0, $results['node_complete']);
+
     $this->assertEntity(1, 'test_content_type', 'en', 'An English Node', '2', TRUE, '1421727515', '1441032132', TRUE, FALSE);
     $this->assertRevision(1, 'An English Node', '1', NULL, '1441032132');
 
diff --git a/core/modules/path/migrations/d6_url_alias.yml b/core/modules/path/migrations/d6_url_alias.yml
index 747a06805b..2ef20469f9 100644
--- a/core/modules/path/migrations/d6_url_alias.yml
+++ b/core/modules/path/migrations/d6_url_alias.yml
@@ -35,7 +35,11 @@ process:
         - 1
     -
       plugin: migration_lookup
-      migration: d6_node_translation
+      migration:
+        - d6_node_complete
+        - d6_node_translation
+    -
+      plugin: node_complete_node_translation_lookup
   langcode:
     -
       plugin: null_coalesce
diff --git a/core/modules/path/migrations/d7_url_alias.yml b/core/modules/path/migrations/d7_url_alias.yml
index b49686a7fb..0add8532a3 100644
--- a/core/modules/path/migrations/d7_url_alias.yml
+++ b/core/modules/path/migrations/d7_url_alias.yml
@@ -34,7 +34,11 @@ process:
         - 1
     -
       plugin: migration_lookup
-      migration: d7_node_translation
+      migration:
+        - d7_node_complete
+        - d7_node_translation
+    -
+      plugin: node_complete_node_translation_lookup
   langcode:
     plugin: null_coalesce
     source:
diff --git a/core/modules/statistics/migrations/statistics_node_counter.yml b/core/modules/statistics/migrations/statistics_node_counter.yml
index 748a4a83c0..0c2aa71d71 100644
--- a/core/modules/statistics/migrations/statistics_node_counter.yml
+++ b/core/modules/statistics/migrations/statistics_node_counter.yml
@@ -10,8 +10,14 @@ process:
   nid:
     -
       plugin: migration_lookup
-      migration: [d6_node, d7_node]
+      migration:
+        - d6_node_complete
+        - d7_node_complete
+        - d6_node
+        - d7_node
       source: nid
+    -
+      plugin: node_complete_node_lookup
     -
       plugin: skip_on_empty
       method: row
diff --git a/core/modules/taxonomy/migrations/d6_term_node.yml b/core/modules/taxonomy/migrations/d6_term_node.yml
index fdb8cc9a41..1e358bf0b4 100644
--- a/core/modules/taxonomy/migrations/d6_term_node.yml
+++ b/core/modules/taxonomy/migrations/d6_term_node.yml
@@ -10,8 +10,12 @@ process:
   nid:
     -
       plugin: migration_lookup
-      migration: d6_node
+      migration:
+        - d6_node_complete
+        - d6_node
       source: nid
+    -
+      plugin: node_complete_node_lookup
     -
       plugin: skip_on_empty
       method: row
diff --git a/core/modules/taxonomy/migrations/d6_term_node_revision.yml b/core/modules/taxonomy/migrations/d6_term_node_revision.yml
index 9487984f94..4b196ac2df 100644
--- a/core/modules/taxonomy/migrations/d6_term_node_revision.yml
+++ b/core/modules/taxonomy/migrations/d6_term_node_revision.yml
@@ -11,8 +11,12 @@ process:
   vid:
     -
       plugin: migration_lookup
-      migration: d6_node_revision
+      migration:
+        - d6_node_copmplete
+        - d6_node_revision
       source: vid
+    -
+      plugin: node_complete_node_revision_lookup
     -
       plugin: skip_on_empty
       method: row
diff --git a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeComplete.php b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeComplete.php
new file mode 100644
index 0000000000..77e4db72f1
--- /dev/null
+++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeComplete.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Drupal\Tests\taxonomy\Kernel\Migrate\d6;
+
+use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
+use Drupal\migrate_drupal\NodeMigrateType;
+use Drupal\node\Entity\Node;
+
+/**
+ * Upgrade taxonomy term node associations.
+ *
+ * @group migrate_drupal_6
+ */
+class MigrateTermNodeComplete extends MigrateDrupal6TestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'content_translation',
+    'language',
+    'menu_ui',
+    // A requirement for d6_node_translation.
+    'migrate_drupal_multilingual',
+    'taxonomy',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // Remove the classic node table made in setup.
+    $this->removeNodeMigrateMapTable(NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC, '6');
+
+    $this->installSchema('node', ['node_access']);
+    $this->installEntitySchema('node');
+
+    $this->executeMigration('language');
+    $this->migrateUsers(FALSE);
+    $this->migrateFields();
+    $this->executeMigrations(['d6_node_settings', 'd6_node_complete']);
+    $this->migrateTaxonomy();
+    // This is a base plugin ID and we want to run all derivatives.
+    $this->executeMigrations(['d6_term_node']);
+  }
+
+  /**
+   * Tests the Drupal 6 term-node association to Drupal 8 migration.
+   */
+  public function testTermNode() {
+    $this->container->get('entity_type.manager')
+      ->getStorage('node')
+      ->resetCache([1, 2]);
+
+    $nodes = Node::loadMultiple([1, 2]);
+    $node = $nodes[1];
+    $this->assertSame(1, count($node->field_vocabulary_1_i_0_));
+    $this->assertSame('1', $node->field_vocabulary_1_i_0_[0]->target_id);
+    $node = $nodes[2];
+    $this->assertSame(2, count($node->field_vocabulary_2_i_1_));
+    $this->assertSame('2', $node->field_vocabulary_2_i_1_[0]->target_id);
+    $this->assertSame('3', $node->field_vocabulary_2_i_1_[1]->target_id);
+  }
+
+}
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 1c8dbee9e7..8208086121 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -741,6 +741,19 @@
  */
 $settings['entity_update_backup'] = TRUE;
 
+/**
+ * Node migration type.
+ *
+ * This is used to force the migration system to use the classic node migrations
+ * instead of the default complete node migrations. The migration system will
+ * use the classic node migration only if there are existing migrate_map tables
+ * for the classic node migrations and they contain data. These tables may not
+ * exist if you are developing custom migrations and do not want to use the
+ * complete node migrations. Set this to TRUE to force the use of the classic
+ * node migrations.
+ */
+$settings['migrate_node_migrate_type_classic'] = FALSE;
+
 /**
  * Load local development override configuration, if available.
  *
