diff --git a/versioncontrol_project.module b/versioncontrol_project.module
index 56036c9..aa77484 100644
--- a/versioncontrol_project.module
+++ b/versioncontrol_project.module
@@ -187,6 +187,21 @@ function versioncontrol_project_repository_load($project_id) {
 }
 
 /**
+ * Asks if a versioncontrol repository has a valid project associated.
+ *
+ * @return boolean
+ *   TRUE if the repository has a valid project associated, FALSE if not.
+ */
+function versioncontrol_project_repository_has_project(VersioncontrolRepository $repository) {
+  if (empty($repository->project_nid)) {
+    // No project associated.
+    return FALSE;
+  }
+  $node = node_load($repository->project_nid);
+  return project_node_is_project($node);
+}
+
+/**
  * Load the project object associated with a repo.
  */
 function versioncontrol_project_project_load($repo_id) {
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue.info b/versioncontrol_project_issue/versioncontrol_project_issue.info
new file mode 100644
index 0000000..aa965d5
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue.info
@@ -0,0 +1,6 @@
+name = "Version Control / Project issue integration"
+description = "Expose some functionality that integrates project_issue and Version Control API."
+package = Version Control
+dependencies[] = versioncontrol_project
+dependencies[] = project_issue
+core = 7.x
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue.install b/versioncontrol_project_issue/versioncontrol_project_issue.install
new file mode 100644
index 0000000..c519135
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue.install
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @file
+ * Version Control / Project issue integration
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function versioncontrol_project_issue_schema() {
+  $schema['versioncontrol_project_issue_operations'] = array(
+    'description' => 'This table associates project issue nodes with versioncontrol operations.',
+    'fields' => array(
+      'nid' => array(
+        'description' => 'Foreign key for the project issue nid.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'vc_op_id' => array(
+        'description' => 'Foreign key for the operation({versioncontrol_operations}.vc_op_id).',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'primary key' => array('nid', 'vc_op_id'),
+  );
+  return $schema;
+}
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue.module b/versioncontrol_project_issue/versioncontrol_project_issue.module
new file mode 100644
index 0000000..6b32fe7
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue.module
@@ -0,0 +1,132 @@
+<?php
+/**
+ * @file
+ * Version Control / Project issue integration.
+ */
+
+/**
+ * Implements hook_node_load().
+ */
+function versioncontrol_project_issue_node_load($nodes, $types) {
+  $issue_node_types = project_issue_issue_node_types();
+  $intersection = array_intersect($issue_node_types, $types);
+  if (empty($intersection)) {
+    // Nothing to do.
+    return;
+  }
+  $vc_op_ids_by_nid = versioncontrol_project_issue_get_issue_operation_ids(array_keys($nodes));
+  if (empty($vc_op_ids_by_nid)) {
+    // Nothing to load.
+    return;
+  }
+  foreach ($vc_op_ids_by_nid as $nid => $vc_op_ids) {
+    $repository = versioncontrol_project_repository_load($nodes[$nid]->field_project[LANGUAGE_NONE][0]['target_id']);
+    $nodes[$nid]->versioncontrol_project_issue['operations'] = $repository->loadCommits($vc_op_ids);
+  }
+}
+
+/**
+ * Implements hook_node_update().
+ *
+ * Change the mappings when a project issue is changed of project.
+ */
+function versioncontrol_project_issue_node_update($node) {
+  if (!project_issue_node_type_is_issue($node->type)) {
+    return;
+  }
+  $project_id = $node->field_project[LANGUAGE_NONE][0]['target_id'];
+  $original_project_id = $node->original->field_project[LANGUAGE_NONE][0]['target_id'];
+  if ($original_project_id == $project_id) {
+    // Nothing to do.
+    return;
+  }
+  // Project was changed, remove operation associations with the issue.
+  db_delete('versioncontrol_project_issue_operations')->condition('nid', $node->nid)->execute();
+  // @todo Search all operations associated with the new project? (if decided,
+  // use a queue, since it can be time consuming).
+}
+
+/**
+ * Implements hook_node_delete().
+ */
+function versioncontrol_project_issue_node_delete($node) {
+  if (!project_issue_node_is_issue($node)) {
+    // Nothing to do.
+    return;
+  }
+  // Remove mappings on delete.
+  db_delete('versioncontrol_project_issue_operations')->condition('nid', $node->nid)->execute();
+}
+
+/**
+ * Implements hook_versioncontrol_entity_commit_delete().
+ *
+ * Repository synchronization removes commits, event processor plugins are
+ * executed later, so we cannot react at that time. So we use this hook to
+ * remove relations from our table.
+ */
+function versioncontrol_project_issue_versioncontrol_entity_commit_delete(VersioncontrolOperation $operation) {
+  db_delete('versioncontrol_project_issue_operations')->condition('vc_op_id', $operation->vc_op_id)->execute();
+}
+
+/**
+ * Implements hook_versioncontrol_repository_bypassing_purge().
+ *
+ * @todo db_delete seems to not support joins, is that possible to use for the
+ * generic case? i.e. no mysql(should be more efficient, in case a lot of
+ * issues are associated).
+ */
+function versioncontrol_project_issue_versioncontrol_repository_bypassing_purge(VersioncontrolRepository $repository) {
+  versioncontrol_project_issue_delete_issue_operation_maps($repository);
+}
+
+/**
+ * Deletes all relared issue/operation associations.
+ *
+ * @param int|VersioncontrolRepository $repository
+ *   Repository object or its repo_id.
+ */
+function versioncontrol_project_issue_delete_issue_operation_maps($repository) {
+  if (!$repository instanceof VersioncontrolRepository) {
+    // Should be a repo_id.
+    $repository = versioncontrol_repository_load($repository);
+  }
+  if (empty($repository->project_nid)) {
+    // No project associated.
+    return;
+  }
+  // Load all associated project issue nids.
+  $query = new EntityFieldQuery();
+  $query->entityCondition('entity_type', 'node')
+    ->entityCondition('bundle', project_issue_issue_node_types())
+    ->fieldCondition('field_project', 'target_id', $repository->project_nid);
+  $result = $query->execute();
+  if (empty($result['node'])) {
+    // No issues associated.
+    return;
+  }
+  // Remove related rows from versioncontrol_project_issue_operations table.
+  $issue_nids = array_keys($result['node']);
+  // Do it in chunks of 500 items.
+  foreach (array_chunk($issue_nids, 500) as $chunk) {
+    db_delete('versioncontrol_project_issue_operations')->condition('nid', array_values($chunk), 'IN')->execute();
+  }
+}
+
+/**
+ * Helper to get the operation IDs.
+ *
+ * @param array $project_issue_nids
+ *   List of project issue nids.
+ *
+ * @return array
+ *   List of operation ids keyed by project issue node id.
+ */
+function versioncontrol_project_issue_get_issue_operation_ids($project_issue_nids) {
+  $vc_op_ids = array();
+  $result = db_query('SELECT nid, vc_op_id FROM {versioncontrol_project_issue_operations} WHERE nid IN (:nids)', array(':nids' => $project_issue_nids));
+  foreach ($result as $row) {
+    $vc_op_ids[$row->nid][] = $row->vc_op_id;
+  }
+  return $vc_op_ids;
+}
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue_git/plugins/event_processor/VersioncontrolEventProcessorGitIssueMapper.inc b/versioncontrol_project_issue/versioncontrol_project_issue_git/plugins/event_processor/VersioncontrolEventProcessorGitIssueMapper.inc
new file mode 100644
index 0000000..ae873da
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue_git/plugins/event_processor/VersioncontrolEventProcessorGitIssueMapper.inc
@@ -0,0 +1,148 @@
+<?php
+/**
+ * @file
+ * Maps issues with operations on git repositories based on commit messages.
+ */
+
+class VersioncontrolEventProcessorGitIssueMapper implements VersioncontrolSynchronizationEventProcessorInterface, VersioncontrolPluginConfigurationInterface {
+  /**
+   * Associated repository.
+   *
+   * @var VersioncontrolRepository
+   */
+  protected $repository;
+
+  /**
+   * Pattern to find issue numbers in commit messages.
+   */
+  protected $messagePattern;
+
+  public function process(VersioncontrolEvent $event) {
+    if (!$event instanceof VersioncontrolGitEvent) {
+      // Not a git event.
+      return;
+    }
+    $project_nid = db_query("SELECT nid FROM {versioncontrol_project_projects} WHERE repo_id = :repo_id", array(':repo_id' => $event->getRepository()->repo_id))->fetchField();
+    if (!$project_nid) {
+      // No project associated.
+      return;
+    }
+    // We are depending on getCommitInterval(), so check we are using the right
+    // synchronization plugin.
+    $synchronizer = $event->getRepository()->getSynchronizer();
+    if (!method_exists($synchronizer, 'getCommitInterval')) {
+      watchdog('versioncontrol_project_issue', 'git_issue_mapper: Cannot use a repository synchronizer of type %type', array('%type' => get_class($synchronizer)), WATCHDOG_WARNING);
+      return;
+    }
+    $operation_nid_maps = array();
+    foreach ($event as $ref) {
+      if ($ref->reftype != VERSIONCONTROL_GIT_REFTYPE_BRANCH) {
+        // Only process branch refs for now.
+        return;
+      }
+      if ($ref->ff != 1) {
+        // @fixme support non-ff.
+        continue;
+      }
+      if ($ref->eventDeletedMe()) {
+        // Nothing to do.
+        // We could try to figure out orphaned commits from label removal. Let's
+        // trust on hook_versioncontrol_entity_commit_delete() for now.
+        continue;
+      }
+      // Usual ff ref update.
+      $commit_hashes = $synchronizer->getCommitInterval($ref->old_sha1, $ref->new_sha1);
+      // Try to deal with big pushes loading operations in chunks of 500 items.
+      foreach (array_chunk($commit_hashes, 500) as $commit_hashes_chunk) {
+        $related_operations = $event->getRepository()->loadCommits(array(), array('revision' => $commit_hashes_chunk));
+        foreach ($related_operations as $operation) {
+          $nids_on_message = $this->getIssuesFromMessage($operation->message);
+          if (count($nids_on_message) < 1) {
+            // Nothing to do.
+            continue;
+          }
+          $valid_issue_nids = $this->checkValidIssues($nids_on_message);
+          foreach ($valid_issue_nids as $valid_issue_nid) {
+            $operation_nid_maps[] = array(
+              'nid' => $valid_issue_nid,
+              'vc_op_id' => $operation->vc_op_id
+            );
+          }
+        }
+      }
+    }
+    if (empty($operation_nid_maps)) {
+      // Nothing to do.
+      return;
+    }
+    // Insert mappings.
+    $insert_query = db_insert('versioncontrol_project_issue_operations')->fields(array('nid', 'vc_op_id'));
+    foreach ($operation_nid_maps as $operation_nid_map) {
+      $insert_query->values($operation_nid_map);
+    }
+    $insert_query->execute();
+  }
+
+  public function setRepository(VersioncontrolRepository $repository) {
+    $this->repository = $repository;
+  }
+
+  public function setConfiguration($default_data) {
+    $this->messagePattern = !empty($default_data['message_pattern']) ? $default_data['message_pattern'] : '';
+  }
+
+  public function buildForm($default_data) {
+    $form = array();
+    $form['event-processor-issue-mapper-pattern'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Extract pattern'),
+      '#description' => t('A pattern to be used to extract the issue ids from the commit message. i.e. "/#(\d+)\b/"'),
+      '#default_value' => !empty($default_data['message_pattern']) ? $default_data['message_pattern'] : '',
+    );
+    return $form;
+  }
+
+  public function getFormData($form_state_values_data) {
+    return array(
+      'message_pattern' => $form_state_values_data['event-processor-issue-mapper-pattern'],
+    );
+  }
+
+  public function submitForm(&$form, &$form_state) {
+    // Nothing special.
+  }
+
+  /**
+   * Retrieve the issues from operation message.
+   */
+  public function getIssuesFromMessage($message) {
+    if (preg_match_all($this->messagePattern, $message, $matches)) {
+      return $matches[1];
+    }
+    return array();
+  }
+
+  /**
+   * Returns nids which can be associated.
+   */
+  public function checkValidIssues($nids) {
+    $valid_nids = array();
+    // Make sure we are dealing with project issues.
+    $possible_issues = node_load_multiple($nids);
+    foreach ($possible_issues as $possible_issue) {
+      if (!project_issue_node_is_issue($possible_issue)) {
+        continue;
+      }
+      // Associate only if repository project is the same than issue
+      // project.
+      if (empty($possible_issue->field_project[LANGUAGE_NONE][0]['target_id'])) {
+        continue;
+      }
+      if ($possible_issue->field_project[LANGUAGE_NONE][0]['target_id'] != $this->repository->project_nid) {
+        continue;
+      }
+      $valid_nids[] = $possible_issue->nid;
+    }
+    return $valid_nids;
+  }
+}
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue_git/plugins/event_processor/git_issue_mapper.inc b/versioncontrol_project_issue/versioncontrol_project_issue_git/plugins/event_processor/git_issue_mapper.inc
new file mode 100644
index 0000000..2f9fec3
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue_git/plugins/event_processor/git_issue_mapper.inc
@@ -0,0 +1,14 @@
+<?php
+/**
+ * @file
+ * Maps issues on git commit messages.
+ */
+$plugin = array(
+  'vcs' => 'git',
+  'title' => t('Issue mapper for git repositories'),
+  'handler' => array(
+    'class' => 'VersioncontrolEventProcessorGitIssueMapper',
+    'file' => 'VersioncontrolEventProcessorGitIssueMapper.inc',
+    'path' => drupal_get_path('module', 'versioncontrol_project_issue_git') . '/plugins/event_processor',
+  ),
+);
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.drush.inc b/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.drush.inc
new file mode 100644
index 0000000..7977ce4
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.drush.inc
@@ -0,0 +1,127 @@
+<?php
+/**
+ * @file
+ *
+ * Drush integration for versioncontrol_project_issue_git.
+ */
+
+function versioncontrol_project_issue_git_drush_command() {
+  $items = array();
+
+  $items['vc-project-issue-git-resync-maps'] = array(
+    'description' => 'Re-discover project issue/operation maps based on project repository commit messages using git_issue_mapper event processor plugin.',
+    'arguments' => array(
+      'type' => 'Either repositories, projects or operations.',
+      'target' => 'A comma-delimited list of repository ids, project ids or operation ids corresponging with the type argument.',
+    ),
+    'examples' => array(
+      'drush vcpi-git-resync-maps repositories 1,2' => 'Re-discover issue/operation maps of the specified repositories.',
+      'drush vcpi-git-resync-maps projects 1,2' => 'Re-discover issue/operation maps of the specified projects.',
+      'drush vcpi-git-resync-maps operations 1,2' => 'Re-discover issue/operation maps of the specified operations.',
+    ),
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL,
+    'aliases' => array('vcpi-git-resync-maps'),
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_drush_help().
+ */
+function versioncontrol_project_issue_git_drush_help($section) {
+  switch ($section) {
+    case 'drush:vc-project-issue-git-resync-maps':
+      return dt('This command will try to re-synchronize issue/operation maps associated with the parmeters passed.');
+  }
+}
+
+/**
+ * Drush callback for 'vc-project-issue-git-resync-maps'.
+ */
+function drush_versioncontrol_project_issue_git_vc_project_issue_git_resync_maps() {
+  list($type, $ids) = func_get_args();
+  $ids = _convert_csv_to_array($ids);
+  $git_backend = versioncontrol_get_backends('git');
+
+  $default_event_processors = variable_get('versioncontrol_repository_plugin_defaults_git_event_processors');
+  if (!in_array('git_issue_mapper', $default_event_processors)) {
+    // Nothing to do.
+    return;
+  }
+  ctools_include('plugins');
+  $git_issue_mapper_plugin = ctools_get_plugins('versioncontrol', 'event_processor', 'git_issue_mapper');
+  $git_issue_mapper_class_name = ctools_plugin_get_class($git_issue_mapper_plugin, 'handler');
+  $git_issue_mapper_instace = new $git_issue_mapper_class_name();
+  $default_event_processor_data = variable_get('versioncontrol_repository_plugin_defaults_git_event_processors_data', array());
+  if (empty($default_event_processor_data['git_issue_mapper'])) {
+    $message = dt('Git issue mapper event processor is not yet configured.');
+    drush_log($message, 'error');
+    return drush_set_error('vcpi_git_resync_maps_unconfig_issue_mapper', $message);
+  }
+  switch ($type) {
+    case 'projects':
+      $projects = node_load_multiple($ids);
+      if (count($ids) != count($projects)) {
+        // Some projects were not loaded correctly.
+        $missing_ids = array_diff($ids, array_keys($projects));
+        drush_log(dt('Some project ids were not loaded correctly: (!ids)', array('!ids' => implode(', ', $missing_ids))), 'warning');
+      }
+      $ids = array();
+      foreach ($projects as $project) {
+        $ids[] = $project->versioncontrol_project['repo']->repo_id;
+      }
+      print_r($ids);
+    case 'repositories':
+      $repositories = $git_backend->loadEntities('repo', $ids);
+      if (count($ids) != count($repositories)) {
+        // Some repositories were not loaded correctly.
+        $missing_ids = array_diff($ids, array_keys($repositories));
+        drush_log(dt('Some repository ids were not loaded correctly: (!ids)', array('!ids' => implode(', ', $missing_ids))), 'warning');
+      }
+      foreach ($repositories as $repository) {
+        if (!versioncontrol_project_repository_has_project($repository)) {
+          // Nothing to do.
+          continue;
+        }
+        // Remove old entries.
+        versioncontrol_project_issue_delete_issue_operation_maps($repository);
+        // Set up the plugin.
+        $git_issue_mapper_instace->setRepository($repository);
+        $git_issue_mapper_instace->setConfiguration($default_event_processor_data['git_issue_mapper']);
+        $operation_nid_maps = array();
+        // Do a manual query for performance reasons.
+        $result = db_query('SELECT vc_op_id, message FROM versioncontrol_operations WHERE repo_id = :repo_id', array(':repo_id' => $repository->repo_id));
+        while ($row = $result->fetchAssoc()) {
+          $nids_on_message = $git_issue_mapper_instace->getIssuesFromMessage($row['message']);
+          if (count($nids_on_message) < 1) {
+            // Nothing to do.
+            continue;
+          }
+          $valid_issue_nids = $git_issue_mapper_instace->checkValidIssues($nids_on_message);
+          foreach ($valid_issue_nids as $valid_issue_nid) {
+            $operation_nid_maps[] = array(
+              'nid' => $valid_issue_nid,
+              'vc_op_id' => $row['vc_op_id'],
+            );
+          }
+        }
+        if (empty($operation_nid_maps)) {
+          // Nothing to do.
+          return;
+        }
+        // Insert mappings.
+        $insert_query = db_insert('versioncontrol_project_issue_operations')->fields(array('nid', 'vc_op_id'));
+        foreach ($operation_nid_maps as $operation_nid_map) {
+          $insert_query->values($operation_nid_map);
+        }
+        $insert_query->execute();
+      }
+      break;
+    case 'operations':
+      // @todo Implement.
+    default:
+      $message = dt('"!type" type not yet implemented.', array('!type' => $type));
+      return drush_set_error('vcpi_git_resync_maps_unimplemented_type', $message);
+  }
+}
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.info b/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.info
new file mode 100644
index 0000000..4c1ef66
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.info
@@ -0,0 +1,7 @@
+name = "Version Control / Project issue integration - Git"
+description = "Expose some functionality that integrates project_issue and Version Control API Git backend."
+package = Version Control
+dependencies[] = versioncontrol_project_issue
+dependencies[] = versioncontrol_git
+dependencies[] = project_issue
+core = 7.x
diff --git a/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.module b/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.module
new file mode 100644
index 0000000..54e3cbc
--- /dev/null
+++ b/versioncontrol_project_issue/versioncontrol_project_issue_git/versioncontrol_project_issue_git.module
@@ -0,0 +1,92 @@
+<?php
+/**
+ * @file
+ * Version Control / Project issue integration - Git backend.
+ */
+
+/**
+ * Implements ctools hook_ctools_plugin_directory().
+ */
+function versioncontrol_project_issue_git_ctools_plugin_directory($module, $plugin_type) {
+  if ($module == 'versioncontrol') {
+    return "plugins/$plugin_type";
+  }
+}
+
+/**
+ * Implements hook_versioncontrol_repository_pre_resync().
+ *
+ * Best effort to preserve existing mappings.
+ * A full review will be too costly, specially if there are a lot of associated
+ * issues.
+ * @todo Maybe add an option to do full re-map re-parsing operation messages.
+ */
+function versioncontrol_project_issue_git_versioncontrol_repository_pre_resync(VersioncontrolRepository $repository, $bypass) {
+  if (empty($repository->project_nid)) {
+    // No project associated.
+    return;
+  }
+  if (!$repository instanceof VersioncontrolGitRepository) {
+    // Not a git repository.
+    return;
+  }
+
+  // Load all associated project issue nids.
+  $query = new EntityFieldQuery();
+  $query->entityCondition('entity_type', 'node')
+    ->entityCondition('bundle', project_issue_issue_node_types())
+    ->fieldCondition('field_project', 'target_id', $repository->project_nid);
+  $result = $query->execute();
+  if (empty($result['node'])) {
+    // No issues associated.
+    return;
+  }
+  $issue_nids = array_keys($result['node']);
+  // Skip full operation loading, and do it manually for performance reasons.
+  $vc_op_ids_by_id = db_query('SELECT vco.vc_op_id, vco.revision FROM {versioncontrol_operations} vco JOIN {versioncontrol_project_projects} vcp WHERE vcp.repo_id = :repo_id', array(':repo_id' => $repository->project_nid))->fetchAllKeyed();
+  $vc_op_ids_by_issue_nid = versioncontrol_project_issue_get_issue_operation_ids($issue_nids);
+  $commit_hashes_by_issue_nid = array();
+  foreach ($vc_op_ids_by_issue_nid as $issue_nid => $vc_op_ids) {
+    foreach ($vc_op_ids as $vc_op_id) {
+      $commit_hashes_by_issue_nid[$issue_nid][] = $vc_op_ids_by_id[$vc_op_id];
+    }
+  }
+
+  // Only set the cache if there were results that'll need refreshing later
+  if (!empty($commit_hashes_by_issue_nid)) {
+    drupal_static('versioncontrol_project_issue_git_resync_recover_' . $repository->repo_id, $commit_hashes_by_issue_nid);
+    // @todo Use delete query with join?
+    // Do it in chunks of 500 items.
+    foreach (array_chunk($issue_nids, 500) as $chunk) {
+      db_delete('versioncontrol_project_issue_operations')->condition('nid', array_values($chunk), 'IN')->execute();
+    }
+  }
+}
+
+/**
+ * Implements hook_versioncontrol_repository_post_resync().
+ */
+function versioncontrol_project_issue_git_versioncontrol_repository_post_resync(VersioncontrolRepository $repository, $bypass) {
+  if (!$repository instanceof VersioncontrolGitRepository) {
+    // Not a git repository.
+    return;
+  }
+  $commit_hashes_by_issue_nid = &drupal_static('versioncontrol_project_issue_git_resync_recover_' . $repository->repo_id);
+  if (empty($commit_hashes_by_issue_nid)) {
+    // Nothing to do.
+    return;
+  }
+  $data_to_insert = FALSE;
+  $insert_query = db_insert('versioncontrol_project_issue_operations')->fields(array('nid', 'vc_op_id'));
+  foreach ($commit_hashes_by_issue_nid as $issue_nid => $commit_hashes) {
+    // Add data only if the commits are still there.
+    foreach ($repository->loadCommits(array(), array('revision' => $commit_hashes)) as $vc_op_id => $operation) {
+      $data_to_insert = TRUE;
+      $insert_query->values(array('nid' => $issue_nid, 'vc_op_id' => $operation->vc_op_id));
+    }
+  }
+  if ($data_to_insert) {
+    $insert_query->execute();
+  }
+  drupal_static_reset('versioncontrol_project_issue_git_resync_recover_' . $repository->repo_id);
+}
