You finally did it! You finished writing your new feature and it's fully tested. You write up a snazzy commit message and hit enter. Your command line is telling you that you have a clean branch and you want to share it with the world RIGHT NOW!
Unfortunately, you have a few mind-numbing steps to take before everyone can bask in the glory of your code. First, you have to push the branch to your remote repository. Next, you have to open up the GitHub repo and click on the "New pull request" button. Then you have to manually select the branch you just published. Finally, you can start writing your PR and share it.
Wouldn't it be nice if you could skip all these steps with one command? Jose can help!
My colleague Logan Henson mentioned this in "Tip 3" of his incredibly helpful post, Building a Great Pull Request. I have made some minor improvements since then. I highly recommend reading his blog post.
The process to automate this is a bit more complicated than can be achieved using a bash alias, so we're going to use bash functions. I recommend using Oh My Zsh, since you're able to easily add functions to the ~/.oh-my-zsh-custom/custom/functions.zsh
file.
I'll post my functions here and we can go over what they're doing.
The openpr()
function does all of the heavy lifting. Using commands like git
, awk
, sed
, and cut
, it generates the GitHub Pull Request URL using the remote configured in your local repository. Let's dissect what it does.
# Open the Pull Request URL for your current directory's branch (base branch defaults to main)function openpr() { github_url=`git remote -v | awk '/fetch/{print $2}' | sed -Ee 's#(git@|git://)#https://#' -e 's@com:@com/@' -e 's%\.git$%%' | awk '/github/'`; branch_name=`git symbolic-ref HEAD | cut -d"/" -f 3,4`; pr_url=$github_url"/compare/main..."$branch_name open $pr_url;} # Run git push and then immediately open the Pull Request URLfunction gpr() { git push origin HEAD if [ $? -eq 0 ]; then openpr else echo 'failed to push commits and open a pull request.'; fi}
github_url
)github_url=`git remote -v | awk '/fetch/{print $2}' | sed -Ee 's#(git@|git://)#https://#' -e 's@com:@com/@' -e 's%\.git$%%' | awk '/github/'`;
git remote -v
lists all of your configured remote repositories. This script assumes that you only have one GitHub remote URL. If your repo has more than one, you will need to add some logic to account for that.
awk '/fetch/'
takes the result of the git remote call and grabs the line that contains the text "fetch".
At this point, the resulting text looks something like:
origin git@github.com:tightenco/symposium.git (fetch)
If you think about exploding each section of that line by spaces, then you end up with this array-like structure:
['origin', 'git@github.com:tightenco/symposium.git', '(fetch)']
The next command, {print $2}
, prints the second of those items. So at this point, we have the text:
git@github.com:tightenco/symposium.git
Now, we use the sed
command to modify the text to make it a GitHub URL.
git@github.com:tightenco/symposium.git
turns into
https://github.com/tighten/symposium
.
The final awk
command filters out any non-GitHub URLs. This is usually only applicable if you have multiple remotes configured in your repo and one of them is not a GitHub remote.
We have now generated the GitHub URL for the remote repository regardless of whether the repository was cloned using SSH or HTTPS.
branch_name
)We need to get the local branch name so we know which branch we're going to compare in the pull request.
branch_name=`git symbolic-ref HEAD | cut -d"/" -f 3,4`;
By running git symbolic-ref HEAD
we get the full reference for the current branch we're on. The result looks something like:
refs/heads/main
We need to explode that string by using /
as a delimiter, which would give us an array-like structure of ['refs', 'heads', 'main']
and grab the 3rd item.
We can do this by using the cut
command. -d"/"
sets the delimiter and -f 3
grabs the 3rd item.
However, sometimes I namespace my branches with my initials like jas/some-feature
. So in order for this command to work with that naming structure, I need to use -f 3,4
which grabs everything between the 3rd and 4th item. Feel free to adjust that according to your workflow.
pr_url
)Next, we need to generate the URL that will allow us to create the Pull Request. I have it hard-coded to merge into the remote main branch, but you can modify that if you like.
pr_url=$github_url"/compare/main..."$branch_name
This command constructs the full URL for the pull request using the GitHub base URL and branch name we generated in the previous commands. It sets that value to the variable pr_url
.
https://github.com/tightenco/symposium/compare/main...jas/some-feature
.
The open
command automatically opens that URL in your browser. Visiting this URL will open the "Comparing changes" page and all you have to do is click "Create pull request" to write your notes. No need to select specific branches.
But we're not done yet. We still need to publish our branch before it can even be compared. That's where the gpr()
function comes in.
function gpr() { git push origin HEAD if [ $? -eq 0 ]; then openpr else echo 'failed to push commits and open a pull request.'; fi}
gpr()
is a simple function that will publish your local branch to the remote by using git push origin HEAD
.
If that command succeeds, then openpr()
is called, otherwise, it displays an error that the branch could not be published.
And that's it. Now you can use the gpr
command straight from your command line to automatically open a page to compare two remote branches and start the Pull Request process automatically!
We appreciate your interest.
We will get right back to you.