diff --git a/core/includes/config.inc b/core/includes/config.inc
index 3e22534..e903fcc 100644
--- a/core/includes/config.inc
+++ b/core/includes/config.inc
@@ -4,6 +4,7 @@
 use Drupal\Core\Config\FileStorage;
 use Drupal\Core\Config\NullStorage;
 use Drupal\Core\Config\StorageInterface;
+use Symfony\Component\Yaml\Dumper;
 
 /**
  * @file
@@ -295,3 +296,46 @@ function config_get_module_config_entities($module) {
     return ($entity_info['module'] == $module) && is_subclass_of($entity_info['class'], 'Drupal\Core\Config\Entity\ConfigEntityInterface');
   });
 }
+
+/**
+ * Return a formatted diff of a named config between two storages.
+ *
+ * @param Drupal\Core\Config\StorageInterface $source_storage
+ *   The storage to diff configuration from.
+ * @param Drupal\Core\Config\StorageInterface $target_storage
+ *   The storage to diff configuration to.
+ * @param string $name
+ *   The name of the configuration object to diff.
+ *
+ * @return string
+ *   A formatted string showing the difference between the two storages.
+ *
+ * @todo Make renderer injectable
+ */
+function config_diff(StorageInterface $source_storage, StorageInterface $target_storage, $name) {
+  require_once DRUPAL_ROOT . '/core/lib/Drupal/Component/Diff/DiffEngine.php';
+
+  // Implementers of StorageInterface::read() return keyed arrays of
+  // configuration data. The diff class wants an array of strings, each
+  // representing one line of the file we're diffing. So we convert the config
+  // array to YAML, then explode it into an array that the differ can deal with.
+  $dumper = new Dumper();
+  $dumper->setIndentation(2);
+
+  $source_data = explode("\n", $dumper->dump($source_storage->read($name), PHP_INT_MAX));
+  $target_data = explode("\n", $dumper->dump($target_storage->read($name), PHP_INT_MAX));
+
+  $diff = new Diff($source_data, $target_data);
+  $formatter = new DrupalDiffFormatter();
+  $formatter->show_header = FALSE;
+
+  $variables = array(
+    'header' => array(
+      array('data' => t('Old'), 'colspan' => '2'),
+      array('data' => t('New'), 'colspan' => '2'),
+    ),
+    'rows' => $formatter->format($diff),
+  );
+
+  return theme('table', $variables);
+}
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 3ce399b..e4d3f48 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -3186,5 +3186,36 @@ function drupal_common_theme() {
     'container' => array(
       'render element' => 'element',
     ),
+    'diff_header_line' => array(
+      'variables' => array('lineno' => NULL),
+    ),
+    'diff_content_line' => array(
+      'variables' => array('line' => NULL),
+    ),
+    'diff_empty_line' => array(
+      'variables' => array('line' => NULL),
+    ),
+
   );
 }
