Last active
July 22, 2024 13:14
-
-
Save trustin/f873c7315c7cf28cd011009514c2b376 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
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
#!/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
I updated the script to use an argument as a search keyword of
gh pr list
if the input argument is not a number. For example,git-checkout-pr <search-key>
searches PRs matching the keyword. If the search result is one, the PR is checked out without an FZF prompt.https://gist.github.com/ikhoon/9e960ea6466e9a73ebafc69e73196ff7/revisions#diff-6079608fc2c302f5270d5d326299dd1431f12eb1ee7af716a3c690f960b444b5