Skip to content

Instantly share code, notes, and snippets.

@ikhoon
Forked from trustin/git-checkout-pr.sh
Last active May 4, 2023 09:30
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 ikhoon/9e960ea6466e9a73ebafc69e73196ff7 to your computer and use it in GitHub Desktop.
Save ikhoon/9e960ea6466e9a73ebafc69e73196ff7 to your computer and use it in GitHub Desktop.
git-checkout-pr.sh - fetches a Git pull request from the remote and creates a local branch for it
#!/usr/bin/env bash
set -Eeuo pipefail
log() {
echo -en '\033[1;32m'
echo -n "$@"
echo -e '\033[0m'
}
choice() {
if [[ $# -gt 0 ]]; then
# Use the first keyword as a serach keyword to minimize the list results
SEARCH=$1
else
SEARCH=''
fi
# gh pr list command always terminates with exit code 0 in a non-interactive
# environment. As a workaround, we check whether its output is empty
# to detect if the command was successful or not.
PR_CHOICES="$(
gh pr list --json number,title,author --limit 50 --search "is:open sort:updated-desc $SEARCH" |
jq -r '.[] | "\u001b[1m#\(.number)\u001b[0m \(.title) \u001b[0;32m@\(.author.login)\u001b[0m"'
)"
if [[ -z "$PR_CHOICES" ]]; then
echo 'Failed to list the pull requests.'
echo 'Please make sure `gh` command is configured properly.'
exec gh pr list
fi
PR_LENGTH="$(echo "$PR_CHOICES" | wc -l)"
if [[ "$PR_LENGTH" =~ ^[[:space:]]*1[[:space:]]* ]]; then
# The gh pr list command found only one result.
# Removing ANSI color codes from text
PR_CHOICE=$(echo $PR_CHOICES | sed -e 's/\x1b\[[0-9;]*m//g')
else
PR_CHOICE="$(
echo -n "$PR_CHOICES" |
fzf --ansi --prompt='Choose the pull request to check out: '
)"
fi
if [[ "$PR_CHOICE" =~ (^#([0-9]+) ) ]]; then
PR_ID="${BASH_REMATCH[2]}"
else
echo 'Failed to parse the choice:'
echo
echo " $PR_CHOICE"
echo
exit 1
fi
}
case $# in
0)
choice
;;
1)
if [[ $1 =~ ^[0=9]+$ ]]; then
PR_ID="$1"
else
choice $1
fi
;;
*)
echo "Usage: $0 [<pull request ID> or <search keyword>]" 1>&2
exit 1
;;
esac
PR_INFO="$(gh pr view "$PR_ID" --json 'headRepositoryOwner,headRefName,url')"
PR_AUTHOR="$(echo "$PR_INFO" | jq -r '.headRepositoryOwner.login')"
PR_BRANCH="$(echo "$PR_INFO" | jq -r '.headRefName')"
PR_URL="$(echo "$PR_INFO" | jq -r '.url')"
LOCAL_BRANCH="pr-$PR_ID-$PR_AUTHOR-$PR_BRANCH"
PR_ID_HYPERLINK="$(echo -e "\033]8;;$PR_URL\007#$PR_ID\033]8;;\007")"
if git branch --list --format='%(refname:short)' | grep -qF "$LOCAL_BRANCH"; then
if [[ "$(git branch --show-current)" == "$LOCAL_BRANCH" ]]; then
echo "You are already on the branch $LOCAL_BRANCH for $PR_ID_HYPERLINK."
else
log "You already have the branch $LOCAL_BRANCH for $PR_ID_HYPERLINK; switching to the local branch .."
git checkout "$LOCAL_BRANCH"
fi
exit 1
else
log "Checking out the pull request $PR_ID_HYPERLINK into $LOCAL_BRANCH .."
gh pr checkout "$PR_ID" -b "pr-$PR_ID-$PR_AUTHOR-$PR_BRANCH"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment