diff --git a/features.admin.inc b/features.admin.inc
index 4e12576..48235e5 100644
--- a/features.admin.inc
+++ b/features.admin.inc
@@ -1095,8 +1095,13 @@ function features_admin_form($form, $form_state) {
       );
 
       // Add in recreate link
+      $markup = l(t('Recreate'), "admin/structure/features/{$name}/recreate", array('attributes' => array('class' => array('admin-update'))));
+      if (features_get_module_status($name) == FEATURES_MODULE_ENABLED) {
+        // If module is not disabled, add in consolidate link
+        $markup .= '&nbsp;' . l(t('Consolidate'), "admin/structure/features/{$name}/consolidate", array('attributes' => array('class' => array('admin-update'))));
+      }
       $form[$package]['actions'][$name] = array(
-        '#markup' => l(t('Recreate'), "admin/structure/features/{$name}/recreate", array('attributes' => array('class' => array('admin-update')))),
+        '#markup' => $markup,
       );
     }
   }
@@ -1228,7 +1233,11 @@ function features_admin_components_revert(&$form, &$form_state) {
   features_include();
   $module = $form_state['values']['module'];
   $revert = array($module => array());
-  foreach (array_filter($form_state['values']['revert']) as $component => $status) {
+  $components = array_filter($form_state['values']['revert']);
+  if ($components == array()) {
+    $components = $form_state['values']['revert'];
+  }
+  foreach ($components as $component => $status) {
     $revert[$module][] = $component;
     drupal_set_message(t('Reverted all <strong>@component</strong> components for <strong>@module</strong>.', array('@component' => $component, '@module' => $module)));
   }
@@ -1319,6 +1328,22 @@ function features_cleanup_form($form, $form_state, $cache_clear = FALSE) {
 }
 
 /**
+ * Page callback to consolidate a feature back into the database.
+ *
+ * @param $feature
+ *   The loaded feature object to be consolidated.
+ */
+function features_feature_consolidate($feature) {
+  $destination = $_SERVER['HTTP_REFERER'];
+  features_include();
+  $module = $feature->name;
+  foreach ($feature->info['features'] as $component => $items) {
+    features_invoke($component, 'features_consolidate', $items, $module);
+  }
+  drupal_goto($destination);
+}
+
+/**
  * Page callback to display the differences between what's in code and
  * what is in the db.
  *
diff --git a/features.api.php b/features.api.php
index 10915e1..81f0c5f 100644
--- a/features.api.php
+++ b/features.api.php
@@ -239,6 +239,18 @@ function hook_features_export_alter(&$export, $module_name) {
 }
 
 /**
+ * TODO
+ */
+function hook_features_consolidate($data, &$export, $module_name) {
+  // The following is the simplest implementation of a straight object export
+  // with no further export processors called.
+  foreach ($data as $component) {
+    $export['mycomponent'][$component] = $component;
+  }
+  return array();
+}
+
+/**
  * Alter the pipe array for a given component. This hook should be implemented
  * with the name of the component type in place of `component` in the function
  * name, e.g. `features_pipe_views_alter()` will alter the pipe for the Views
diff --git a/features.drush.inc b/features.drush.inc
index 9da547d..af69994 100644
--- a/features.drush.inc
+++ b/features.drush.inc
@@ -75,6 +75,19 @@ function features_drush_command() {
     ),
     'aliases' => array('fc'),
   );
+  $items['features-consolidate'] = array(
+    'description' => "Consolidate a feature to the database.",
+    'drupal dependencies' => array('features'),
+    'aliases' => array('fco'),
+  );
+  $items['features-consolidate-all'] = array(
+    'description' => "Consolidate all features to the database.",
+    'drupal dependencies' => array('features'),
+    'options' => array(
+      'exclude' => "A comma-separated list of features to exclude from consolidate.",
+    ),
+    'aliases' => array('fco-all', 'fcoa'),
+  );
   $items['features-update'] = array(
     'description' => "Update a feature module on your site.",
     'arguments' => array(
@@ -166,6 +179,10 @@ Patterns uses * or % for matching multiple sources/components. Unlike shorthands
 
 Lastly, a pattern without a colon is interpreted as having \":%\" appended, for easy listing of all components of a source.
 ");
+    case 'drush:features-consolidate':
+      return dt("Consolidate a feature to the database.");
+    case 'drush:features-consolidate-all':
+      return dt("Consolidate all features to the database.");
     case 'drush:features-update':
       return dt("Update a feature module on your site. The option '--version-set=foo' may be used to specify a version number for the feature or the option '--version-increment' may also to increment the feature's version number.");
     case 'drush:features-update-all':
@@ -499,6 +516,58 @@ function drush_features_add() {
 
 
 /**
+ * Consolidate a feature to the database.
+ */
+function drush_features_consolidate() {
+  if ($args = func_get_args()) {
+    foreach ($args as $module) {
+      if (($feature = feature_load($module, TRUE)) && module_exists($module)) {
+        drush_log(dt("Consolidating features for module !module", array('!module' => $module)), 'notice');
+        _drush_features_consolidate($feature->info['features'], $module);
+      }
+      elseif ($feature) {
+        _features_drush_set_error($module, 'FEATURES_FEATURE_NOT_ENABLED');
+      }
+      else {
+        _features_drush_set_error($module);
+      }
+    }
+  }
+  else {
+    // By default just show contexts that are available.
+    $rows = array(array(dt('Available features')));
+    foreach (features_get_features(NULL, TRUE) as $name => $info) {
+      $rows[] = array($name);
+    }
+    drush_print_table($rows, TRUE);
+  }
+}
+
+/**
+ * Consolidate all features to the database.
+ */
+function drush_features_consolidate_all() {
+  $features_to_consolidate = array();
+  $features_to_exclude = _convert_csv_to_array(drush_get_option('exclude'));
+
+  $features = features_get_features();
+  foreach ($features as $module) {
+    if ($module->status && !in_array($module->name, $features_to_exclude)) {
+      $features_to_consolidate[] = $module->name;
+    }
+  }
+  drush_print(dt('The following modules will be consolidated: !modules', array('!modules' => implode(', ', $features_to_consolidate))));
+  if (drush_confirm(dt('Do you really want to continue?'))) {
+    foreach ($features_to_consolidate as $module_name) {
+      drush_invoke_process('@self', 'features-consolidate', array($module_name));
+    }
+  }
+  else {
+    return drush_user_abort();
+  }
+}
+
+/**
  * Update an existing feature module.
  */
 function drush_features_update() {
@@ -654,6 +723,17 @@ function _drush_features_generate_export(&$info, &$module_name) {
 }
 
 /**
+ * Consolidate a feature to the database.
+ */
+function _drush_features_consolidate($features = array(), $module_name = '') {
+  features_include();
+  foreach ($features as $component => $items) {
+    drush_log(dt("Running consolidate for component !component", array('!component' => $component)), 'notice');
+    features_invoke($component, 'features_consolidate', $items, $module_name);
+  }
+}
+
+/**
  * Revert a feature to it's code definition.
  * Optionally accept a list of components to revert.
  */
diff --git a/features.module b/features.module
index ba5b9fe..a591ad5 100644
--- a/features.module
+++ b/features.module
@@ -154,6 +154,18 @@ function features_menu() {
     'file' => "features.admin.inc",
     'weight' => 11,
   );
+  $items['admin/structure/features/%feature/consolidate'] = array(
+    'title' => 'Consolidate',
+    'description' => 'Consolidate a feature to the database.',
+    'page callback' => 'features_feature_consolidate',
+    'page arguments' => array(3),
+    'load arguments' => array(3, TRUE),
+    'access callback' => 'features_access_consolidate_feature',
+    'access arguments' => array(3),
+    'type' => MENU_LOCAL_TASK,
+    'file' => "features.admin.inc",
+    'weight' => 12,
+  );
   if (module_exists('diff')) {
     $items['admin/structure/features/%feature/diff'] = array(
       'title' => 'Review overrides',
@@ -876,6 +888,14 @@ function features_access_override_actions($feature) {
 }
 
 /**
+ * Menu access callback for whether a user should be able to
+ * consolidate a given feature.
+ */
+function features_access_consolidate_feature($feature) {
+  return (user_access('administer features') && (features_get_module_status($feature->name) == FEATURES_MODULE_ENABLED));
+}
+
+/**
  * Implements hook_form_alter() for system_modules form().
  */
 function features_form_system_modules_alter(&$form) {
diff --git a/includes/features.context.inc b/includes/features.context.inc
index 2da59a7..dd6b937 100644
--- a/includes/features.context.inc
+++ b/includes/features.context.inc
@@ -52,3 +52,15 @@ function context_features_revert($module = NULL) {
   context_invalidate_cache();
   return $return;
 }
+
+
+/**
+ * Implementation of hook_features_consolidate().
+ */
+function context_features_consolidate($items = array(), $module_name = '') {
+  foreach ($items as $context_name) {
+    if ($context = context_load($context_name)) {
+      context_save($context);
+    }
+  }
+}
diff --git a/includes/features.image.inc b/includes/features.image.inc
index 2b5eb27..d92197e 100644
--- a/includes/features.image.inc
+++ b/includes/features.image.inc
@@ -99,3 +99,36 @@ function _image_features_style_sanitize(&$style, $child = FALSE) {
     }
   }
 }
+
+/**
+ * Implementation of hook_features_consolidate().
+ */
+function image_features_consolidate($items = array(), $module_name = '') {
+  foreach ($items as $style_name) {
+    $style = image_style_load($style_name);
+    // Styles
+    if (isset($style['isid'])) {
+      if (!is_numeric($style['isid'])) {
+        _image_style_and_effects_save($style);
+      }
+    }
+    else {
+      _image_style_and_effects_save($style);
+    }
+  }
+}
+
+/**
+ * Helper function for image_features_consolidate().
+ * Saves a single style together with its effects.
+ */
+function _image_style_and_effects_save($style) {
+  $style = image_style_save($style);
+  // Actions
+  if (is_numeric($style['isid'])) {
+    foreach ($style['effects'] as $effect)  {
+      $effect['isid'] = $style['isid'];
+      image_effect_save($effect);
+    }
+  }
+}
diff --git a/includes/features.node.inc b/includes/features.node.inc
index 7beb55f..f9df80c 100644
--- a/includes/features.node.inc
+++ b/includes/features.node.inc
@@ -115,7 +115,7 @@ function node_features_revert($module = NULL) {
 }
 
 /**
- * Implements hook_features_disable().
+ * Implements hook_features_disable_feature().
  *
  * When a features module is disabled, modify any node types it provides so
  * they can be deleted manually through the content types UI.
@@ -123,7 +123,7 @@ function node_features_revert($module = NULL) {
  * @param $module
  *   Name of module that has been disabled.
  */
-function node_features_disable($module) {
+function node_features_disable_feature($module) {
   if ($default_types = features_get_default('node', $module)) {
     foreach ($default_types as $type_name => $type_info) {
       $type_info = node_type_load($type_name);
@@ -137,7 +137,7 @@ function node_features_disable($module) {
 }
 
 /**
- * Implements hook_features_enable().
+ * Implements hook_features_enable_feature().
  *
  * When a features module is enabled, modify any node types it provides so
  * they can no longer be deleted manually through the content types UI.
@@ -145,7 +145,7 @@ function node_features_disable($module) {
  * @param $module
  *   Name of module that has been enabled.
  */
-function node_features_enable($module) {
+function node_features_enable_feature($module) {
   if ($default_types = features_get_default('node', $module)) {
     foreach ($default_types as $type_name => $type_info) {
       // Ensure the type exists.
@@ -159,3 +159,28 @@ function node_features_enable($module) {
     }
   }
 }
+
+/**
+ * Implementation of hook_features_consolidate().
+ *
+ * When a features module is consolidated, modify any node types it provides
+ * so responsibility is delegated to the node module.
+ *
+ * @param $items
+ *   Array of names of node types to be consolidated.
+ * @param $module
+ *   Name of module that has been consolidated.
+ */
+function node_features_consolidate($items = array(), $module = 'feature') {
+  module_load_include('inc', 'features', 'features.export');
+  // Delegate responsibility to node module
+  foreach ($items as $type_name) {
+    // Load the type.
+    $type_info = node_type_load($type_name);
+    $type_info->module = 'node';
+    $type_info->custom = 1;
+    $type_info->modified = 1;
+    $type_info->locked = 0;
+    node_type_save($type_info);
+  }
+}
diff --git a/includes/features.views.inc b/includes/features.views.inc
new file mode 100644
index 0000000..231c950
--- /dev/null
+++ b/includes/features.views.inc
@@ -0,0 +1,277 @@
+<?php
+
+/**
+ * Implementation of hook_features_export().
+ */
+function views_api_features_export($data, &$export, $module_name = '') {
+  // Add views dependency
+  $export['dependencies']['views'] = 'views';
+
+  // Add the actual views API hook entries to be accounted for in
+  // hook_views_api(). The components are actually identified by a delimited
+  // list of values: `key:value`. Currently only the 'api' key is supported
+  // as Features does not yet know how to write to subdirectories.
+  foreach ($data as $component) {
+    if (is_numeric($component)) {
+      $version = "api:{$component}";
+      $export['features']['views_api'][$version] = $version;
+    }
+  }
+
+  return array();
+}
+
+/**
+ * Implementation of hook_features_export_render().
+ * Adds the views mothership hook, views_api().
+ */
+function views_api_features_export_render($module, $data) {
+  $values = array();
+  foreach ($data as $component) {
+    $split = explode(':', $component);
+    if (count($split) === 2) {
+      list($key, $value) = $split;
+      $values[$key] = $value;
+    }
+  }
+  $code = '  return ' . features_var_export($values, '  ') . ';';
+  return array('views_api' => $code);
+}
+
+/**
+ * Implementation of hook_features_api().
+ */
+function views_features_api() {
+  return array(
+    'views' => array(
+      'name' => t('Views'),
+      'feature_source' => TRUE,
+      'default_hook' => 'views_default_views',
+      'default_file' => FEATURES_DEFAULTS_CUSTOM,
+      'default_filename' => 'views_default',
+    ),
+    'views_api' => array(
+      'name' => t('Views API'),
+      'feature_source' => FALSE,
+      'duplicates' => FEATURES_DUPLICATES_ALLOWED,
+      // Views API integration does not include a default hook declaration as
+      // it is not a proper default hook.
+      // 'default_hook' => 'views_api',
+    )
+  );
+}
+
+/**
+ * Implementation of hook_features_export_options().
+ */
+function views_features_export_options() {
+  $enabled_views = array();
+  $views = views_get_all_views();
+  foreach ($views as $view) {
+    if (!isset($views[$view->name]->disabled) || !$views[$view->name]->disabled) {
+      $enabled_views[$view->name] = $view->name;
+    }
+  }
+  ksort($enabled_views);
+  return $enabled_views;
+}
+
+/**
+ * Implementation of hook_features_export_render().
+ */
+function views_features_export_render($module, $data) {
+  $code = array();
+  $code[] = '  $views = array();';
+  $code[] = '';
+
+  // Build views & add to export array
+  foreach ($data as $view_name) {
+    // Build the view
+    $view = views_get_view($view_name, TRUE);
+    if ($view) {
+      $code[] = '  // Exported view: '. $view_name;
+      $code[] = $view->export('  ');
+      $code[] = '  $views[$view->name] = $view;';
+      $code[] = '';
+    }
+  }
+  $code[] = '  return $views;';
+  $code = implode("\n", $code);
+  return array('views_default_views' => $code);
+}
+
+/**
+ * Implementation of hook_features_export().
+ */
+
+function views_features_export($data, &$export, $module_name = '') {
+  // Build views & add to export array
+  $map = features_get_default_map('views', 'name');
+  $views = array();
+  $conflicts = array();
+  foreach ($data as $view_name) {
+    if ($view = views_get_view($view_name, TRUE)) {
+      // This view is provided by another module. Add it as a dependency or
+      // display a conflict message if the View is overridden.
+      if (isset($map[$view_name]) && $map[$view_name] !== $module_name) {
+        if ($v = views_get_view($view_name)) {
+          if ($v->type === 'Overridden') {
+            $conflicts[$map[$view_name]] = $view_name;
+          }
+          elseif ($v->type === 'Default') {
+            $export['dependencies'][$map[$view_name]] = $map[$view_name];
+          }
+        }
+      }
+      // Otherwise just add to exports
+      else {
+        $export['features']['views'][$view_name] = $view_name;
+        $views[$view_name] = $view;
+      }
+    }
+  }
+  if (!empty($conflicts)) {
+    $message = 'The following overridden view(s) are provided by other modules: !views. To resolve this problem either revert each view or clone each view so that modified versions can be exported with your feature.';
+    $tokens = array('!views' => implode(', ', $conflicts));
+    features_log(t($message, $tokens), 'warning');
+  }
+
+  // Only add Views API hook if there are actually views to export.
+  if (!empty($export['features']['views'])) {
+    $export['features']['views_api']['api:'. views_api_version()] = 'api:'. views_api_version();
+    $export['dependencies']['views'] = 'views';
+  }
+
+  // Discover module dependencies
+  // We need to find dependencies based on:
+  // 1. handlers
+  // 2. plugins (style plugins, display plugins)
+  // 3. other... (e.g. imagecache display option for CCK imagefields) : (
+
+  // Handlers
+  $handlers = array('fields', 'filters', 'arguments', 'sort', 'relationships');
+  $handler_dependencies = views_handler_dependencies();
+
+  // Plugins
+  // For now we only support dependency detection for a subset of all views plugins
+  $plugins = array('display', 'style', 'row', 'access');
+  $plugin_dependencies = views_plugin_dependencies();
+
+  foreach ($views as $view) {
+    foreach ($view->display as $display) {
+      // Handlers
+      foreach ($handlers as $handler) {
+        if (isset($display->display_options[$handler])) {
+          foreach ($display->display_options[$handler] as $item) {
+            if ($item['table'] && isset($handler_dependencies[$item['table']])) {
+              $module = $handler_dependencies[$item['table']];
+              $export['dependencies'][$module] = $module;
+            }
+          }
+        }
+      }
+
+      // Plugins
+      foreach ($plugins as $plugin_type) {
+        $plugin_name = '';
+        switch ($plugin_type) {
+          case 'display':
+            if (isset($display->display_plugin)) {
+              $plugin_name = $display->display_plugin;
+            }
+            break;
+          case 'access':
+            if (isset($display->display_options['access'], $display->display_options['access']['type']) && $display->display_options['access']['type'] != 'none') {
+              $plugin_name = $display->display_options['access']['type'];
+            }
+            break;
+          default:
+            if (isset($display->display_options["{$plugin_type}_plugin"])) {
+            $plugin_name = $display->display_options["{$plugin_type}_plugin"];
+          }
+          break;
+        }
+        if (!empty($plugin_name) && isset($plugin_dependencies[$plugin_type][$plugin_name])) {
+          $module = $plugin_dependencies[$plugin_type][$plugin_name];
+          $export['dependencies'][$module] = $module;
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Provides an array that maps hook_views_data() tables to modules.
+ */
+function views_handler_dependencies() {
+  views_include_handlers();
+
+  static $map;
+  if (!isset($map)) {
+    $map = array();
+    foreach (module_implements('views_data') as $module) {
+      if ($tables = module_invoke($module, 'views_data')) {
+        foreach ($tables as $table => $info) {
+          if (isset($info['table']) && (!isset($map[$table]) || $info['table']['group'])) {
+            $map[$table] = $module;
+          }
+          else if (!isset($map[$table])) {
+            $map[$table] = $module;
+          }
+        }
+      }
+    }
+  }
+  return $map;
+}
+
+/**
+ * Provides an array that maps hook_views_plugins() to modules.
+ */
+function views_plugin_dependencies() {
+  views_include_handlers();
+
+  static $map;
+  if (!isset($map)) {
+    $map = array();
+    foreach (module_implements('views_plugins') as $module) {
+      $plugins = module_invoke($module, 'views_plugins');
+      if (!empty($plugins)) {
+        foreach ($plugins as $type => $items) {
+          if (is_array($items)) {
+            foreach (array_keys($items) as $plugin_name) {
+              $map[$type][$plugin_name] = $module;
+            }
+          }
+        }
+      }
+    }
+  }
+  return $map;
+}
+
+/**
+ * Implementation of hook_features_revert().
+ */
+function views_features_revert($module) {
+  if ($default_views = features_get_default('views', $module)) {
+    foreach ($default_views as $default_view) {
+      if ($current_view = views_get_view($default_view->name)) {
+        $current_view->delete(FALSE);
+      }
+    }
+    // Flush caches.
+    cache_clear_all();
+    menu_rebuild();
+  }
+}
+
+/**
+ * Implementation of hook_features_consolidate().
+ */
+function views_features_consolidate($items = array(), $module_name = '') {
+  foreach ($items as $view_name) {
+    $view = views_get_view($view_name);
+    $view->save();
+  }
+}
