How to Rollback Homebrew Update

How to rollback brew updateIf you use Homebrew to install software on macOS, you may notice that Homebrew may perform version upgrade prior to installing the software. If you wonder why, deep inside the core logic of brew, the main command line tool of Homebrew, there is a subroutine to perform automatic update when brew detects that the version installed on your machine is older than the latest available version. The automatic update is not usually a problem when your machine runs on latest macOS version. For older versions of macOS, however, automatic brew update can break things including brew itself. In the event that brew stops working after unexpected update, is it possible to rollback the update? In this article, we will show you how to undo brew update and bring back your system to the last working configuration.

How Homebrew Works

Homebrew is a popular open source software distribution tool for macOS. If you develop on macOS, there’s big chance that Homebrew is already part of your workflow. If you are new to Homebrew, it’s worth taking some time to familiarize with the beer-themed terminologies used by Homebrew.

Homebrew provides a versatile command line tool named brew that can execute installation, removal, and upgrade process for numerous software packages, modules, and libraries on macOS. To install an executable or library, you simply execute brew install <software-name> command on the terminal. Homebrew will then handle the rest of installation process for you, whether by installing from a prebuilt package or building the executable or library from source.

Let’s say that you want to install Node.js by using Homebrew. You will invoke the command brew install node. How does Homebrew decide the Node.js version to install? The secret is Homebrew formula, a specification file written in Ruby that consists of instruction sequences to be executed by brew when a user invokes certain brew command. For Node.js, Homebrew has node.rb formula file that is referenced when it installs Node.js on your system. As of February 2026, executing brew install node on the terminal will install Node.js 25. If you want to install other versions, let’s say Node.js 22, you will then invoke brew install node@22 command. This means that there is a separate node@22.rb formula file that is referenced by Homebrew when installing Node.js 22 on your system.

Homebrew formula files are stored in a formula repository. Version control is enabled for the repository through git. When you invoke brew install command for the first time to install certain software, it will fetch the most updated formula for the software from the repository. Since the repository runs on git, what brew does in the background is basically checking out the HEAD version of the formula repository. This way, it gets the latest version of formula file that will then be referenced when installing the target software.

Homebrew can also install GUI applications, such as Chrome, GIMP, or others. To install a GUI application, brew will read a similar file-based specification that’s named cask. A cask file is a Ruby file that contains the location of the GUI application installer (.dmg file) and the necessary instruction sequences for brew command line tool to install the GUI application into the /Applications folder without having to run the GUI installation wizard. The cask files are stored in a separate repository that’s different from the formula repository. The cask repository also runs version control through git.

In summary, Homebrew consists of three main components: brew command line tool, formula repository, and cask repository. All of these components run version control through git. The repositories for those three components are as follows:

  • brew: The git repository for brew command line tool
  • homebrew-core: The git repository for formulae files and pre-built binary packages
  • homebrew-cask: The git repository for cask files

What Triggers Automatic Homebrew Update

When you execute brew install command, Homebrew will perform automatic update. It will first check if the brew command line tool is the latest version. It will then fetch the latest HEAD state of brew repository and update the command line tool if it finds that the local version is outdated. Subsequently, it will check the latest state of formula repository by fetching the HEAD state of homebrew-core repository. If the install command is to install GUI application, it will check the latest state of cask repository by fetching the HEAD state of homebrew-cask repository.

Besides brew install command, there are other commands that will trigger automatic update as shown in the snippet of Library/Homebrew/brew.sh file below:

...
# Check for commands that should call `brew update --auto-update` first.
AUTO_UPDATE_COMMANDS=(
  install
  outdated
  upgrade
  bundle
  release
)
if check-array-membership "${HOMEBREW_COMMAND}" "${AUTO_UPDATE_COMMANDS[@]}" ||
   [[ "${HOMEBREW_COMMAND}" == "tap" && "${HOMEBREW_ARG_COUNT}" -gt 1 ]]