+
+/**
+ * Theme function for a header line in the diff.
+ */
+function theme_diff_header_line($vars) {
+  return '<strong>' . t('Line %lineno', array('%lineno' => $vars['lineno'])) . '</strong>';
+}
+
+/**
+ * Theme function for a content line in the diff.
+ */
+function theme_diff_content_line($vars) {
+  return '<div>' . $vars['line'] . '</div>';
+}
+
+/**
+ * Theme function for an empty line in the diff.
+ */
+function theme_diff_empty_line($vars) {
+  return $vars['line'];
+}
diff --git a/core/modules/config/config.admin.inc b/core/modules/config/config.admin.inc
index c15e02a..c2b2348 100644
--- a/core/modules/config/config.admin.inc
+++ b/core/modules/config/config.admin.inc
@@ -40,6 +40,10 @@ function config_admin_sync_form(array &$form, array &$form_state, StorageInterfa
     if (empty($config_files)) {
       continue;
     }
+
+    // Add the CSS for the inline diff.
+    $form['#attached']['css'] = array(drupal_get_path('module', 'system') . '/system.diff.css');
+
     // @todo A table caption would be more appropriate, but does not have the
     //   visual importance of a heading.
     $form[$config_change_type]['heading'] = array(
@@ -63,8 +67,35 @@ function config_admin_sync_form(array &$form, array &$form_state, StorageInterfa
       '#theme' => 'table',
       '#header' => array('Name'),
     );
+
     foreach ($config_files as $config_file) {
       $form[$config_change_type]['list']['#rows'][] = array($config_file);
+
+      switch ($config_change_type) {
+        case 'change':
+          $fieldset_title = t('View changes of @config_file', array('@config_file' => $config_file));
+          break;
+        case 'create':
+          $fieldset_title = t('View added file @config_file', array('@config_file' => $config_file));
+          break;
+        case 'delete':
+          $fieldset_title = t('View removed file @config_file', array('@config_file' => $config_file));
+          break;
+      }
+
+      // Show the additions/changes/deletions in a nice collapsible fieldset.
+      $fieldset = array(
+        '#type' => 'fieldset',
+        '#title' => $fieldset_title,
+        '#collapsible' => TRUE,
+        '#collapsed' => TRUE,
+      );
+      $fieldset['diff'] = array(
+        '#markup' => config_diff($target_storage, $source_storage, $config_file),
+      );
+      $form[$config_change_type]['list']['#rows'][] = array(
+        array('data' => $fieldset),
+      );
     }
   }
 }
diff --git a/core/modules/system/system.diff.css b/core/modules/system/system.diff.css
new file mode 100644
index 0000000..8187561
--- /dev/null
+++ b/core/modules/system/system.diff.css
@@ -0,0 +1,86 @@
+
+html.js .diff-js-hidden { display: none; }
+
+/**
+ * Inline diff metadata
+ */
+.diff-inline-metadata {
+  padding:4px;
+  border:1px solid #ddd;
+  background:#fff;
+  margin:0px 0px 10px;
+}
+
+.diff-inline-legend { font-size:11px; }
+
+.diff-inline-legend span,
+.diff-inline-legend label { margin-right:5px; }
+
+/**
+ * Inline diff markup
+ */
+span.diff-deleted { color:#ccc; }
+span.diff-deleted img { border: solid 2px #ccc; }
+span.diff-changed { background:#ffb; }
+span.diff-changed img { border:solid 2px #ffb; }
+span.diff-added { background:#cfc; }
+span.diff-added img { border: solid 2px #cfc; }
+
+/**
+ * Traditional split diff theming
+ */
+table.diff {
+  border-spacing: 4px;
+  margin-bottom: 20px;
+  table-layout: fixed;
+  width: 100%;
+}
+table.diff tr.even, table.diff tr.odd {
+  background-color: inherit;
+  border: none;
+}
+td.diff-prevlink {
+  text-align: left;
+}
+td.diff-nextlink {
+  text-align: right;
+}
+td.diff-section-title, div.diff-section-title {
+  background-color: #f0f0ff;
+  font-size: 0.83em;
+  font-weight: bold;
+  padding: 0.1em 1em;
+}
+td.diff-deletedline {
+  background-color: #ffa;
+  width: 50%;
+}
+td.diff-addedline {
+  background-color: #afa;
+  width: 50%;
+}
+td.diff-context {
+  background-color: #fafafa;
+}
+span.diffchange {
+  color: #f00;
+  font-weight: bold;
+}
+
+table.diff col.diff-marker {
+  width: 1.4em;
+}
+table.diff col.diff-content {
+  width: 50%;
+}
+table.diff th {
+  padding-right: inherit;
+}
+table.diff td div {
+  overflow: auto;
+  padding: 0.1ex 0.5em;
+  word-wrap: break-word;
+}
+table.diff td {
+  padding: 0.1ex 0.4em;
+}
