code: def git_list_branches(repo_dir):
      
      command = ['git', 'branch', '--remotes', '--all',
                 '--verbose', '--no-abbrev']
      output = execute_git_command(command, repo_dir=repo_dir).splitlines()
      # remove nullish lines
      lines = [l.strip() for l in output if l.strip()]
      # find the * current branch
      try:
          current_branch = [l for l in lines if l.startswith('* ')][0]
      except IndexError:
          current_branch = None
      item = None
      if current_branch:
          lines.remove(current_branch)
          current_branch = current_branch.replace('* ', '', 1)
          if re.match('\(.*detached.+\)', current_branch):
              branch, rest = current_branch.split(')', 1)
              branch = "%s)" % branch
              sha, msg = rest.split(None, 1)
              item = {'branch': branch, 'commit': sha, 'message': msg}
          else:
              lines.insert(0, current_branch)
      # <branch> <hash> <commit_message>
      # make a list of lists with clean elements of equal length
      breakout = [k.split(None, 2) for k in lines]
      # remove any strange hashless outliers
      breakout = [k for k in breakout if len(k[1]) == 40]
      headers = ['branch', 'commit', 'message']
      # use izip_longest so we fill in None if message was empty
      result = [dict(zip_longest(headers, vals))
                for vals in breakout]
      if item:
          result.append(item)
      return result
docs: Return a list of git branches for the git repo in 'repo_dir'.
  
      .. code-block:: python
  
          [
              {'branch': <branchname>,
               'commit': <commit_hash>,
               'message': <commit message>},
              {...},
          ]