since 1999

 

5 minutes estimated reading time.

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