Installing a specific version of a homebrew package

When developing for the web, I like to make sure that the software I'm using in development is a close match for the code that I'm running on my live servers.

My preferred approach is to develop my code in a virtual machine containing the same operating system and software as my production server environment, but sometimes we don't have much control over the code we run on the server. This is often the case when hosting apps on a PaaS (Platform as a Service) provider such as Heroku.

I develop Agile Planner on a Mac, and install software required by my app (such as PostgreSQL, memcached and Elasticsearch) using the homebrew package manager.

Packages in homebrew are typically updated to provide the latest version of an app, which means that you can find yourself running more recent versions of your software in development, than in production.

It's useful to be able to install a specific version.

It's easy to do with homebrew.

Installing from a tap

If a lot of people might need to use an old version of a package (or "formula", in homebrew's terminology), it might have been made available as a tap. Old versions are maintained in the homebrew-versions repository, and show up in the output of homebrew search:

$ brew search elasticsearch
elasticsearch
homebrew/versions/elasticsearch-0.20        homebrew/versions/elasticsearch090          homebrew/versions/elasticsearch11

The first line of output refers to the default package, while the following line refers to the "tapped" versions that are also available. You can install one of them like this:

$ brew install homebrew/versions/elasticsearch11

In my case, the version I'm looking for (version 1.2.1) isn't available as a tap, so I need an alternative approach.

Installing from a specific commit

The homebrew formulae (that tells the brew command how to build each package) are all stored in a Git repository.

All we need to do is to roll back the formula for the package we want to build to the latest commit that was active for that package.

Up until around October 2014, Homebrew had a brew versions command that would list all the versions of a package, and the corresponding Git commands to roll the formula back.

If your version of homebrew is more recent than October 2014, you'll need to install the boneyard tap in order to make the command available:

$ brew tap homebrew/boneyard

Then you can run brew versions. Here's the first few lines of output for Elasticsearch:

$ brew versions elasticsearch
Warning: brew-versions is unsupported and will be removed soon.
You should use the homebrew-versions tap instead:
  https://github.com/Homebrew/homebrew-versions

1.3.2    git checkout 55c1ef3 /usr/local/Library/Formula/elasticsearch.rb
1.3.1    git checkout f19e447 /usr/local/Library/Formula/elasticsearch.rb
1.3.0    git checkout afe760c /usr/local/Library/Formula/elasticsearch.rb
1.2.2    git checkout 97e96ed /usr/local/Library/Formula/elasticsearch.rb
1.2.1    git checkout 3bbd4f1 /usr/local/Library/Formula/elasticsearch.rb
1.2.0    git checkout 53d3a63 /usr/local/Library/Formula/elasticsearch.rb

There's more information on the brew versions command in this StackOverflow answer, so if at some point in the future you find that this blog post seems to be out of date, try that.

So anyway, back to installing Elasticsearch. I need version 1.2.1, so I'll pipe the versions command through grep and then run the Git command:

$ brew versions elasticsearch | grep 1.2.1
  1.2.1    git checkout 3bbd4f1 /usr/local/Library/Formula/elasticsearch.rb
$ cd /usr/local/Library
$ git checkout 3bbd4f1 /usr/local/Library/Formula/elasticsearch.rb
$ brew install elasticsearch

If you've already got a version of the package you're building installed, you might need to unlink it before installing it:

$ brew unlink elasticsearch
$ brew install elasticsearch