Skip to content

Instantly share code, notes, and snippets.

@mnieber
Created March 9, 2020 08:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnieber/bfa7a225885a59c27e96f8af0c09bd9f to your computer and use it in GitHub Desktop.
Save mnieber/bfa7a225885a59c27e96f8af0c09bd9f to your computer and use it in GitHub Desktop.
Picks a commit and puts it on a new branch
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Usage: git pick sha branch-name --base[=origin/master]
#
# Picks a commit and puts it on a new branch that is based off "base".
# The following actions are taken:
#
# - check if branch-name does not already exist (abort if it does)
# - resolve "sha" to an absolute hash
# - git fetch
# - git checkout of branch-name based on "base"
# - git cherry-pick "sha" (using the absolute hash)
# - git checkout - (this returns us to the previous branch)
# - remove branch-name if any of the previous steps failed
#
import argparse
import subprocess
import sys
def git(*args, quiet=False):
pipes = subprocess.Popen(['git'] + list(args),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
std_out, std_err = pipes.communicate()
std_out = std_out.decode('utf-8')
std_err = std_err.decode('utf-8')
if pipes.returncode != 0:
if not quiet:
print(std_out)
print(std_err.strip())
raise Exception(pipes.returncode)
return std_out
def chop(x):
return x[:-1] if x.endswith("\n") else x
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("sha")
parser.add_argument("branch_name")
parser.add_argument("--base", default="origin/master")
args = parser.parse_args()
args.abs_sha = chop(git("rev-parse", args.sha))
try:
git("diff-index", "--quiet", "HEAD", "--")
except Exception:
print("You have uncommitted changes")
sys.exit(1)
try:
git("rev-parse", "--verify", args.branch_name, quiet=True)
except Exception:
pass
else:
print("Destination branch already exists")
sys.exit(1)
try:
git("fetch")
except Exception:
pass
git("branch", args.branch_name, args.base)
git("checkout", args.branch_name)
failed = False
try:
git("cherry-pick", args.abs_sha)
except Exception:
failed = True
print("Sorry, cherry-pick failed")
git("checkout", "-")
if failed:
git("branch", "-d", args.branch_name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment