Using Brewfile to Share Homebrew Configs across machines
- coding, version control
- 2024-05-14
- 4 minutes to read
- dotfiles
- homebrew
- brewfile
Table of Contents
Introduction
I am making use of a variation of dotfiles to manage my configuration files. One of the tools I use is Homebrew, a package manager for macOS. I wanted to find a way to share my Homebrew configuration with others. I found that I could use a Brewfile to do this.
What is Brewfile?
Brewfile manages packages installed by Homebrew. It also supports brew-cask and other Homebrew subcommand installers.
What are dotfiles?
Dotfiles are hidden files in your home directory that typically contain configuration settings for applications. They are called dotfiles because their filenames begin with a dot (period). I have been using a version control process to track multiple dotfiles and share them between different machines. Homebrew config isn’t exposed by default in a dotfile and so I have inconsistent Homebrew configurations across my machines.
Install brewfile
Run the following command to install brewfile:
brew install rcmdnk/file/brew-file
Then add the following lines to your .bashrc
or .zshrc
file (or both):
if [ -f $(brew --prefix)/etc/brew-wrap ];then
source $(brew --prefix)/etc/brew-wrap
fi
Brew wrap is a wrapper script for Homebrew commands. The idea being that when you run a Homebrew (un)install command, it will also update the Brewfile.
Export the Brewfile
Reload your shell and initialise brewfile:
brew init
This will review the installed packages, then output a brewfile to the default location of ~/.config/brewfile/Brewfile
. With my Homebrew config stored as a dotfile, I can now commit it to my dotfiles repository and share with my other machines.
Update a new machine
Assuming machineB has a fresh install of Homebrew, you can use the brewfile to install the same configuration as your original machine (machineA) by running the following command:
brew file install
This will load the config from machineA and install all the packages listed in the brewfile on machineB.
Update an existing machine
Whilst brew file install
will install the packages listed in the brewfile it doesn’t take into account consolidating packages that have already been installed on the existing machine (machineC). There are two options here:
- bring machineC in line with machineA
- consolidate the config of machineA and machineC
If you want to bring machineC in line with machineA, you can run the following command:
brew file update
This will grab the config of machineA, then install any missing packages and remove any packages that are not listed in the brewfile.
If you want to consolidate configs, it gets a bit more complicated. Assuming that you are using version control, currently the config of machineA will be tracked. By running brew file init
on machineC, the config present on machineC will be pushed to the brewfile and will be tracked by git. You can then use git diff to evaluate the differences between the two configs and decide upon your consolidated config.
In the screenshot above, the left hand side is the config from machineA and the right hand side is the config from machineC. Having run the brew file init
command on machineC, the config of machineC is now being tracked by git and you can see that neither zoom or vlc are installed on machineC. I can then decide whether to bring those changes into the consolidated config or leave them out.
Review the brewfile
If you want to review the brewfile, you can run the following command:
brew file cat
# tap repositories and their packages
tap homebrew/core
brew aom
brew azure-cli
brew brotli
brew c-ares
brew ca-certificates
brew cairo
brew cascadia
brew cask
... ## clipped for brevity
Conclusion
I have found Brewfile to be a useful tool for producing a dotfile, which allows me to share my Homebrew configuration between machines. It is a simple process to export the brewfile and commit it to my dotfiles repository. I can then load the brewfile on my other machines and have a consistent Homebrew configuration across all of them.