diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
index 8ef5f48..364c973 100644
--- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
@@ -690,14 +690,20 @@ public function buildOverviewForm(array $form, FormStateInterface $form_state) {
     $form['#title'] = $this->t('Drupal Upgrade');
 
     if ($date_performed = $this->state->get('migrate_drupal_ui.performed')) {
-      // @todo Add back support for rollbacks and incremental migrations.
-      //   https://www.drupal.org/node/2687843
+      // @todo Add back support for rollbacks.
       //   https://www.drupal.org/node/2687849
       $form['upgrade_option_item'] = [
         '#type' => 'item',
-        '#prefix' => $this->t('An upgrade has already been performed on this site. To perform a new migration, create a clean and empty new install of Drupal 8. Rollbacks and incremental migrations are not yet supported through the user interface. For more information, see the <a href=":url">upgrading handbook</a>.', [':url' => 'https://www.drupal.org/upgrade/migrate']),
+        '#prefix' => $this->t('An upgrade has already been performed on this site. To perform a new migration, create a clean and empty new install of Drupal 8. Rollbacks are not yet supported through the user interface. For more information, see the <a href=":url">upgrading handbook</a>.', [':url' => 'https://www.drupal.org/upgrade/migrate']),
         '#description' => $this->t('<p>Last upgrade: @date</p>', ['@date' => $this->dateFormatter->format($date_performed)]),
       ];
+      $form['actions']['incremental'] = [
+        '#type' => 'submit',
+        '#value' => $this->t('Import additional configuration and content'),
+        '#button_type' => 'primary',
+        '#validate' => ['::validateIncrementalOverviewForm'],
+        '#submit' => ['::submitIncrementalOverviewForm'],
+      ];
       return $form;
     }
     else {
@@ -740,6 +746,46 @@ public function buildOverviewForm(array $form, FormStateInterface $form_state) {
   }
 
   /**
+   * Validation handler for the incremental overview form.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   */
+  public function validateIncrementalOverviewForm(array &$form, FormStateInterface $form_state) {
+    // Retrieve source base path from state.
+    $source_base_path = \Drupal::state()->get('migrate.source_base_path_state_key', '');
+    if (!$source_base_path) {
+      $form_state->setValue('step', 'credentials');
+      $form_state->setRebuild();
+    }
+    // Retrieve the database driver from state.
+    $database_state_key = \Drupal::state()->get('migrate.fallback_state_key', '');
+    if ($database_state_key) {
+      $database = \Drupal::state()->get($database_state_key, [])['database'];
+      $this->setUpSourceAndMigrations($form_state, $database, $source_base_path);
+    }
+    else {
+      $form_state->setValue('step', 'credentials');
+      $form_state->setRebuild();
+    }
+  }
+
+  /**
+   * Form submission handler for the incremental overview form.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   */
+  public function submitIncrementalOverviewForm(array &$form, FormStateInterface $form_state) {
+    $form_state->setValue('step', 'confirm');
+    $form_state->setRebuild();
+  }
+
+  /**
    * Form submission handler for the overview form.
    *
    * @param array $form
@@ -861,7 +907,6 @@ public function buildCredentialForm(array $form, FormStateInterface $form_state)
    *   The current state of the form.
    */
   public function validateCredentialForm(array &$form, FormStateInterface $form_state) {
-
     // Retrieve the database driver from the form, use reflection to get the
     // namespace, and then construct a valid database array the same as in
     // settings.php.
@@ -883,11 +928,22 @@ public function validateCredentialForm(array &$form, FormStateInterface $form_st
       return;
     }
 
+    $source_base_path = $form_state->getValue('source_base_path');
+    $this->setUpSourceAndMigrations($form_state, $database, $source_base_path, $database['driver'] . '][0');
+  }
+
+  /**
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   * @param array $database
+   * @param string $source_base_path
+   * @param string $form_error_name
+   */
+  protected function setUpSourceAndMigrations(FormStateInterface $form_state, array $database, $source_base_path, $form_error_name = '') {
     try {
       $connection = $this->getConnection($database);
       $version = $this->getLegacyDrupalVersion($connection);
       if (!$version) {
-        $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database does not contain a recognizable Drupal version.'));
+        $form_state->setErrorByName($form_error_name, $this->t('Source database does not contain a recognizable Drupal version.'));
       }
       else {
         $this->createDatabaseStateSettings($database, $version);
@@ -903,9 +959,12 @@ public function validateCredentialForm(array &$form, FormStateInterface $form_st
           $migration_array[$migration->id()] = $migration->label();
         }
 
+        // Store the source_base_path in state.
+        \Drupal::state()->set('migrate.source_base_path_state_key', $source_base_path);
+
         // Store the retrieved migration IDs in form storage.
         $form_state->set('migrations', $migration_array);
-        $form_state->set('source_base_path', $form_state->getValue('source_base_path'));
+        $form_state->set('source_base_path', $source_base_path);
 
         // Store the retrived system data in form storage.
         $form_state->set('system_data', $system_data);
@@ -923,8 +982,9 @@ public function validateCredentialForm(array &$form, FormStateInterface $form_st
         ],
       ];
 
-      $form_state->setErrorByName($database['driver'] . '][0', $this->renderer->renderPlain($error_message));
+      $form_state->setErrorByName($form_error_name, $this->renderer->renderPlain($error_message));
     }
+
   }
 
   /**
diff --git a/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
index 7a2d2c2..b87954f 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
@@ -137,16 +137,40 @@ protected function testMigrateUpgrade() {
     $this->assertText('Are you sure?');
     $this->drupalPostForm(NULL, [], t('Perform upgrade'));
     $this->assertText(t('Congratulations, you upgraded Drupal!'));
+    $this->assertMigrationResults($this->getEntityCounts());
 
+    // Enable the aggregator module so we can test incremental migration.
+    \Drupal::service('module_installer')->install(['aggregator']);
+    $this->drupalGet('/upgrade');
+    $this->assertText('An upgrade has already been performed on this site.');
+    $this->drupalPostForm(NULL, [], t('Import additional configuration and content'));
+    $this->assertResponse(200);
+    $this->assertText('Are you sure?');
+    $this->drupalPostForm(NULL, [], t('Perform upgrade'));
+    $this->assertText(t('Congratulations, you upgraded Drupal!'));
+    $this->assertMigrationResults($this->getEntityCountsIncremental());
+  }
+
+  /**
+   * Checks that migrations have been performed successfully.
+   *
+   * @param array $expected_counts
+   *   The expected counts of each entity type.
+   *
+   * @return bool
+   *   TRUE if successful, FALSE if not.
+   */
+  protected function assertMigrationResults(array $expected_counts) {
+    $return = TRUE;
     // Have to reset all the statics after migration to ensure entities are
     // loadable.
     $this->resetAll();
 
-    $expected_counts = $this->getEntityCounts();
     foreach (array_keys(\Drupal::entityTypeManager()->getDefinitions()) as $entity_type) {
       $real_count = count(\Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple());
       $expected_count = isset($expected_counts[$entity_type]) ? $expected_counts[$entity_type] : 0;
-      $this->assertEqual($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count.");
+      $result = $this->assertEqual($expected_count, $real_count, "Found $real_count $entity_type entities, expected $expected_count.");
+      $return = $return & $result;
     }
 
     $version_tag = 'Drupal ' . $this->getLegacyDrupalVersion($this->sourceDatabase);
@@ -168,14 +192,16 @@ protected function testMigrateUpgrade() {
         // MigrateIdMapInterface::STATUS_IMPORTED.
         if ($row['source_row_status'] == MigrateIdMapInterface::STATUS_FAILED || $row['source_row_status'] == MigrateIdMapInterface::STATUS_NEEDS_UPDATE) {
           $this->fail($message);
+          $return = FALSE;
         }
         else {
           $this->pass($message);
+          $return = $return & TRUE;
         }
       }
     }
+    return $return;
   }
-
   /**
    * Gets the source base path for the concrete test.
    *
@@ -192,4 +218,12 @@ protected function testMigrateUpgrade() {
    */
   abstract protected function getEntityCounts();
 
+  /**
+   * Gets the expected number of entities per entity type after incremental.
+   *
+   * @return int[]
+   *   An array of expected counts keyed by entity type ID.
+   */
+  abstract protected function getEntityCountsIncremental();
+
 }
diff --git a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
index ea0b588..4df4a79 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
@@ -72,6 +72,19 @@ protected function getEntityCounts() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  protected function getEntityCountsIncremental() {
+    $counts = $this->getEntityCounts();
+    $counts['aggregator_feed'] = 1;
+    $counts['aggregator_item'] = 1;
+    $counts['view'] = 14;
+    $counts['entity_view_display'] = 35;
+    $counts['entity_view_mode'] = 14;
+    return $counts;
+  }
+
+  /**
    * Executes all steps of migrations upgrade.
    */
   protected function testMigrateUpgrade() {
diff --git a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
index 1d3ce61..bf24185 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
@@ -72,6 +72,19 @@ protected function getEntityCounts() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  protected function getEntityCountsIncremental() {
+    $counts = $this->getEntityCounts();
+    $counts['aggregator_feed'] = 1;
+    $counts['aggregator_item'] = 10;
+    $counts['view'] = 14;
+    $counts['entity_view_display'] = 25;
+    $counts['entity_view_mode'] = 12;
+    return $counts;
+  }
+
+  /**
    * Executes all steps of migrations upgrade.
    */
   protected function testMigrateUpgrade() {
