Homebrew install specific version of formula?

Viewed 1636969

How do I install a specific version of a formula in homebrew? For example, postgresql-8.4.4 instead of the latest 9.0.

33 Answers

Simple Workflow

Now that Homebrew/versions has been deprecated, Homebrew/core supports a few versions of formulae with a new naming format.

To install a specific version, e.g. postgresql 9.5 you simply run:

$ brew install postgresql@9.5

To list the available versions run a search with @:

$ brew search postgresql@
==> Searching local taps...
postgresql@10.1 ✔     postgresql@9.4        postgresql@9.5        postgresql@9.6

Solution

brew extract --version=8.4p1  openssh homebrew/cask
brew install openssh@8.4p1

The newest openssl@8.5p1 has bugs after I run brew upgrade, so I backed to the previous version successfully via the above way.

Most of the other answers are obsolete by now. Unfortunately Homebrew still doesn’t have a builtin way of installing an outdated version, unless that version exists as a separate formula (e.g. python@2, postgresql@9.4 …).

Luckily, for other formulas there’s a much easier way than the convoluted mess that used to be necessary. Here are the full instructions:

  1. Search for the correct version in the logs:

    brew log formula
    # Scroll down/up with j/k or the arrow keys
    # or use eg. /4\.4\.23 to search a specific version
    
    # This syntax only works on pre-2.0 Homebrew versions
    brew log --format=format:%H\ %s -F --grep=‹version› ‹formula›
    

    This will show a list of commit hashes. Take one that is appropriate (mostly it should be pretty obvious, and usually is the most recent (i.e. top) one.

  2. Find the URL at which the formula resides in the upstream repository:

    brew info ‹formula› | grep ^From:
    
  3. Fix the URL:

    1. Replace github.com with raw.githubusercontent.com
    2. Replace blob/master with the commit hash we found in the first step.
  4. Install the desired version by replacing master in the previously found URL by the commit hash, e.g.:

    brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/‹hash›/Formula/‹formula›.rb
    

(The last step may necessitate running brew unlink ‹formula› before.)


If you have copied a commit hash you want to use, you can use something like this example to install that version, replacing the value and bash with your commit hash and your desired formula.

BREW_VERSION_SHA=32353d2286f850fd965e0a48bcf692b83a6e9a41
BREW_FORMULA_NAME=bash
brew info $BREW_FORMULA_NAME \
| sed -n \
    -e '/^From: /s///' \
    -e 's/github.com/raw.githubusercontent.com/' \
    -e 's%blob/%%' \
    -e "s/master/$BREW_VERSION_SHA/p" \
| xargs brew install

This example is installing bash 4.4.23 instead of bash 5, though if you performed a brew upgrade afterward then bash 5 would get installed over top, unless you first executed brew pin bash. Instead to make this smoother WITHOUT pinning, you should first install the latest with brew install bash, then brew unlink bash, then install the older version you want per the script above, and then use brew switch bash 4.4.23 to set up the symlinks to the older version. Now a brew upgrade shouldn't affect your version of Bash. You can brew switch bash to get a list of the versions available to switch to.


Alternative using a custom local-only tap

Another way of achieving the same goal appears to be:

brew tap-new username/repo-name
# extract with a version seems to run a grep under the hood
brew extract --version='4.4.23' bash username/repo-name
brew install bash@4.4.23
# Note this "fails" when trying to grab a bottle for the package and seems to have
# some odd doubling of the version in that output, but this isn't fatal.

This creates a formula@version in your custom tap that you can install per the above example. The downside is that you probably still need to brew unlink bash and then brew link bash@4.4.23 in order to use your specific version of Bash or any other formula.

Official method ( judging from the response to https://github.com/Homebrew/brew/issues/6028 )

Unfortunately Homebrew still doesn’t have an obvious builtin way of installing an older version.

Luckily, for most formulas there’s a much easier way than the convoluted mess that used to be necessary. Here are the full instructions using bash as an example:

brew tap-new $USER/local-tap
# extract with a version seems to run a `git log --grep` under the hood
brew extract --version=4.4.23 bash $USER/local-tap
# Install your new version from the tap
brew install bash@4.4.23
# Note this "fails" trying to grab a bottle for the package and seems to have
# some odd doubling of the version in that output, but this isn't fatal.

This creates the formula@version in your custom tap that you can install per the above example. An important note is that you probably need to brew unlink bash if you had previously installed the default/latest version of the formula and then brew link bash@4.4.23 in order to use your specific version of Bash (or any other formula where you have latest and an older version installed).

A potential downside to this method is you can't easily switch back and forth between the versions because according to brew it is a "different formula".

If you want to be able to use brew switch $FORMULA $VERSION you should use the next method.


Scripted Method (Recommended)

This example shows installing the older bash 4.4.23, a useful example since the bash formula currently installs bash 5.

  • First install the latest version of the formula with brew install bash
  • then brew unlink bash
  • then install the older version you want per the snippets below
  • finally use brew switch bash 4.4.23 to set up the symlinks to your version

If you performed a brew upgrade after installing an older version without installing the latest first, then the latest would get installed clobbering your older version, unless you first executed brew pin bash.

The steps here AVOID pinning because it is easy to forget about and you might pin to a version that becomes insecure in the future (see Shellshock/etc). With this setup a brew upgrade shouldn't affect your version of Bash and you can always run brew switch bash to get a list of the versions available to switch to.

Copy and paste and edit the export lines from the code snippet below to update with your desired version and formula name, then copy and paste the rest as-is and it will use those variables to do the magic.

# This search syntax works with newer Homebrew
export BREW_FORMULA_SEARCH_VERSION=4.4.23 BREW_FORMULA_NAME=bash
# This will print any/all commits that match the version and formula name
git -C $(brew --repo homebrew/core) log \
--format=format:%H\ %s -F --all-match \
--grep=$BREW_FORMULA_SEARCH_VERSION --grep=$BREW_FORMULA_NAME

When you are certain the version exists in the formula, you can use the below:

# Gets only the latest Git commit SHA for the script further down
export BREW_FORMULA_VERSION_SHA=$(git -C $(brew --repo homebrew/core) log \
 --format=format:%H\ %s -F --all-match \
--grep=$BREW_FORMULA_SEARCH_VERSION --grep=$BREW_FORMULA_NAME | \
head -1 | awk '{print $1}')

Once you have exported the commit hash you want to use, you can use this to install that version of the package.

brew info $BREW_FORMULA_NAME \
| sed -n \
    -e '/^From: /s///' \
    -e 's/github.com/raw.githubusercontent.com/' \
    -e 's%blob/%%' \
    -e "s/master/$BREW_FORMULA_VERSION_SHA/p" \
| xargs brew install

Follow the directions in the formula output to put it into your PATH or set it as your default shell.

Upgraded Postgres by accident?

My case:

  • postgresql was upgraded from 11 to 12 accidentally (after running brew upgrade without arguments)
  • I want to keep Postgres 11.

Solution:

  1. Stop the DB:
brew services stop postgresql
  1. Install Postgres 11:
brew install postgresql@11
  1. Enable it:
brew link postgresql@11 --force
  1. (Optional) Rename DB data directory from postgres to postgres@11:
cd /usr/local/var
ls -lh
mv postgresql@11 postgresql@11-fresh-backup
mv postgres postgresql@11
  1. Start the DB:
brew services start postgresql@11

If you have any errors, check /usr/local/var/log/postgresql@11.log (notice the @11).

Homebrew changed recently. Things that used to work do not work anymore. The easiest way I found to work (January 2021), was to:

  • Find the .rb file for my software (first go to Formulas, find the one I need and then click "History"; for CMake, this is at https://github.com/Homebrew/homebrew-core/commits/master/Formula/cmake.rb)
    • Pick the desired version among the revisions, e.g. 3.18.4, click three dots in the top right corner of the .rb file diff (...) and then click Raw. Copy the URL.
  • Unlink the old version brew unlink cmake
  • Installing directly from the git URL does not work anymore (brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/2bf16397f163187ae5ac8be41ca7af25b5b2e2cc/Formula/cmake.rb will fail)
    • Instead, download it and install from a local file curl -O https://raw.githubusercontent.com/Homebrew/homebrew-core/2bf16397f163187ae5ac8be41ca7af25b5b2e2cc/Formula/cmake.rb && brew install ./cmake.rb

Voila! You can delete the downloaded .rb file now.

Edit: 2021, this answer is no longer functional due to the github install being deprecated. (Thanks Tim Smith for update).

Install an old brew package version (Flyway 4.2.0 example)

Find your local homebrew git dir or clone Homebrew/homebrew-core locally

cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/

OR

git clone git@github.com:Homebrew/homebrew-core.git

List all available versions

git log master -- Formula/flyway.rb

Copy the commit ID for the version you want and install it directly

brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/793abfa325531415184e1549836c982b39e89299/Formula/flyway.rb

I've tried most of the solutions here and they are outdated. I had to combine some ideas from here with my own work. As a result I've created a script to help me do the heavy lifting which you can find here

Usage:

brewv.sh formula_name desired_version

The other answers here are great, but if you need to install an older version of the package and ensure that the package name is modified, you'll need a different approach. This is important when using scripts (in my case, PHP build scripts) which use brew --prefix package_name to determine what directory to use for compilation.

If you are using brew extract a version is added to the end of the package name which will break the brew --prefix lookup.

Here's how to install an older package version while maintaining the original package name:

# uninstall the newer version of the package that you accidentally installed
brew uninstall --ignore-dependencies icu4c

# `extract` the version you'd like to install into a custom tap
brew tap-new $USER/local-tap
brew extract --version=68.2 icu4c $USER/local-tap

# jump into the new tap you created
cd $(brew --repository $USER/local-tap)/Formula

# rename the formula
mv icu4c@68.2.rb icu4c.rb

# change the name of the formula by removing "AT682" from the `class` definition
# the exact text you'll need to remove will be different
# depending on the version you extracted
nano icu4c.rb

# then, install this specific formula directly
brew install $(brew --repository $USER/local-tap)/Formula/icu4c.rb

I wrote more about this here.

None of the other answers cover this adequately for 2022, so I'm adding these instructions that are adapted from a Homebrew maintainer's answer for a similar question for installing a specific Cask version: https://stackoverflow.com/a/62765875/6310633

Uninstall your formula

brew uninstall <formula>

Switch over to your clone of the homebrew-core repo and reset to a commit containing the version you want.

cd "$(brew --prefix)/Library/Taps/homebrew/homebrew-core/Formula"
git log <formula>.rb # examine recent commits for <formula>
git reset --hard <commit-sha> # reset clone to last known-good commit for <formula>

Checkout a new branch for your version so brew won't autorefresh master after each command, install your formula, and pin it.

git checkout -b <formula>-downgrade-<version>
brew install <formula>
brew pin <formula>

Clean up

git checkout master
brew update

When you're ready to upgrade your formula, you can brew unpin <formula> and upgrade as usual.

Currently the old ways of installing specific formula versions have been deprecated. So it seems like we have to use brew edit [formula]. E.g. say we want to install an the 62.1 version of icu4c (needed e.g. for postgresql 10.5). Then you'd have to

> brew edit icu4c
# drops you to editor

Here you'd have to alter the url, version and sha256 (perhaps also mirror) to the corresponding 62.1 strings.

url "https://ssl.icu-project.org/files/icu4c/62.1/icu4c-62_1-src.tgz"
mirror "https://github.com/unicode-org/icu/releases/download/release-62-1/icu4c-62_1-src.tgz"
version "62.1"
sha256 "3dd9868d666350dda66a6e305eecde9d479fb70b30d5b55d78a1deffb97d5aa3"

then run brew reinstall icu4c to finally download the 62.1 version.

Here my simple answer for it - was really annoyed that there is no built in solution for that so I've built my own lazy "script". Feel free to contribute

# Please define variables
packageName=<packageName>
packageVersion=<packageVersion>

# Create a new tab
brew tap-new local/$packageName

# Extract into local tap
brew extract --version=$packageVersion $packageName local/$packageName

# Verify packages is present
brew search $packageName@

# Run brew install@version as usual
brew install local/$packageName/$packageName@$packageVersion

https://gist.github.com/ArgonQQ/cff4834dab6b254cc2140bb1454b47ef

I created a tool to ease the process prescribed in this answer.

To find a package pkg with version a.b.c, run:

$ brew-install-specific pkg@a.b.c

This will list commits on the pkg homebrew formula that mention the given version along with their GitHub urls.

Matching versions:
1. pkg: update a.b.c bottle.
   https://github.com/Homebrew/homebrew-core/commit/<COMMIT-SHA>
2. pkg: release a.b.c-beta
   https://github.com/Homebrew/homebrew-core/commit/<COMMIT-SHA>
3. pkg a.b.c
   https://github.com/Homebrew/homebrew-core/commit/<COMMIT-SHA>

Select index: 

Verify the commit from the given URL, and enter the index of the selected commit.

Select index: 2
Run:
  brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/<COMMIT-SHA>/Formula/pkg.rb

Copy and run the given command to install.

Here is how I downgrade KOPS (which does not support versioning)

# brew has a git repo on your localhost
cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core

git remote -v
origin  https://github.com/Homebrew/homebrew-core (fetch)
origin  https://github.com/Homebrew/homebrew-core (push)

# find the version of kops.rb you need
git log Formula/kops.rb

# checkout old commit
# kops: update 1.18.1 bottle.
git checkout 2f0ede7f27dfc074d5b5493894f3468f27cc73f0 -- Formula/kops.rb

brew unlink kops
brew install kops

# now we have old version installed
ls -1 /usr/local/Cellar/kops/
1.18.1
1.18.2

which kops
/usr/local/bin/kops
ls -l /usr/local/bin/kops
/usr/local/bin/kops -> ../Cellar/kops/1.18.1/bin/kops
kops version
Version 1.18.1

# revert to the newest version
brew uninstall kops
git checkout -f
brew link kops
kops version
Version 1.18.2

brew versions and brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/<COMMIT-HASH>/Formula/<Formula>.rb not supported now.

You can try like this:

$ brew extract --version 5.6.2 gradle vitahlin/core
$ brew install gradle@5.6.2
Related