diff --git a/multifield.info b/multifield.info
index 4e50a68..f8d3a8d 100644
--- a/multifield.info
+++ b/multifield.info
@@ -6,6 +6,7 @@ dependencies[] = ctools
 dependencies[] = field
 configure = admin/structure/multifield
 files[] = MultifieldEntityController.php
+files[] = multifield.migrate.inc
 files[] = tests/MultifieldAdministrationTestCase.test
 files[] = tests/MultifieldDevelGenerateTestCase.test
 files[] = tests/MultifieldEntityTranslationTestCase.test
diff --git a/multifield.migrate.inc b/multifield.migrate.inc
new file mode 100644
index 0000000..7f9d960
--- /dev/null
+++ b/multifield.migrate.inc
@@ -0,0 +1,162 @@
+<?php
+
+/**
+ * @file
+ * Migrate integration for the Multifield module.
+ *
+ * Contains the MultifieldMigrateFieldHandler class.
+ *
+ * Requires Migrate 2.4 or later. To migrate into fields inside of a multifield,
+ * use the field name as the subfield:
+ *
+ * @code
+ * $this->addFieldMapping('field_my_multifield:field_label', 'label');
+ * $this->addFieldMapping('field_my_multifield:field_slug', 'slug');
+ * $this->addFieldMapping('field_my_multifield:field_description', 'description');
+ * @endcode
+ *
+ * Within each subfield, you can use the field type's usual subfields, just like
+ * you would if the field were not nested inside a multifield. For example, to
+ * set the summary and text format on a long text field:
+ *
+ * @code
+ * $this->addFieldMapping('field_my_multifield:field_description', 'description');
+ * $this->addFieldMapping('field_my_multifield:field_description:summary', 'short_description');
+ * $this->addFieldMapping('field_my_multifield:field_description:format')
+ *   ->defaultValue('plain_text');
+ * @endcode
+ *
+ */
+
+/**
+ * Implements hook_migrate_api().
+ */
+function multifield_migrate_api() {
+  return array(
+    'api' => 2,
+    'field handlers' => array('MultifieldMigrateFieldHandler'),
+  );
+}
+
+/**
+ * Migrate field handler class for multifield fields.
+ */
+class MultifieldMigrateFieldHandler extends MigrateFieldHandler {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct() {
+    // Register this as the handler for all multifield types.
+    $field_types = module_invoke('multifield', 'field_info');
+    $this->registerTypes(array_keys($field_types));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields($type, $instance, $migration = NULL) {
+    // Display the field label and name for each field in a multifield.
+    $handler = new MigrateFieldsEntityHandler();
+    $field = field_info_field($instance['field_name']);
+    $machine_name = multifield_extract_multifield_machine_name($field);
+    return $handler->fields('multifield', $machine_name, $migration);
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Each set of subfield values will be in its own array; each of these arrays
+   * should be the same length:
+   *
+   * @code
+   * $arguments = array(
+   *   'field_label' => array('value 1', 'value 2', 'value 3'),
+   *   'field_slug' => array('value_1', 'value_2', 'value_3'),
+   *   'field_description' => array('first description', '', 'third description'),
+   * );
+   * @endcode
+   *
+   * These need to be collated into three multifield arrays:
+   *
+   * @code
+   * $multifield_values = array(
+   *   0 => array(
+   *     'field_label' => 'value 1',
+   *     'field_slug' => 'value_1',
+   *     'field_description' => 'first description',
+   *   ),
+   *   1 => array(
+   *     'field_label' => 'value 2',
+   *     'field_slug' => 'value_2',
+   *     'field_description' => '',
+   *   ),
+   *   2 => array(
+   *     'field_label' => 'value 3',
+   *     'field_slug' => 'value_3',
+   *     'field_description' => 'third description',
+   *   ),
+   * );
+   * @endcode
+   *
+   * Then, each set of multifield values can be migrated in using the
+   * appropriate field handlers.
+   *
+   */
+  public function prepare($entity, array $field_info, array $instance, array $values) {
+    // Get the subfield arguments.
+    $arguments = $entity->{$field_info['field_name']}['arguments'];
+
+    // Collate the subfield values.
+    $items = array();
+    // Step through by field.
+    foreach ($arguments as $field_name => $field_values) {
+      // Normalize values to arrays.
+      if (!is_array($field_values)) {
+        $field_values = array($field_values);
+      }
+
+      // Add each field value to a separate multifield.
+      foreach ($field_values as $delta => $value) {
+        if (!isset($items[$delta])) {
+          $items[$delta] = array();
+        }
+
+        $items[$delta][$field_name] = array($value);
+      }
+    }
+
+    // Remove multifield values that are completely empty.
+    foreach ($items as $delta => $value) {
+      $is_empty = TRUE;
+
+      foreach ($value as $field_name => $v) {
+        if (reset($v) !== NULL) {
+          $is_empty = FALSE;
+        }
+      }
+
+      if ($is_empty) {
+        unset($items[$delta]);
+      }
+    }
+
+    // Migrate each set of subfields.
+    // @see MigrateFieldsEntityHandler::prepare()
+    $language = $this->getFieldLanguage($entity, $field_info, $arguments);
+    $machine_name = multifield_extract_multifield_machine_name($field_info);
+    $subinstances = field_info_instances('multifield', $machine_name);
+    foreach ($items as $delta => $item) {
+      $pseudo_entity = _multifield_field_item_to_entity($machine_name, $item);
+      foreach ($subinstances as $subfield_name => $subinstance) {
+        if (property_exists($pseudo_entity, $subfield_name)) {
+          $subfield = field_info_field($subfield_name);
+          $pseudo_entity->$subfield_name = migrate_field_handler_invoke_all($pseudo_entity, $subfield, $subinstance, $pseudo_entity->$subfield_name);
+        }
+      }
+      $return[$language][$delta] = _multifield_field_entity_to_item($pseudo_entity);
+    }
+
+    return !empty($return) ? $return : NULL;
+  }
+}
