Skip to content

Instantly share code, notes, and snippets.

@madprog
Created April 3, 2019 14:08
Show Gist options
  • Save madprog/c3c766318577cd99f6497a9769fbb2fa to your computer and use it in GitHub Desktop.
Save madprog/c3c766318577cd99f6497a9769fbb2fa to your computer and use it in GitHub Desktop.
Utility script which insert branch creation commands in a git rebase-TODO
#!/usr/bin/env python3
import os
import re
import subprocess as sp
import sys
def find_git_folder():
parts = os.getcwd().split(os.path.sep)
parts[0] = '/' # instead of ''
while len(parts) > 0:
p = os.path.join(*parts, '.git')
if os.path.exists(p):
return p
parts.pop()
raise RuntimeError(f'Unable to find a git folder in {os.getcwd()!r} '
'or one of its parents')
def main(args):
git_folder = find_git_folder()
rebase_todo_path = f'{git_folder}/rebase-merge/git-rebase-todo'
if not os.path.exists(rebase_todo_path):
raise RuntimeError('Unable to find git rebase TODO '
f'at {rebase_todo_path!r}. No rebase in progress?')
git_branches = sp.Popen(['git', '-C', git_folder, 'branch', '-v'],
stdout=sp.PIPE, stderr=sp.PIPE)
out, err = git_branches.communicate()
if git_branches.returncode != 0:
raise RuntimeError(err.decode('utf-8'))
branches = {}
for m in re.finditer(r'^[* ] ([^ ]+) +([0-9a-f]*) ', out.decode('utf-8'),
re.MULTILINE):
branches[m.group(2)] = m.group(1)
with open(rebase_todo_path, 'r') as fp:
rebase_todo = fp.readlines()
new_todo = []
line_expr = re.compile(r'^(?P<cmd>p|r|e|s|f|x|b|d|l|t|m|pick|reword|edit|'
r'squash|fixup|exec|break|drop|label|reset|merge) '
r'(?P<hash>[0-9a-f]{7})')
append_cmd = None
for line in rebase_todo:
m = line_expr.match(line)
if m:
if append_cmd is not None:
new_todo.append(append_cmd)
append_cmd = None
hash = m.group('hash')
if hash in branches:
append_cmd = f'exec git branch -f {branches[hash]} HEAD\n'
new_todo.append(line)
# Last append_cmd is not added because the branch will be moved by git-rebase
# If we move it ourselves, git-rebase will be lost and will fail
with open(rebase_todo_path, 'w') as fp:
fp.write(''.join(new_todo))
if __name__ == '__main__':
try:
main(sys.argv[1:])
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment