Last active
December 15, 2015 14:38
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python -O | |
""" | |
Finds the branch all the commits have most likely been mode on | |
""" | |
import os | |
import sys | |
import re | |
from pprint import pprint | |
if len(sys.argv) < 2: | |
print ("USAGE: {0} <list-of-branches>".format([sys.argv[0]])) | |
exit(1) | |
rev_list = os.popen('git log --format="%H:%P:%s" ' + ' '.join(sys.argv[1:])) | |
heads = {} | |
for head in sys.argv[1:]: | |
if head[0] == "^": | |
continue | |
sha = os.popen('git rev-parse {0}'.format(head)).read().strip() | |
heads[head] = sha | |
commits = {} | |
# commit structure: | |
# [parents, children, msg, distances | |
for line in rev_list: | |
line = line.strip().split(":") | |
sha = line[0] | |
if sha not in commits: | |
commits[sha] = [[], [], "", {}] | |
commit = commits[sha] | |
# Build Tree | |
for parent in line[1].split(' '): | |
if parent.strip() == "": | |
continue | |
if parent not in commits: | |
commits[parent] = [[], [], "", {}] | |
parent = commits[parent] | |
parent[1].append(commit) | |
commit[0].append(parent) | |
# Commit message | |
if len(commit[0]) > 1: | |
commit[2] = line[2] | |
def getBranchNames(message): | |
m = re.match(r"Merge branch '([^']+)' into (.+)", message) | |
if m is None: | |
return None | |
else: | |
return [m.group(2), m.group(1)] | |
known = [] | |
for (branch, sha) in heads.iteritems(): | |
todo = [] | |
c = commits[sha] | |
d = 0 | |
while True: | |
c[3][branch] = d | |
d = d - 1 | |
if len(c[0]) == 2: | |
names = getBranchNames(c[2]) | |
todo.append([c[0][1], d + 100 + 10000 * (names[1] == branch)]) | |
c = c[0][0] | |
d = d + 10000 * (names[0] == branch) | |
for (parent, name) in zip(c[0], names): | |
if name not in heads: | |
continue | |
for parent_child in parent[1]: | |
# Are we the first parent? | |
if parent_child[0][0] == parent: | |
known.append([name, parent_child]) | |
elif len(c[0]) > 0: | |
c = c[0][0] | |
todo.extend([x, d + 100] for x in c[0][1:]) | |
else: | |
try: | |
(c, d) = todo.pop() | |
except IndexError: | |
break | |
branchHeadIds = set(id(commits[sha]) for sha in heads.itervalues()) | |
for (branch, c) in known: | |
while True: | |
if branch not in c[3]: | |
break | |
if id(c) in branchHeadIds: | |
break | |
c[3][branch] = c[3][branch] - 10000 | |
if len(c[1]) == 1: | |
c = c[1][0] | |
else: | |
break | |
match = {} | |
for (sha, commit) in sorted(commits.iteritems()): | |
match[sha] = min(commit[3].items(), key=lambda x: x[1])[0] | |
#print sha + ": " + match[sha] | |
log = os.popen('git log --color --oneline --graph --decorate --abbrev=100 ' | |
+ ' '.join(sys.argv[1:])).read().splitlines() | |
for line in log: | |
try: | |
sha = re.search('[a-f0-9]{40}', line).group(0) | |
except AttributeError: | |
print line | |
continue | |
print re.sub('([a-f0-9]{7})[a-f0-9]{33}', | |
r'\1 [{}]'.format(match[sha]), line) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment