Last active
April 11, 2019 22:53
-
-
Save jakecraige/51f9583f1f55cc0ecccfaa11e7a7c6b1 to your computer and use it in GitHub Desktop.
Script to allow for some fancy git workflows as described in https://wchargin.github.io/posts/managing-dependent-pull-requests/. I've extended it to also have features to support a style described in https://jg.gg/2018/09/29/stacked-diffs-versus-pull-requests/ via the --pick(-p) option
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# | |
# git-push-to-target: Force push with lease this commit to a branch specified in its | |
# commit description like `branch: jake/my-branch`: | |
# | |
# `git-push-to-target --query` will do a dry run and print the branch name it detects | |
# `git-push-to-target --pick` will pick this to it's own branch off master and push. | |
# | |
# Usage within an interative rebase, add this after each commit that contains the branch directive: | |
# > exec git push-to-target | |
# | |
# Copyright (c) 2017 William Chargin. Released under the MIT license. | |
# https://wchargin.github.io/posts/managing-dependent-pull-requests/ | |
# Modified by Jake Craige for: | |
# - Mac sed support | |
# - Remove branch prefix | |
# - Support sha argument | |
# - Support pick option to move to it's own branch | |
set -eu | |
DIRECTIVE='branch' | |
target_branch() { | |
source="$1" | |
directive="$( \ | |
git show "$source" --pretty='%B' \ | |
| sed -n 's/^'"${DIRECTIVE}"': \([A-Za-z0-9_./-]*\)$/\1/p' \ | |
; )" | |
if [ -z "${directive}" ]; then | |
printf >&2 'error: missing "%s" directive\n' "${DIRECTIVE}" | |
return 1 | |
fi | |
if [ "$(printf '%s\n' "${directive}" | wc -l)" -gt 1 ]; then | |
printf >&2 'error: multiple "%s" directives\n' "${DIRECTIVE}" | |
return 1 | |
fi | |
printf '%s\n' "${directive}" | |
} | |
main() { | |
arg="${1:-none}" | |
case $arg in | |
-q|--query) | |
branch="$(target_branch "${2:-HEAD}")" | |
echo $branch | |
return | |
;; | |
-p|--pick) | |
source="${2:-HEAD}" | |
head_sha="${2:-$(git rev-parse --verify HEAD)}" | |
branch="$(target_branch "$source")" | |
set -x | |
git fetch | |
# create new branch from master, expect it to not exist or fail. tmp prefix needed to not | |
# accidentally checkout an existing remote branch with same name. | |
git checkout -b "tmp/$branch" origin/master | |
# cherry-pick commit over and push the branch | |
git cherry-pick "$head_sha" | |
git push --force-with-lease origin HEAD:refs/heads/"$branch" | |
# Clean up. Go back to where we came from. If specific commit sha given, assume no rebase and | |
# go back to last branch. If not, we assume rebase and go back to the sha. | |
# Then delete tmp branch from local git | |
if [ -n "${2:-}" ]; then # non-empty value | |
git checkout - | |
else | |
git checkout "$head_sha" | |
fi | |
git branch -D "tmp/$branch" | |
;; | |
*) | |
source="${1:-HEAD}" | |
branch="$(target_branch "$source")" | |
git push --force-with-lease origin "$source":refs/heads/"$branch" | |
;; | |
esac | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment