Return a list of git branches for the git repo in 'repo_dir'.

    .. code-block:: python

        [
            {'branch': <branchname>,
             'commit': <commit_hash>,
             'message': <commit message>},
            {...},
        ]

def git_list_branches(repo_dir):
    """Return a list of git branches for the git repo in 'repo_dir'.

    .. code-block:: python

        [
            {'branch': <branchname>,
             'commit': <commit_hash>,
             'message': <commit message>},
            {...},
        ]
    """
    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