Skip to content

Instantly share code, notes, and snippets.

@viktor-evdokimov
Forked from koreno/README.md
Last active August 29, 2015 14:25
Show Gist options
  • Save viktor-evdokimov/61f3cf487173b8051636 to your computer and use it in GitHub Desktop.
Save viktor-evdokimov/61f3cf487173b8051636 to your computer and use it in GitHub Desktop.
'rebaser' improves on 'git rebase -i' by adding information per commit regarding which files it touched.
pick d0d13d0 1:removed some bullshit from __entrypoint.d _________9______
pick a44e878 2:Improvements to object.d and __entrypoint.d ________89______
pick 12c5b47 3:Add usage to build.d ___3____________
pick 318af43 4:Added .gitignore ______________e_
pick eb9ad0f 5:Attempting to add more array support _1_3_56_89abcd__
pick 8b8df05 6:Added some special support for ldc to object.d ________8_______
pick e630300 7:Removed imports from build ___3____________
pick 69ae673 8:c-main to d-main __2345_7_9______
pick c00b344 9:Implemented write an exit system calls _1_345678_______
pick 3901cca 10:Add wscript_build file 0__3____________
pick 349bec4 11:WAF: fix build script 0_______________
pick 70e1d26 12:Make main module qualified __2_____________
pick f22cca0 13:Update to 2.067 _1______________
pick 06cb727 14:revert to compiling under 2.066 01______________
pick 25c13c4 15:WAF: remove unneeded post()s 0_______________
# [0] wscript_build 0_______________
# [1] ports/posix.d _1______________
# [2] app/main.d __2_____________
# [3] build.d ___3____________
# [4] include/__entrypoint.di ____4___________
# [5] ports/linux.d _____5__________
# [6] source/array.d ______6_________
# [7] source/dmain.d _______7________
# [8] source/object.d ________8_______
# [9] source/__entrypoint.d _________9______
# [a] ports/windows.d __________a_____
# [b] source/ports/linux.d ___________b____
# [c] source/ports/posix.d ____________c___
# [d] source/ports/windows.d _____________d__
# [e] .gitignore ______________e_
# Rebase 9c75315..25c13c4 onto 9c75315
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
#!/usr/bin/env python3
from subprocess import check_call, check_output
SPACER = "_"
def parse_log(first, last):
gitlog = check_output([
'git', 'log', '--name-only', '--oneline', '--no-color',
'--format=#commit %h {idx:4}:%s',
"%s^..%s" % (first, last)],
universal_newlines=True)
lines = iter(gitlog.splitlines())
line = next(lines)
while True:
prefix, _, commit = line.partition(" ")
assert prefix == "#commit"
files = set()
for line in lines:
if line.startswith("#commit"):
yield (commit, sorted(files))
break # for
elif line:
files.add(line)
else:
yield (commit, sorted(files))
break # while
def compact(line, length, ellipsis="....", suffix_length=10):
if len(line) <= length:
return line
return line[:length-len(ellipsis)-suffix_length] + ellipsis + line[-suffix_length:]
def write_todo(file, first, last, comments):
from itertools import count, chain
from collections import defaultdict
from string import digits, ascii_letters
c = count(0)
file_indices = defaultdict(lambda: next(c))
SYM = dict(enumerate(chain(digits, ascii_letters)))
lines = []
log = list(parse_log(first, last))
width = min(120, max(len(c) for (c, _) in log) if log else 80)
for commit, files in log:
indices = {file_indices[f] for f in files}
placements = "".join(SYM[i % len(SYM)] if i in indices else SPACER for i in range(max(indices)+1)) if indices else ""
lines.append((compact(commit, width).ljust(width), placements))
lines.reverse()
placements_width = max(file_indices.values()) + 2
for i, (commit, placements) in enumerate(lines, 1):
print("pick", commit.format(idx=i), placements.ljust(placements_width, SPACER), file=file)
print("", file=file)
for f, i in sorted(file_indices.items(), key=lambda p: p[1]):
pos = SYM[i % len(SYM)].rjust(1+i, SPACER).ljust(placements_width, SPACER)
f = "[%s] %s" % (SYM[i], f)
fname = compact("# %s" % f, width+2).ljust(width+2)
print(fname, pos, file=file)
print("", file=file)
print(comments, file=file)
if __name__ == '__main__':
import sys
import os
if not os.path.isfile(sys.argv[1]):
base_commit = sys.argv[1]
os.environ['GIT_ORIG_EDITOR'] = check_output(["git", "var", "GIT_EDITOR"], universal_newlines=True).strip()
os.environ['GIT_EDITOR'] = __file__
os.execlpe("git", "git", "rebase", "-i", base_commit, os.environ)
todo_file = sys.argv[1]
os.environ['GIT_EDITOR'] = editor = os.environ['GIT_ORIG_EDITOR']
if not todo_file.endswith("git-rebase-todo"):
os.execlpe(editor, editor, todo_file, os.environ)
commits = []
with open(todo_file) as f:
for line in f:
if not line.strip():
break
commits.append(line.split()[1])
comments = f.read()
first, *_, last = commits
with open(todo_file, "w") as file:
write_todo(file, first, last, comments)
check_call([editor, todo_file])
# subl['-n', '-w', todo_file] & FG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment