Skip to content

Instantly share code, notes, and snippets.

@jonstacks
Created January 23, 2018 22:24
Show Gist options
  • Save jonstacks/a04cd68e44539fe7b37ca975634af02a to your computer and use it in GitHub Desktop.
Save jonstacks/a04cd68e44539fe7b37ca975634af02a to your computer and use it in GitHub Desktop.
Cleanup Git branches
"""
Usage:
python git-branch-cleanup.py <repo_name>
Run this script from the /tmp directory. It will clone the
repo locally and then proceed to delete branches.
"""
import os, errno, logging, sys
from subprocess import call, check_output, STDOUT
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
FNULL = open(os.devnull, 'w')
def get_remote_branches():
resp = check_output(['git', 'branch', '-a'])
clean_lines = []
for l in resp.splitlines():
l = l.strip()
if 'master' in l:
continue
if 'origin/' not in l:
continue
l = l.split("origin/", 1)[1]
clean_lines.append(l)
return clean_lines
def init_git_repo(dir_name):
dir_path = os.path.join(os.path.dirname(__file__), dir_name)
logger.info("Creating directory {}".format(dir_path))
try:
os.makedirs(dir_path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
os.chdir(dir_path)
call('git clone git@github.com:C2FO/{}.git .'.format(dir_name), stdout=FNULL, shell=True)
def checkout_local_copy(branch):
call('git checkout -b {0} origin/{0}'.format(branch), stdout=FNULL, shell=True)
def delete_local_branch(branch):
resp = check_output(['git', 'branch', '-d', branch], stderr=STDOUT)
if 'warning' in resp:
return False
if 'but not yet merged to HEAD' in resp:
return False
return True
def delete_remote_branch(branch):
try:
resp = check_output(['git', 'push', 'origin', ':{}'.format(branch)], stderr=STDOUT)
return resp
except Exception as e:
return "Could not delete branch '{}' : {}".format(branch, str(e))
if __name__ == "__main__":
repo = sys.argv[1]
init_git_repo(repo)
remote_branches = get_remote_branches()
for b in remote_branches:
checkout_local_copy(b)
# Switch back to master
call('git checkout master', shell=True)
deleted = 0
not_deleted = 0
protected_branches = ['master', 'release', 'develop', 'hot-fix']
try:
for b in remote_branches:
if any(b in s for s in protected_branches):
print "Branch {} is protected".format(b)
continue
if delete_local_branch(b):
# print "Safe to delete {}".format(b)
print delete_remote_branch(b)
deleted += 1
else:
print "Not safe to delete {}".format(b)
not_deleted += 1
except Exception as e:
print str(e)
print "Deleted {} branches.".format(deleted)
print "Did not delete {} branches.".format(not_deleted)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment