docs: def _process_changes(self, newRev, branch):
          """
          Read changes since last change.
  
          - Read list of commit hashes.
          - Extract details from each commit.
          - Add changes to database.
          """
  
          # initial run, don't parse all history
          if not self.lastRev:
              return
          rebuild = False
          if newRev in self.lastRev.values():
              if self.buildPushesWithNoCommits:
                  existingRev = self.lastRev.get(branch)
                  if existingRev is None:
                      # This branch was completely unknown, rebuild
                      log.msg('gitpoller: rebuilding {} for new branch "{}"'.format(
                              newRev, branch))
                      rebuild = True
                  elif existingRev != newRev:
                      # This branch is known, but it now points to a different
                      # commit than last time we saw it, rebuild.
                      log.msg('gitpoller: rebuilding {} for updated branch "{}"'.format(
                              newRev, branch))
                      rebuild = True
  
          # get the change list
          revListArgs = (['--format=%H', '{}'.format(newRev)] +
                         ['^' + rev
                          for rev in sorted(self.lastRev.values())] +
                         ['--'])
          self.changeCount = 0
          results = yield self._dovccmd('log', revListArgs, path=self.workdir)
  
          # process oldest change first
          revList = results.split()
          revList.reverse()
  
          if rebuild and not revList:
              revList = [newRev]
  
          self.changeCount = len(revList)
          self.lastRev[branch] = newRev
  
          if self.changeCount:
              log.msg('gitpoller: processing {} changes: {} from "{}" branch "{}"'.format(
                      self.changeCount, revList, self.repourl, branch))
  
          for rev in revList:
              dl = defer.DeferredList([
                  self._get_commit_timestamp(rev),
                  self._get_commit_author(rev),
                  self._get_commit_files(rev),
                  self._get_commit_comments(rev),
              ], consumeErrors=True)
  
              results = yield dl
  
              # check for failures
              failures = [r[1] for r in results if not r[0]]
              if failures:
                  for failure in failures:
                      log.err(
                          failure, "while processing changes for {} {}".format(newRev, branch))
                  # just fail on the first error; they're probably all related!
                  failures[0].raiseException()
  
              timestamp, author, files, comments = [r[1] for r in results]
  
              yield self.master.data.updates.addChange(
                  author=author,
                  revision=bytes2unicode(rev, encoding=self.encoding),
                  files=files, comments=comments, when_timestamp=timestamp,
                  branch=bytes2unicode(self._removeHeads(branch)),
                  project=self.project,
                  repository=bytes2unicode(self.repourl, encoding=self.encoding),
                  category=self.category, src='git')