diff --git versioncontrol_git.log.inc versioncontrol_git.log.inc
index 46a90dd..4171d66 100644
--- versioncontrol_git.log.inc
+++ versioncontrol_git.log.inc
@@ -36,8 +36,180 @@ function _versioncontrol_git_log_update_repository(VersioncontrolGitRepository &
   $repository->locked = 1;
   $repository->update();
 
-  // 1. Process branches
 
+  // Is this a fresh import?
+  $commits_in_db = $repository->loadCommits(array(), array(), array('may cache' => FALSE));
+  if (empty($commits_in_db)) {
+    $file_names = _version_control_fast_export();
+
+    $marks = _versioncontrol_git_log_process_marks($file_names[2]);
+    $logs = _versioncontrol_git_log_process_logfile($file_names[1], $marks);
+
+    //db_query('LOCK TABLES {versioncontrol_operations} WRITE');
+    $values = '';
+    $start = db_result(db_query('SELECT MAX(vc_op_id) FROM {versioncontrol_operations}'));
+    if (!is_numeric($start)) {
+      $start = 0;
+    }
+    foreach ($logs as $log) {
+      $start += 1;
+      $type = 1;
+      $repo_id = $repository->repo_id;
+      $date = $log->date;
+      $author = db_escape_string($log->author);
+      $author_uid = 0;
+      $committer = db_escape_string($log->committer);
+      $committer_uid = 0;
+      $revision = $log->revision;
+      $message = db_escape_string($log->msg);
+      $log->vc_op_id = $start;
+      if (empty($values)) {
+        $values = "(NULL, $type, $repo_id, $date, '$author', $author_uid, '$committer', $committer_uid, '$revision', '$message')";
+      }
+      else {
+        $values .= ", (NULL, $type, $repo_id, $date, '$author', $author_uid, '$committer', $committer_uid, '$revision', '$message')";
+      }
+    }
+    if ($values) {
+      $r = db_query("INSERT INTO {versioncontrol_operations} VALUES ". $values);
+    }
+    //db_query('UNLOCK TABLES');
+
+    //db_query('LOCK TABLES {versioncontrol_item_revisions} WRITE');
+    $values = '';
+    $start = db_result(db_query('SELECT MAX(item_revision_id) FROM {versioncontrol_item_revisions}'));
+    if (!is_numeric($start)) {
+      $start = 0;
+    }
+    $type = 1; // This is...
+//define('VERSIONCONTROL_ITEM_FILE',              1);
+//define('VERSIONCONTROL_ITEM_DIRECTORY',         2);
+//define('VERSIONCONTROL_ITEM_FILE_DELETED',      3);
+//define('VERSIONCONTROL_ITEM_DIRECTORY_DELETED', 4);
+    $source_id = 0; // Ask Sam.
+    // Revision ID of parent item.
+    $lines_added = 0; //Get these with a git log --numlines ?
+    $lines_removed = 0;
+    foreach ($logs as $log) {
+      foreach($log->files as $hash => $file) {
+        $start += 1;
+        $log->files[$hash]['rev_id'] = $start;
+        $log->name_block->updateAncestor($log->revision, $file['name'], $start);
+        $path = db_escape_string($file['name']);
+        $source_id = $log->name_block->getAncestor( $file['name'], $log->revision);
+        $action = $file['type'];
+        if (empty($values)) {
+          $values = "(NULL, $log->vc_op_id, $repo_id, '$path', '$log->revision', $type, $source_id, $action, $lines_added, $lines_removed)";
+        }
+        else {
+          $values .= ", (NULL, $log->vc_op_id, $repo_id, '$path', '$log->revision', $type, $source_id, $action, $lines_added, $lines_removed)";
+        }
+      }
+    }
+    if ($values) {
+      $r = db_query("INSERT INTO {versioncontrol_item_revisions} VALUES ". $values);
+    }
+    //db_query('UNLOCK TABLES');
+
+    //db_query('LOCK TABLES {versioncontrol_git_item_revisions} WRITE');
+    $values = '';
+    foreach ($logs as $log) {
+      foreach(array_keys($log->files) as $hash) {
+        $start = $log->files[$hash]['rev_id'];
+        if (empty($values)) {
+          $values = "($start, '$hash')";
+        }
+        else {
+          $values .= ", ($start, '$hash')";
+        }
+      }
+    }
+    if ($values) {
+      $r = db_query("INSERT INTO {versioncontrol_git_item_revisions} VALUES ". $values);
+    }
+    //db_query('UNLOCK TABLES');
+
+    //db_query('LOCK TABLES {versioncontrol_git_operations} WRITE');
+    $values = '';
+    $start = 0;
+    foreach ($logs as $log) {
+      $author = db_escape_string($log->author);
+      $committer = db_escape_string($log->committer);
+      $parent_commit = $log->from; //Should be 40 zeros for empty.
+      // I don't know how git-export-fast handles octo-merges.
+      $merge = $log->merge ? 1 : 0; // Where to we reference the actual merge commit? Extra rows?
+      if (empty($values)) {
+        $values = "($log->vc_op_id, '$author', '$committer', '$parent_commit', $merge)";
+      }
+      else {
+        $values .= ", ($log->vc_op_id, '$author', '$committer', '$parent_commit', $merge)";
+      }
+    }
+    if ($values) {
+      $r = db_query("INSERT INTO {versioncontrol_git_operations} VALUES ". $values);
+    }
+    //db_query('UNLOCK TABLES');
+
+    //db_query('LOCK TABLES {versioncontrol_labels} WRITE');
+    $values = '';
+    $start = db_result(db_query('SELECT MAX(label_id) FROM {versioncontrol_labels}'));
+    if (!is_numeric($start)) {
+      $start = 0;
+    }
+    $log = $logs[0];
+    $names = $log->name_block;
+    foreach (array_keys($names->names) as $name) {
+      $start += 1;
+      $name = db_escape_string($name);
+      // Just making this up surely we can get the data we need.
+      if (substr($name, strlen($name)-1 ,1) == 'x') {
+        $type = 2;
+      }
+      else {
+        $type = 3;
+      }
+      $data = db_escape_string('');
+      $names->names[$name] = $start;
+      if (empty($values)) {
+        $values = "(NULL, $repo_id, '$name', $type, '$data')";
+      }
+      else {
+        $values .= ", (NULL, $repo_id, '$name', $type, '$data')";
+      }
+    }
+    if ($values) {
+      $r = db_query("INSERT INTO {versioncontrol_labels} VALUES ". $values);
+    }
+    //db_query('UNLOCK TABLES');
+
+    //db_query('LOCK TABLES {versioncontrol_operation_labels} WRITE');
+    $values = '';
+    foreach ($logs as $log) {
+      $vc_op_id = $log->vc_op_id;
+      $label_id = $log->name_block->names[$log->commit];
+      $action = 2; // It had always two on the live db.
+      if (empty($values)) {
+        $values = "($vc_op_id, $label_id, $action)";
+      }
+      else {
+        $values .= ", ($vc_op_id, $label_id, $action)";
+      }
+    }
+    if ($values) {
+      $r = db_query("INSERT INTO {versioncontrol_operation_labels} VALUES ". $values);
+    }
+    //db_query('UNLOCK TABLES');
+
+
+
+    $repository->updated = time();
+    $repository->locked = 0;
+    $repository->update();
+
+    return TRUE;
+  }
+
+  // 1. Process branches
   // Fetch branches from the repo and load them from the db.
   $branches_in_repo = $repository->fetchBranches();
   $branches_in_db = $repository->loadBranches(array(), array(), array('may cache' => FALSE));
@@ -46,11 +218,9 @@ function _versioncontrol_git_log_update_repository(VersioncontrolGitRepository &
     $branches_in_db_by_name[$branch->name] = $branch;
   }
   unset($branches_in_db);
-
   // Determine whether we've got branch changes to make.
   $branches_new = array_diff_key($branches_in_repo, $branches_in_db_by_name);
   $branches_deleted = array_diff_key($branches_in_db_by_name, $branches_in_repo);
-
   // Insert new branches in the repository. Later all commits in these new
   // branches will be updated.
   // Unfortunately we can't say anything about the branch author at this time.
@@ -67,14 +237,11 @@ function _versioncontrol_git_log_update_repository(VersioncontrolGitRepository &
   foreach ($branches_in_db as $branch) {
     $branches_in_db_by_name[$branch->name] = $branch;
   }
-
   // Deleted branches are removed, commits in them are not!
   foreach($branches_deleted as $branch) {
     $branch->delete();
   }
-
   // 2. Process commits
-
   // Fetch commits from the repo and load them from the db.
   $commits_in_repo_hashes = $repository->fetchCommits();
   $commits_in_db = $repository->loadCommits(array(), array(), array('may cache' => FALSE));
@@ -84,16 +251,13 @@ function _versioncontrol_git_log_update_repository(VersioncontrolGitRepository &
   }
   unset($commits_in_db);
   $commits_new = array_diff($commits_in_repo_hashes, $commits_in_db_hashes);
-
   // Insert new commits in the database.
   foreach ($commits_new as $hash) {
     $command = "show --numstat --summary --pretty=format:\"%H%n%P%n%an%n%ae%n%cn%n%ce%n%ct%n%s%n%b%nENDOFOUTPUTGITMESSAGEHERE\" " . escapeshellarg($hash);
     $output = _versioncontrol_git_log_exec($command);
     _versioncontrol_git_log_parse_and_insert_commit($repository, $output, $branches_in_db_by_name);
   }
-
   // 3. Process tags
-
   // Insert new tags in the database.
   $tags_in_repo = $repository->fetchTags();
   $tags_in_db = $repository->loadTags();
@@ -108,9 +272,7 @@ function _versioncontrol_git_log_update_repository(VersioncontrolGitRepository &
   if (!empty($tags_new)) {
     _versioncontrol_git_log_process_tags($repository, $tags_new);
   }
-
   // 4. Process both tags abd branches for relations with commits
-
   $labels_new = array();
   foreach ($branches_new as $label) {
     $labels_new[] = $label;
@@ -125,16 +287,27 @@ function _versioncontrol_git_log_update_repository(VersioncontrolGitRepository &
       $commit->labels[$label_new->name] = $label_new;
     }
   }
-
   // Update repository updated field. Displayed on administration interface for documentation purposes.
   $repository->updated = time();
   $repository->locked = 0;
   $repository->update();
   return TRUE;
 }
-
 /// All general functions
-
+function _version_control_fast_export() {
+  $git_bin = variable_get('versioncontrol_git_binary_path', 'git');
+  if ($errors = _versioncontrol_git_binary_check_path($git_bin)) {
+    watchdog('versioncontrol_git', '!errors', array('!errors' => implode('<br />', $errors)), WATCHDOG_ERROR);
+    return array();
+  }
+  $tmp_mark = tempnam(file_directory_temp(), 'vclpm');
+  $tmp_log = tempnam(file_directory_temp(), 'vclpl');
+  $cmd = "fast-export --no-data --export-marks=$tmp_mark --all";
+  exec(escapeshellcmd("$git_bin $cmd") ." > $tmp_log", $logs);
+  //array_unshift($logs, ''); // FIXME doing it this way is just wrong.
+  //reset($logs); // Reset the array pointer, so that we can use next().
+  return array($logs, $tmp_log, $tmp_mark);
+}
 /**
  * Execute a Git command using the root context and the command to be executed.
  * @param string $command Command to execute.
@@ -152,7 +325,6 @@ function _versioncontrol_git_log_exec($command) {
   reset($logs); // Reset the array pointer, so that we can use next().
   return $logs;
 }
-
 /// All commit related function
 
 /**
@@ -549,3 +721,192 @@ function _versioncontrol_git_log_process_tags($repository, $tags_new) {
     $tag->insert();
   }
 }
+
+function _versioncontrol_git_log_process_marks($mark_file) {
+  $lines = file($mark_file);
+  $marks = array();
+  foreach ($lines as $line) {
+    $e = explode(' ', $line);
+    $marks[intval(ltrim($e[0], ':'))] = trim($e[1]);
+  }
+  unlink($mark_file);
+  return $marks;
+}
+
+function _versioncontrol_git_log_process_logfile($log_file, &$marks) {
+  $lines = file($log_file);
+  $name_block = new nameBlock();
+  $log = array();
+  $debt = 0;
+  foreach ($lines as $line) {
+    $mark = array();
+    if (empty($line)) {
+      continue;
+    }
+    if ($debt > 0) {
+      if (strlen($line) == $debt) {
+        // Keep adding to the commit message until we have all the promised characters.
+        $working->addMsg($line);
+        $debt = 0;
+      }
+      elseif (preg_match('/from :(\d+)$/', $line, $mark)) {
+          $working->from = $marks[$mark[1]];
+          $working->addMsg(substr($line, 0, strpos($line, 'from :')));
+          $debt = 0;
+      }
+      elseif (preg_match('/merge :(\d+)$/', $line, $mark)) {
+          $working->merge = $marks[$mark[1]];
+          $working->addMsg(substr($line, 0, strpos($line, 'merge :')));
+          $debt = 0;
+      }
+      else {
+        $debt -= $working->addMsg($line);
+      }
+      continue;
+    }
+    if (preg_match('/^commit\b/', $line)) {
+      if ($working) {
+        $log[] = $working;
+      }
+      $working = new logBlock();
+      $working->name_block = $name_block;
+      $working->setCommit($line);
+      continue;
+    }
+    if (preg_match('/^mark :(\d+)$/', $line, $mark)) {
+      $working->revision = $marks[$mark[1]];
+      continue;
+    }
+   if (preg_match('/^author[^<]*<([^>]+)> (\d+)/', $line, $mark)) {
+      $working->author = $mark[1];
+      $working->date = $mark[2];
+      continue;
+    }
+   if (preg_match('/^committer[^<]*<([^>]+)> (\d+)/', $line, $mark)) {
+      $working->committer = $mark[1];
+      continue;
+    }
+    if (preg_match('/^data (\d+)$/', $line, $mark)) {
+      $debt = $mark[1];
+      continue;
+    }
+    if (preg_match('/^from :(\d+)$/', $line, $mark)) {
+      $working->from = $marks[$mark[1]];
+      $debt = 0;
+      continue;
+    }
+    if (preg_match('/^merge :(\d+)$/', $line, $mark)) {
+      $working->merge = $marks[$mark[1]];
+      $debt = 0;
+      continue;
+    }
+    if (preg_match('/(.) (\d+) ([a-f,0-9]{40}) (.+)$/', $line, $mark)) {
+      $working->addFile($mark[1], $mark[2], $mark[3], $mark[4]);
+    }
+  }
+  $log[] = $working;
+  unlink($log_file);
+
+  return $log;
+}
+
+class logBlock {
+  public $files = array();
+  public $commit = '';
+  public $revision = '';
+  public $date = 0;
+  public $author = '';
+  public $committer = '';
+  public $msg = '';
+  public $from = '';
+  public $vc_op_id;
+  public $name_block;
+  public $merge;
+
+  function addMsg($line) {
+    $this->msg .= $line;
+    return strlen($line);
+  }
+
+  function setCommit($commit) {
+    $parts = explode(' ', $commit);
+    $ref = trim($parts[1]);
+    $path = explode('/', $ref);
+    $this->commit = array_pop($path);
+    $this->name_block->add($this->commit);
+  }
+
+  function addfile($type, $mode, $hash, $name) {
+    $name = '/'. $name; // Remove this later.
+    switch ($type) {
+      case 'M':
+        $type = VERSIONCONTROL_ACTION_MODIFIED;
+        break;
+      case 'A':
+        $type = VERSIONCONTROL_ACTION_ADDED;
+        break;
+      case 'D':
+        $type = VERSIONCONTROL_ACTION_DELETED;
+        break;
+      case 'R':
+        $type = VERSIONCONTROL_ACTION_MOVED;
+        break;
+      case 'C':
+        $type = VERSIONCONTROL_ACTION_COPIED;
+        break;
+      case '?':
+        $type = VERSIONCONTROL_ACTION_MERGED;
+        break;
+      case '?':
+        $type = VERSIONCONTROL_ACTION_REPLACED;
+        break;
+      default:
+        $type = VERSIONCONTROL_ACTION_OTHER;
+    }
+    $this->files[$hash] = array('name' => $name, 'type' => $type, 'mode' => $mode);
+    $this->name_block->addAncestor($name, $this->revision);
+  }
+
+
+}
+
+class nameBlock {
+  public $names = array();
+  public $ancestor = array();
+  public $history = array();
+
+  function add($name) {
+    if (!array_key_exists($name, $this->names)) {
+      $this->names[$name] = array();
+    }
+  }
+
+  function addAncestor($name, $hash) {
+    if (array_key_exists($name, $this->ancestor)) {
+      if (array_key_exists($hash, $this->ancestor[$name])) {
+        return;
+      }
+      $last = end(array_keys($this->ancestor[$name]));
+    }
+    else {
+      $this->ancestor[$name][$hash] = 0;
+      return;
+    }
+    $this->ancestor[$name][$hash] = $last;
+  }
+
+  function updateAncestor($hash, $name, $id) {
+    $this->history[$name][$hash] = $id;
+  }
+
+  function getAncestor($name, $rev) {
+    if (array_key_exists($name, $this->history)) {
+      $last_rev = $this->ancestor[$name][$rev];
+      if ($last_rev && array_key_exists($last_rev, $this->history[$name])) {
+        return $this->history[$name][$last_rev];
+      }
+    }
+    return 0;
+  }
+
+}
