This little bash snippet will let you open a GitHub or GitLab pull request from the command line on most Unix-like systems (OSX, Ubuntu, etc), without using any magic libraries, ZSH tricks or other dependencies.
tl;dr download the gpr.sh
gist.
Here’s how it looks in action OSX:
And Ubuntu:
The script is available as the gpr.sh
gist. You can also find it in my dotfiles, in the git.sh file.
The Script
Here’s the script in its entirety:
# Colour constants for nicer output.
GREEN='\033[0;32m'
RESET='\033[0m'
# Push the current branch to origin, set upstream, open the PR page if possible.
gpr() {
# Get the current branch name, or use 'HEAD' if we cannot get it.
branch=$(git symbolic-ref -q HEAD)
branch=${branch##refs/heads/}
branch=${branch:-HEAD}
# Pushing take a little while, so let the user know we're working.
echo "Opening pull request for ${GREEN}${branch}${RESET}..."
# Push to origin, grabbing the output but then echoing it back.
push_output=`git push origin -u ${branch} 2>&1`
echo ""
echo ${push_output}
# If there's anything which starts with http, it's a good guess it'll be a
# link to GitHub/GitLab/Whatever. So open it.
link=$(echo ${push_output} | grep -o 'http.*' | sed -e 's/[[:space:]]*$//')
if [ ${link} ]; then
echo ""
echo "Opening: ${GREEN}${link}${RESET}..."
python -mwebbrowser ${link}
fi
}
How It Works
Blow-by-blow, let’s take a look.
# Colour constants for nicer output.
GREEN='\033[0;32m'
RESET='\033[0m'
To make colouring console output easier, we create strings with the escape code required to set the ‘green’ colour, and reset the text colour.
gpr() {
# Get the current branch name, or use 'HEAD' if we cannot get it.
branch=$(git symbolic-ref -q HEAD)
branch=${branch##refs/heads/}
branch=${branch:-HEAD}
Now we define the gpr
(Git Pull Request) function. We’ll need to push the current branch, so we need to get the current branch name. There’s plenty of discussion on how this works on Stack Overflow: How to get the current branch name in Git. Essentially we just get the symbolic name for the head of our current branch, which will be something like this:
refs/heads/my-new-branch
We then use Bash substring removal to rip out the ref/heads/
part. If we have no branch (for example, we are detached) we just use HEAD
a the branch name.
Next we have this:
# Pushing take a little while, so let the user know we're working.
echo "Opening pull request for ${GREEN}${branch}${RESET}..."
# Push to origin, grabbing the output but then echoing it back.
push_output=`git push origin -u ${branch} 2>&1`
echo ""
echo ${push_output}
We’ve previously defined some strings which include the escape codes to colour terminal output. Now we just show the user the branch we’re going to push, push it and then store all of the output in the push_output
variable.
The 2>&1
idiom is a common one. This simply makes sure we put all stderr
output (which is always file descriptor 2) into stdout
(which is always file descriptor 1). This means whether the program writes output to stdout
or stderr
, we capture it. There’s a nice write-up on this in the blog post ‘Understanding Shell Script’s idiom: 2>&1
’.
The output from Git push will be dependent on the Git server being used. For GitHub it’ll look like this:
remote:
remote: Create a pull request for 'feat/doc-cleanup' on GitHub by visiting:
remote: https://github.com/dwmkerr/dotfiles/pull/new/feat/doc-cleanup
remote:
To github.com:dwmkerr/dotfiles
* [new branch] feat/doc-cleanup -> feat/doc-cleanup
Branch feat/doc-cleanup set up to track remote branch feat/doc-cleanup from origin.
Now all we want to do is see if there is any text which starts with http
and if there is, then open it. Here’s how we do that:
# If there's anything which starts with http, it's a good guess it'll be a
# link to GitHub/GitLab/Whatever. So open it.
link=$(echo ${push_output} | grep -o 'http.*' | sed -e 's/[[:space:]]*$//')
if [ ${link} ]; then
echo ""
echo "Opening: ${GREEN}${link}${RESET}..."
python -mwebbrowser ${link}
fi
This uses grep
to rip out everything from http
onwards, and the sed
to remove any trailing whitespace. If we have found a link, we use python
to open it (which is a fairly safe cross-platform solution).
That’s it! When you have a branch ready which you want to push and create a pull request from, just run:
gpr
And the branch will be pushed to origin
, and if there is a Pull Request webpage, it’ll be opened.
Prior Art
My colleague Tobias recently shared a nice trick we worked out to open a GitLab merge request - which also now works for GitHub:
git push and directly open PR in Chrome - works for @github & @gitlab 🚀
— Tobias Büschel (@TobiasBueschel) September 19, 2018
Here is how to set it up 👉 https://t.co/YfNTmdwTFt #github #gitlab pic.twitter.com/ISE9kVZmw1
I wanted to be able to use the same trick in Ubuntu and other Linux distros, but realised it relied on oh-my-zsh and assumed OSX with Chrome as the browser, so tweaked it to the above. Thanks Tobi!