then
  export HOMEBREW_AUTO_UPDATE_COMMAND="1"
fi
...

As you can see in the snippet above, invoking brew installbrew outdatedbrew upgradebrew bundle, and brew release will trigger automatic update by default. Additionally, brew tap command will also run automatic update.

Let’s say you haven’t touched brew for a while so that your local Homebrew version is older than the repository version. On a fine day, you want to install Python 3.14 by invoking command brew install python@3.14. After pressing enter, you will see this message on the terminal output:

==> Updating Homebrew...

When you see the message, there is very high probability that your local brew version has been updated to the latest version in brew repository without you explicitly instructing the update. For the case that your machine runs on older macOS version, like macOS 10.x, you will notice that brew has now stopped working as shown in sample error message for macOS 10.13 High Sierra below:

==> Updating Homebrew...
ERROR: Your version of macOS (10.13.6) is too old to run Homebrew!
         For 10.5 - 10.13.6 support see: https://www.macports.org

ERROR: Your version of macOS (10.13.6) is too old to run Homebrew!
         For 10.5 - 10.13.6 support see: https://www.macports.org

==> Downloading https://ghcr.io/v2/homebrew/core/portable-ruby/blobs/sha256:80c194381e990a4967a1ae44b8242b688e6a17ab590865a38671137677411469
######################################################################## 100.0%
==> Pouring portable-ruby-3.4.8.catalina.bottle.tar.gz
dyld: lazy symbol binding failed: Symbol not found: ____chkstk_darwin
  Referenced from: /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/./3.4.8/bin/ruby (which was built for Mac OS X 10.15)
  Expected in: /usr/lib/libSystem.B.dylib

dyld: Symbol not found: ____chkstk_darwin
  Referenced from: /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/./3.4.8/bin/ruby (which was built for Mac OS X 10.15)
  Expected in: /usr/lib/libSystem.B.dylib

/usr/local/Homebrew/Library/Homebrew/cmd/vendor-install.sh: line 239:  8657 Abort trap: 6           "./${VENDOR_VERSION}/bin/${VENDOR_NAME}" --version > /dev/null
Error: Failed to install ruby 3.4.8!
Error: Failed to upgrade Homebrew Portable Ruby!

How can we rollback and get back to the previous state of working brew?

How to Prevent Automatic Homebrew Update

Before you invoke any of brew commands that triggers automatic update, perform these steps to prevent automatic update and also to give you the ability to rollback undesired brew update.

1. Set HOMEBREW_NO_AUTO_UPDATE to true.

HOMEBREW_NO_AUTO_UPDATE is a special flag that instructs brew to skip automatic update when a user invokes a command that by default will trigger automatic update. To set this flag, type this command on your terminal:

$ export HOMEBREW_NO_AUTO_UPDATE=1

Note that this flag will only be recognized in current terminal session. If you open a new terminal, the flag will not exist. To persist the flag, append the command to your ~/.bashrc file.

2. (Optional) Set HOMEBREW_NO_INSTALL_FROM_API to true

HOMEBREW_NO_INSTALL_FROM_API is a special flag that instructs brew to avoid downloading pre-built binary package (bottle file) from the package repository. Instead, brew will try to build the software you want to install from source. You only need to set this flag when you observe that the binary package downloaded by brew failed to be installed on your machine. To set this flag, type this command on your terminal:

$ export HOMEBREW_NO_INSTALL_FROM_API=1

3. Get the brew version running on your machine

You need to get the brew version running on your machine for recovery purpose.

$ brew version

4. Get current brew configuration.

You need to get the current brew configuration for recovery purpose.

$ brew config

How to Rollback Homebrew Update

It is actually difficult to rollback brew update if you don’t know the last working configuration. For that case, there is a high chance that you will have to restore from Time Machine. When you know the last working configuration, however, you should be able to rollback the update successfully.

