Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 105 lines (75 sloc) 3.26 KB
#!/usr/bin/env python3
import argparse
import re
import subprocess
import sys
def get_default_branch():
"""Get the repo's "default" branch from the config. If not set, then use either master or main"""
result = subprocess.run(['git', 'config', '--get', 'rmbranch.defaultBranch'], capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.rstrip()
for branch_name in ('master', 'main'):
if subprocess.run(['git', 'show-ref', '--verify', '--quiet', f'refs/heads/{branch_name}']).returncode == 0:
return branch_name
raise RuntimeError('Unable to determine the default branch for the repo')
def get_upstream(branch_name):
"""Get upstream information for a local branch from config"""
result = subprocess.run(
['git', 'config', '--get-regexp', fr'^branch\.{re.escape(branch_name)}\.'],
capture_output=True, text=True)
if result.returncode != 0:
return None
upstream = {}
offset = len(f'branch.{branch_name}.')
for line in result.stdout.splitlines():
key, value = line.split()
key = key[offset:]
assert key not in upstream, f"Multiple values for 'branch.{branch_name}.{key}'"
upstream[key] = value
return upstream
def get_current_branch():
"""Get the current branch name"""
return subprocess.run(
['git', 'branch', '--show-current'],
capture_output=True, check=True, text=True
).stdout.rstrip()
def main():
args = parse_args()
current_branch = get_current_branch()
branch_name = current_branch if args.branch_name is None else args.branch_name
default_branch = get_default_branch()
if branch_name == default_branch:
print(f"Refusing to remove the default branch '{branch_name}'")
return 1
if branch_name == current_branch:
new_branch = input(f'Enter a branch name to checkout ({default_branch}): ').strip()
if not new_branch:
new_branch = default_branch
result = subprocess.run(['git', 'checkout', new_branch])
if result.returncode != 0:
return result.returncode
upstream = get_upstream(branch_name)
result = subprocess.run(['git', 'branch', '-D', branch_name],
capture_output=True, text=True)
if result.returncode != 0:
print(result.stderr, end='')
return result.returncode
sha = re.search(r'\(was (\w+)\)', result.stdout)[1]
print(result.stdout.rstrip(),
f"To restore, run 'git branch {branch_name} {sha}'.")
if upstream is None:
print(f"No upstream configured for the branch '{branch_name}'.")
return 0
print(f"Deleting '{upstream['merge']}' from '{upstream['remote']}'..")
# this command also removes the local remote-tracking branch
return subprocess.run(
['git', 'push', upstream['remote'], '--delete', upstream['merge']],
timeout=30
).returncode
def parse_args():
parser = argparse.ArgumentParser(description='Delete a Git branch locally and remotely.')
parser.add_argument('branch_name', nargs='?',
help='The branch name. In case no argument is provided, the current branch will be used')
return parser.parse_args()
if __name__ == '__main__':
sys.exit(main())