diff --git a/lib/Drupal/views/Tests/ViewStorageTest.php b/lib/Drupal/views/Tests/ViewStorageTest.php
index 6e300a7..960b3ae 100644
--- a/lib/Drupal/views/Tests/ViewStorageTest.php
+++ b/lib/Drupal/views/Tests/ViewStorageTest.php
@@ -79,6 +79,9 @@ class ViewStorageTest extends WebTestBase {
     // Confirm we have the correct controller class.
     $this->assertTrue($this->controller instanceof ViewStorageController, 'The correct controller is loaded.');
 
+    // Export config before the CRUD tests, mainly for the purpose of reverting.
+    config_export();
+
     // CRUD tests.
     $this->loadTests();
     $this->createTests();
@@ -86,6 +89,7 @@ class ViewStorageTest extends WebTestBase {
     $this->deleteTests();
     $this->displayTests();
     $this->statusTests();
+    $this->revertTests();
   }
 
   /**
@@ -288,6 +292,27 @@ class ViewStorageTest extends WebTestBase {
   }
 
   /**
+   * Tests that views can be reverted.
+   */
+  protected function revertTests() {
+    // Use a view we have not used in any other tests.
+    $view = $this->loadView('comments_recent');
+    $this->assertFalse($view->isOverridden(), 'The view is not overridden.');
+
+    // Modify the view and save it.
+    $view->core = 9;
+    $view->save();
+
+    $view = $this->loadView('comments_recent');
+    $this->assertTrue($view->isOverridden(), 'The view is overridden.');
+
+    // Test reverting.
+    $view->revert();
+    $view = $this->loadView('comments_recent');
+    $this->assertFalse($view->isOverridden(), 'The view has been reverted and is not overridden.');
+  }
+
+  /**
    * Loads a single configuration entity from the controller.
    *
    * @param string $view_name
diff --git a/lib/Drupal/views/ViewListController.php b/lib/Drupal/views/ViewListController.php
index c3c7231..3468168 100644
--- a/lib/Drupal/views/ViewListController.php
+++ b/lib/Drupal/views/ViewListController.php
@@ -52,6 +52,10 @@ class ViewListController extends EntityListControllerBase {
     $items["$path/view/%views_ui_view/disable"] = array(
       'title' => 'Disable a view',
     ) + $ajax_base;
+    // Add a revert link.
+    $items["$path/view/%views_ui_view/revert"] = array(
+      'title' => 'Disable a view',
+    ) + $ajax_base;
 
     return $items;
   }
@@ -146,8 +150,7 @@ class ViewListController extends EntityListControllerBase {
         'href' => "$path/disable",
       );
     }
-    // This property doesn't exist yet.
-    if (!empty($view->overridden)) {
+    if ($view->isOverridden()) {
       $definition['revert'] = array(
         'title' => t('Revert'),
         'href' => "$path/revert",
diff --git a/lib/Drupal/views/ViewStorage.php b/lib/Drupal/views/ViewStorage.php
index 0471d69..ae0edc8 100644
--- a/lib/Drupal/views/ViewStorage.php
+++ b/lib/Drupal/views/ViewStorage.php
@@ -126,6 +126,13 @@ class ViewStorage extends ConfigEntityBase implements ViewStorageInterface {
   public $module = 'views';
 
   /**
+   * The overridden status of this view.
+   *
+   * @var bool
+   */
+  protected $overridden = FALSE;
+
+  /**
    * Stores the executable version of this view.
    *
    * @param Drupal\views\ViewExecutable $executable
@@ -192,6 +199,54 @@ class ViewStorage extends ConfigEntityBase implements ViewStorageInterface {
   }
 
   /**
+   * Returns whether the view configuration is overridden.
+   *
+   * @return bool
+   *   TRUE if there are changes between the active and staging storage, FALSE
+   *   otherwise.
+   */
+  public function isOverridden() {
+    return $this->overridden;
+  }
+
+  /**
+   * Sets the overridden status of a view.
+   *
+   * @param bool $status
+   *   The overridden status to set, defaults to TRUE.
+   */
+  public function setOverridden($status = TRUE) {
+    $this->overridden = (bool) $status;
+  }
+
+  /**
+   * Gets the fully prefixed config name for this view.
+   *
+   * This is just a convenience function to return this name.
+   *
+   * @return string
+   *   The config name.
+   */
+  public function getConfigName() {
+    $info = $this->entityInfo();
+    return $info['config prefix'] . '.' . $this->id();
+  }
+
+  /**
+   * Reverts the current config changes.
+   */
+  public function revert() {
+    if ($this->isOverridden()) {
+      // The current config changes in the active store are reset to the values
+      // in the staging store.
+      $config_name = $this->getConfigName();
+      $active_storage = drupal_container()->get('config.storage');
+      $staging_storage = drupal_container()->get('config.storage.staging');
+      $active_storage->write($config_name, $staging_storage->read($config_name));
+    }
+  }
+
+  /**
    * Returns the name of the module implementing this view.
    */
   public function getModule() {
diff --git a/lib/Drupal/views/ViewStorageController.php b/lib/Drupal/views/ViewStorageController.php
index 744157c..a313b5b 100644
--- a/lib/Drupal/views/ViewStorageController.php
+++ b/lib/Drupal/views/ViewStorageController.php
@@ -42,7 +42,17 @@ class ViewStorageController extends ConfigStorageController {
    * Overrides Drupal\config\ConfigStorageController::attachLoad();
    */
   protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
+    // Get config changes.
+    $source_storage = drupal_container()->get('config.storage');
+    $target_storage = drupal_container()->get('config.storage.staging');
+    $config_changes = config_sync_get_changes($source_storage, $target_storage);
+    $changes = !empty($config_changes['change']) ? $config_changes['change'] : array();
+
     foreach ($queried_entities as $id => $entity) {
+      // Set as overridden if config has picked up changes for this view.
+      if (in_array($entity->getConfigName(), $changes)) {
+        $entity->setOverridden();
+      }
       // Create a uuid if we don't have one.
       if (empty($entity->{$this->uuidKey})) {
         // Only get an instance of uuid once.