To enable you to rollback an undesired Homebrew update, perform these steps:

1. Keep the information about your current brew version

You can get the Homebrew version running on your machine through brew version command.

$ brew version

Sample output as a reference:

Homebrew 4.4.22
Homebrew/homebrew-core (git revision 8f3f0995f36; last commit 2026-01-13)
Homebrew/homebrew-cask (git revision ede7374549e; last commit 2026-01-13)

2. Keep the information about your current brew configuration

You can get the Homebrew configuration for your machine through brew version command.

$ brew config

Sample output as a reference:

HOMEBREW_VERSION: 4.4.22-97-g42cbf27
ORIGIN: https://github.com/Homebrew/brew
HEAD: 42cbf27fca9b5c1e045f65543958e614933b9196
Last commit: 12 months ago
Branch: HEAD
Core tap HEAD: 2cf9064aca640979de31d241e91c53a0349e550c
Core tap last commit: 12 months ago
Core tap JSON: 06 Feb 02:11 UTC
Core cask tap HEAD: ede7374549e33f2502edd6b2cef80bad612609ee
Core cask tap last commit: 4 weeks ago
Core cask tap branch: main
Core cask tap JSON: 06 Feb 02:11 UTC
HOMEBREW_PREFIX: /usr/local
HOMEBREW_CASK_OPTS: []
HOMEBREW_MAKE_JOBS: 8
HOMEBREW_NO_AUTO_UPDATE: set
HOMEBREW_NO_INSTALL_FROM_API: set
HOMEBREW_SORBET_RUNTIME: set
Homebrew Ruby: 3.3.7 => /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/3.3.7/bin/ruby
CPU: octa-core 64-bit haswell
Clang: 10.0.0 build 1000
Git: 2.17.2 => /Applications/Xcode.app/Contents/Developer/usr/bin/git
Curl: 7.54.0 => /usr/bin/curl
macOS: 10.13.6-x86_64
CLT: 10.1.0.0.1.1539992718
Xcode: 10.1

3. Perform software installation through brew install command.

4. If the installation results in failure and you have to rollback, perform rollback process as follows:

\a. Create a temporary variable named HOMEBREW_PREFIX for your current terminal session and assign value based on the output of brew config

$ export HOMEBREW_PREFIX=/usr/local

\b. Rollback brew repository to the latest working version for your machine.

– Go to brew project root directory

$ cd "${HOMEBREW_PREFIX}/Homebrew"

– Rollback the version based on “HEAD” value seen in the output of brew config command.

For the example config, this command will be executed as follows:

$ git reset 42cbf27fca9b5c1e045f65543958e614933b9196

c. Rollback homebrew-core repository to the latest working version for your machine.

– Go to homebrew-core project root directory

$ cd "${HOMEBREW_PREFIX}/Homebrew/Library/Taps/homebrew/homebrew-core"

– Stash existing change to the homebrew-core repository so that you can safely roll back.

$ git stash

– Rollback the version based on “Core tap HEAD” value seen in the output of brew config command.

For the example config, this command will be executed as follows:

$ git reset --hard 2cf9064aca640979de31d241e91c53a0349e550c

d. (Optional) Rollback homebrew-cask repository to the latest working version for your machine.

– Go to homebrew-cask project root directory

$ cd "${HOMEBREW_PREFIX}/Homebrew/Library/Taps/homebrew/homebrew-cask"

– Rollback the version based on “Core cask tap HEAD” value seen in the output of brew config command.

For the example config, this command will be executed as follows:

$ git reset --hard ede7374549e33f2502edd6b2cef80bad612609ee

5. Check that brew has been rolled back to the last working state

Perform another check to confirm that brew version has been downgraded.

$ brew version

You should see that your brew version has been reverted back to the same version before you invoke brew config command.

After getting brew rolled back to the previous version, you can then reinstall the software that breaks in your latest install.

Leave a Reply

Your email address will not be published. Required fields are marked *