'Collect all ancestors of heads up to (excluding) those in common.
:param heads: commits to start from
:param common: commits to end at, or empty set to walk repository
completely
:param get_parents: Optional function for getting the parents of a
commit.
:return: a tuple (A, B) where A - all commits reachable
from heads but not present in common, B - common (shared) elements
that are directly reachable from heads'

def _collect_ancestors(self, heads, common=set(), get_parents=(lambda commit: commit.parents)):

    bases = set()
    commits = set()
    queue = []
    queue.extend(heads)
    while queue:
        e = queue.pop(0)
        if (e in common):
            bases.add(e)
        elif (e not in commits):
            commits.add(e)
            cmt = self[e]
            queue.extend(get_parents(cmt))
    return (commits, bases)
