Revert bogus merger optimizations

Revert "Fix checkout when preparing a ref"

This reverts commit 6eeb24743a4012613a679600247c70986ff1f63d.

Revert "Don't reset the local repo"

This reverts commit 96ee718c4b162d77ed58865a684b9bedd46c9cab.

Revert "Fetch specific refs on ref-updated events"

This reverts commit bfd5853957d53e231c0ccdf74004f726709aa07e.

Change-Id: I50ae4535e3189350d3cc3a7527f89d5cb8eec01d
diff --git a/zuul/merger.py b/zuul/merger.py
index 2627b94..218f7f2 100644
--- a/zuul/merger.py
+++ b/zuul/merger.py
@@ -34,8 +34,6 @@
         self._initialized = False
         try:
             self._ensure_cloned()
-            # Pick up any tags or branch updates since we last ran:
-            self.update()
         except:
             self.log.exception("Unable to initialize repo for %s" % remote)
 
@@ -60,16 +58,29 @@
         self._ensure_cloned()
         self.repo = git.Repo(self.local_path)
 
+    def reset(self):
+        self._ensure_cloned()
+        self.log.debug("Resetting repository %s" % self.local_path)
+        self.update()
+        origin = self.repo.remotes.origin
+        for ref in origin.refs:
+            if ref.remote_head == 'HEAD':
+                continue
+            self.repo.create_head(ref.remote_head, ref, force=True)
+
+        # Reset to remote HEAD (usually origin/master)
+        self.repo.head.reference = origin.refs['HEAD']
+        self.repo.head.reset(index=True, working_tree=True)
+        self.repo.git.clean('-x', '-f', '-d')
+
+    def getBranchHead(self, branch):
+        return self.repo.heads[branch]
+
     def checkout(self, ref):
         self._ensure_cloned()
         self.log.debug("Checking out %s" % ref)
+        self.repo.head.reference = ref
         self.repo.head.reset(index=True, working_tree=True)
-        self.repo.git.clean('-x', '-f', '-d')
-        if self.repo.re_hexsha_only.match(ref):
-            self.repo.git.checkout(ref)
-        else:
-            self.fetch(ref)
-            self.repo.git.checkout("FETCH_HEAD")
 
     def cherryPick(self, ref):
         self._ensure_cloned()
@@ -94,15 +105,15 @@
         # data was fetched properly subsequent fetches don't seem to fail.
         # So try again if an AssertionError is caught.
         origin = self.repo.remotes.origin
-        self.log.debug("Fetching %s" % ref)
         try:
             origin.fetch(ref)
         except AssertionError:
             origin.fetch(ref)
 
         # If the repository is packed, and we fetch a change that is
-        # also entirely packed, the cache may be out of date.
-        # See the comment in update() and
+        # also entirely packed, the cache may be out of date for the
+        # same reason as reset() above.  Avoid these problems by
+        # recreating the repo object.
         # https://bugs.launchpad.net/zuul/+bug/1078946
         self.repo = git.Repo(self.local_path)
 
@@ -171,18 +182,13 @@
         r.recreateRepoObject()
         return r
 
-    def updateRepo(self, project, ref=None):
+    def updateRepo(self, project):
         repo = self.getRepo(project)
         try:
-            if ref:
-                self.log.debug("Fetching ref %s for local repository %s" %
-                               (ref, project))
-                repo.fetch(ref)
-            else:
-                self.log.info("Updating local repository %s" % project)
-                repo.update()
+            self.log.info("Updating local repository %s", project)
+            repo.update()
         except:
-            self.log.exception("Unable to update %s" % project)
+            self.log.exception("Unable to update %s", project)
 
     def _mergeChange(self, change, ref, target_ref):
         repo = self.getRepo(change.project)
@@ -237,8 +243,14 @@
         # Only current change to merge against tip of change.branch
         if len(sibling_items) == 1:
             repo = self.getRepo(item.change.project)
+            # we need to reset here in order to call getBranchHead
+            try:
+                repo.reset()
+            except:
+                self.log.exception("Unable to reset repo %s" % repo)
+                return False
             commit = self._mergeChange(item.change,
-                                       item.change.branch,
+                                       repo.getBranchHead(item.change.branch),
                                        target_ref=target_ref)
         # Sibling changes exist. Merge current change against newest sibling.
         elif (len(sibling_items) >= 2 and
diff --git a/zuul/scheduler.py b/zuul/scheduler.py
index 29c856e..6a6c5d1 100644
--- a/zuul/scheduler.py
+++ b/zuul/scheduler.py
@@ -563,14 +563,13 @@
             return
 
         # Preprocessing for ref-update events
-        if event.ref:
+        if hasattr(event, 'refspec'):
             # Make sure the local git repo is up-to-date with the remote one.
             # We better have the new ref before enqueuing the changes.
             # This is done before enqueuing the changes to avoid calling an
             # update per pipeline accepting the change.
-            self.log.info("Fetching updated ref %s for %s" %
-                          (event.ref, project))
-            self.merger.updateRepo(project, event.ref)
+            self.log.info("Fetching references for %s" % project)
+            self.merger.updateRepo(project)
 
         for pipeline in self.layout.pipelines.values():
             change = event.getChange(project,