Skip to content

Instantly share code, notes, and snippets.

@jaredru
Last active January 6, 2016 02:46
Show Gist options
  • Save jaredru/89ab7a83546a7931aaad to your computer and use it in GitHub Desktop.
Save jaredru/89ab7a83546a7931aaad to your computer and use it in GitHub Desktop.
a git command to open pull requests in the default difftool
#!/usr/bin/env bash
set -fu -o pipefail
# prepare some help info
OPTS_SPEC="\
git prdifftool <github pull request url>
git prdifftool <github remote> <pull request number>
git prdifftool <pull request number>
git prdifftool opens a GitHub pull request in the default difftool
--
"
if [[ $# -eq 0 ]]; then
set -- -h
fi
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
shift
die () {
echo >&2 "$@"
exit 1
}
# if the first argument is a github url, parse it into repo and pr number
if [[ $1 =~ github\.com/([[:alnum:]]+/[[:alnum:]]+)/pull/([[:digit:]]+) ]]; then
repo=${BASH_REMATCH[1]}
pr=${BASH_REMATCH[2]}
# from the repo, we can find the user's remote name
remote=`git remote -v | grep -E -i -m1 "github\.com(:|/)$repo" | awk '{print $1}'`
elif [[ $# -eq 2 ]]; then
remote=$1
pr=$2
else
remote=origin
pr=$1
fi
# verify that we have valid arguments
[[ $remote ]] || die "FATAL: missing github remote"
[[ $(git remote -v | grep "^$remote\b.*github\.com") ]] || die "FATAL: invalid github remote '$remote'"
[[ $pr ]] || die "FATAL: missing pull request number"
[[ $pr =~ ^[[:digit:]]+$ ]] || die "FATAL: invalid pull request number '$pr'"
refname_head="refs/pull/$pr/head"
refname_merge="refs/pull/$pr/merge"
# list the remote's refs, and try to match a merge ref for the pr
ls_remote=`git ls-remote $remote`
head_ref=$(echo "$ls_remote" | grep "$refname_head")
merge_ref=`echo "$ls_remote" | grep "$refname_merge"`
# make sure the pr head ref exists in the given remote
[[ $head_ref ]] || die "FATAL: pull request '$pr' does not existing in remote '$remote'"
# we'll fetch one of two possible refs depending on the state of the pr
fetch=`git config remote.${remote}.fetch`
if [[ $merge_ref ]]; then
# we found a merge ref, fetch it, and save its sha
git fetch $remote $fetch refs/pull/$pr/merge
merge_sha=`echo $merge_ref | awk '{print $1}'`
else
# we didn't find a merge ref, so fetch the head ref
git fetch $remote $fetch refs/pull/$pr/head
pr_sha=`echo "$ls_remote" | grep "refs/pull/$pr/head" | awk '{print $1}'`
# list all the refs (and their children) except those that are ancestors of
# the pr, find the first child of it, and save its sha.
merge_sha=`git rev-list --all --children --not $pr_sha^@ | grep -m1 "^$pr_sha" | awk '{print $2}'`
fi
# diff the merge sha in the user's difftool
git difftool $merge_sha^..$merge_sha
@jaredru
Copy link
Author

jaredru commented Oct 9, 2015

Save in your path (probably /usr/local/bin) as git-prdifftool. The command can then be used as git prdifftool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment