Get and compare the current Git branch in BASH
My favorite revision control system is Git. I use it to maintain all of my Ruby on Rails projects, my Linux system configuration, and even this blog!
In my web development work, I like to automate as much as possible with BASH shell and Ruby scripts. This makes my work easier by replacing repetitive tasks with simple commands and reduces the instances of certain classes of mistakes in my daily workflow. One of those mistakes that I would like to avoid is accidentally publishing a draft post to the live website.
**Here is how I use the value of the current Git branch to keep from accidentally publishing a post to the real website before it is ready! **
The software that is used to power the blog and website here is Octopress, which is a blogging framework built on top of Jekyll, the static site compiler. The site compiler is in Ruby, but unlike a Rails application that runs on the server, in Octopress all of the Ruby code runs on my local computer and the resulting statically compiled HTML, CSS, and other assets are uploaded to the server! It’s the ultimate form of caching!
Managing the site with Git
Since the entire website is managed in Git repository locally, the typical publishing pattern involves creating a feature branch for the post, writing the post, merging the finished post back into the master branch, and publishing the updated blog with rsync. Then as a final step, the local feature branch can be deleted to keep the repo nice and tidy.
When there are multiple branches in a project, running git branch
returns something like this:
2013
2014
* bashbranch
development
master
The current branch is indicated with a asterisk in the output. In this case it is bashbranch
, which is the feature branch I am using to write this post!
By convention, the master
branch represents the ready-for-production version of the website. The other branches are snapshots in time or works in progress that are not yet merged back into the master branch.
Next, I will show how to get the current branch into a variable in BASH.
Loading the current branch name into a variable
The next step is to load the string on the line with the asterisk in the git branch
output into a variable in a shell script.
This can be accomplished in several ways, but one way is by using sed
with a regular expression like this:
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
Go ahead and run that in your terminal with one of your own Git repositories. It should not output anything, because the value is loaded silently into the $branch
variable.
Now to echo the value, run echo $branch
.
In my terminal, that outputs ‘bashbranch’, so I know that it works in this case!
I first learned this trick from the answer by wich on a 2010 Stackoverflow thread that asked how to get the name of the current git branch into a variable in a shell script? It’s worth a read as there are other possible ways to get the data.
Creating a safer publish script
To speed up the publishing process, I have a BASH script called publish.sh
that generates the site and syncs it up to the remote server via rsync
over SSH
.
To ensure that I do not accidentally push an unfinished blog post up to the server, I use the new $branch
variable with a scripted branch instruction (an if
/else
block). It reads as follows:
#!/bin/bash
START_TIME=$SECONDS
# Get the name of the current Git branch and then ensure that only
# the master Git branch is deployable to production by this script.
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
# Only push this update to the server if the current branch is the Master branch
if [ "$branch" == "master" ]
then
echo "Compiling and deploying $branch to production..."
rake generate
rsync -avz public/ mywebsite@myserver.example.com:~/httpdocs/
ELAPSED_TIME=$(($SECONDS - $START_TIME))
echo "\nFinished in $ELAPSED_TIME seconds.\n\n"
else
echo "Will not publish from a branch other than master to production.\nPlease merge your changes into master and try again.\n\n"
fi
Now, when I am ready to push new content to the live website, I just run sh publish.sh
. If I run this accidentally from a draft branch, I am told that:
Will not publish from a branch other than master to production.
Please merge your changes into master and try again.
On the other hand, if I am in the master branch, it runs the build and I see something like this:
...
sent 58726 bytes received 153222 bytes 22310.32 bytes/sec
total size is 18654252 speedup is 88.01
Finished in 34 seconds.
Conclusion
Git is a wonderful tool for managing all sorts of projects, especially your own website! I really like using a static site compiler for blogging rather than depending upon a database-driven dynamic blog engine, such as WordPress.
By taking a few simple steps to practice a good Git workflow and having a publish script that automatically ensures that I am not accidentally publishing a work in progress draft to the live website, I can enjoy focusing on writing in my favorite text editor and easily publish with a few commands.
Further reading
- Stack Overflow: How to get the name of the current git branch into a variable in a shell script?
- Advanced Bash-Scripting Guide: 7.3. Other Comparison Operators
- Advanced Bash-Scripting Guide: 11.4. Testing and Branching
- The Geek Stuff: 4 Bash If Statement Examples ( If then fi, If then else fi, If elif else fi, Nested if )
- More Examples of Branching
- Advanced Bash-Scripting Guide: 9.1. Internal Variables
- Explains that
$SECONDS
returns ‘the number of seconds the script has been running.’
- Explains that
- Atlassian: Survey the most common Git workflows for enterprise teams