-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgit-mass-branch-rename
executable file
·96 lines (79 loc) · 2.84 KB
/
git-mass-branch-rename
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env python3
"""
Git branch editor.
This script spawns the editor configured in Git, in order to edit the local
list of branches as if it was a text file. It allows removing branches, adding
branches, changing branches' names, and setting a branch to a different
githash.
"""
import os
import pty
import subprocess as sp
import sys
import re
import tempfile
import argparse
PREFIX = "refs/heads/"
def dict_diff(a, b):
for key in list(set(a.keys()) | set(b.keys())):
yield (a.get(key, None), b.get(key, None))
def main():
parser = argparse.ArgumentParser(description='Mass branch editor')
parser.add_argument('--by-date', dest="by_date", action='store_true')
args = parser.parse_args()
x = os.popen('git for-each-ref --format="%(objectname) %(refname) ' +
'# %(committerdate:format:%Y-%m-%d): %(subject)"', "r")
data = x.read()
x.close()
lst = []
for line in data.splitlines():
m = re.match(r"^([a-f0-9]+) ([^ ]+) (.*)$", line)
(githash, refname, meta) = m.groups()
if not refname.startswith(PREFIX):
continue
lst.append((githash, refname, meta))
if args.by_date:
lst.sort(key=lambda item: item[2])
branches = {}
idx = 1
for item in lst:
branches[idx] = item
idx += 1
editor = os.popen("git config core.editor", "r").read().strip()
filename = tempfile.mktemp("git-mass-branch-rename")
filehandle = open(filename, "w")
for (key, (githash, refname, meta)) in branches.items():
refname = refname[len(PREFIX):]
githash = githash[:12]
print("%d: %s %-35s %s" % (key, githash, refname, meta), file=filehandle)
filehandle.close()
cmd = "%s %s" % (editor, filename)
os.system(cmd)
output = {}
for line in open(filename):
m = re.match(r"^([0-9]+): +([a-f0-9]+) +([^ ]+)( +.*)$", line.strip())
(idx, githash, new_name, _) = m.groups(0)
idx = int(idx)
output[idx] = (githash, new_name)
os.unlink(filename)
for (orig, after) in dict_diff(branches, output):
cmd = None
if after is None and orig is not None:
(orig_githash, orig_refname, _) = orig
cmd = "git update-ref -d %s" % (orig_refname, )
elif orig is not None and after is not None:
(orig_githash, orig_refname, _) = orig
(new_githash, new_name) = after
branch_name = orig_refname[len(PREFIX):]
cmd = ""
if orig_githash[:12] != new_githash:
cmd = "git update-ref %s %s" % (orig_refname, new_githash)
if branch_name != new_name:
if cmd:
cmd += "&& "
cmd += "git branch -M %s %s" % (branch_name, new_name)
if cmd:
print(cmd)
os.system(cmd)
if __name__ == "__main__":
main()