Skip to content

Instantly share code, notes, and snippets.

@houkanshan
Created December 26, 2014 03:42
Show Gist options
  • Save houkanshan/9ca09ef52ef9db1fa08e to your computer and use it in GitHub Desktop.
Save houkanshan/9ca09ef52ef9db1fa08e to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This script helps removing Git branches.
# Run it from a git repo dir. It will open the Git branches list
# in your favorite editor. Delete some branches from the list.
# Save and close the file. The script applies the changes to the repo.
from subprocess import call, Popen, PIPE
from os import getenv
import re
import sys
args = sys.argv[1:]
if not args:
args = ['--merged', ' | sed \'/master/d\'']
# configure commands used in this script
editor_command = getenv('EDITOR') or 'vim'
branch_command = 'git branch -a ' + ' '.join(args)
mktemp_command = 'mktemp'
own_remote = 'origin'
# regex to check whether the branch is a remote branch
remote_re = re.compile(r'remotes\/')
def is_remote(branch):
return bool(remote_re.findall(branch))
# takes 'git branch' output and returns a set of branches
def branches_to_list(text):
branches = set()
for branch in re.split('\n', text):
branch = re.sub(' .+', '', branch.lstrip());
#if is_remote(branch):
#branch = branch.replace('remotes/', '')
if branch:
branches.add(branch)
return branches
# create a temp file
tmp_file = Popen(mktemp_command, stdout=PIPE).communicate()[0].decode().rstrip()
# write git branches to the temp file
call('%s > %s' % (branch_command, tmp_file), shell=True)
# get original branches
original_branches = branches_to_list(open(tmp_file, 'r').read())
# edit the temp file with the editor command
call('%s %s' % (editor_command, tmp_file), shell=True)
# get new branches
new_branches = branches_to_list(open(tmp_file, 'r').read())
# adding and renaming branches is not supported
if(new_branches.difference(original_branches)):
exit('Aborting! Do not add or rename branches, just remove them.')
# remove branches with Git
for branch in original_branches.difference(new_branches):
if is_remote(branch):
branch = branch.replace('remotes/', '')
pushable = re.sub('/', ' :', branch, 1)
print 'now delete remote: git push %s' % pushable
if own_remote in branch:
call('git push %s' % pushable, shell=True)
else:
call('git branch -r -d %s' % branch, shell=True)
else:
print 'now local: git push %s' % pushable
call('git branch -D %s' % branch, shell=True)
# just run `git remote prune origin` to remove local tracked branch
# which is not exist on server
call('git remote prune origin', shell=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment