Why? I have my system config source controlled and even have a bootstrap script to set up a new Mac from scratch that installs Homebrew, which installs git and Python, and then installs via Homebrew all my system packages and casks like Google Chrome, iTerm2, Spotify, etc. plus programming language packages through their respective package managers, etc. And now fonts (which I only discovered the tap for a little while ago). That's one less thing to install/update manually and it's very appreciated.
Not often, but I'm a software dev, I like things to be reproducible. So I always install everything through "setup brew" ('setup' is my program), and then the only part of my setup that is particular to a new machine is my bootstrap, which is like 30 lines of code:
Also, ever set up a new machine and then for days you keep finding system config that's not how you like, or things that aren't installed that should be? I even set my Mac's settings (defaults write ...) through my setup program. I started a new job fairly recently and my system was up and how I like it in one step.
As a mostly exclusive user of GNU+Linux for the past 9 years who started using a Mac last year because it was issued to me by my employer:
because Homebrew lacks many of the strengths of the kinds of package managers you find in the Linux ecosystem.
It only half-installs some packages, leaving you to manually link things in to certain directories (it was like this with Varnish a few months ago, and maybe still is). It's generally nondeterministic. Huge parts of it are basically scripted installation of preexisting binary packages, putting it more on par with Chocolatey or yaourt than a tool like apt backed by proper repos with source packages.
More on the topic of fonts in particular, there are tons of reasons that Apple's font handling, especially but not only in terms of installation and configuration management, is an embarrassment. macOS lacks configurable font substitutions, so extended characters like those provided in the ‘nerd fonts’ can only appear in applications which can be explicitly configured to use those fonts. Certain fonts are considered ‘required’ parts of the system, so that to modify or remove them on a Mac you have to disable System Integrity Protection, and a whole host of apps will simply crash on startup if, e.g., the Apple Color Emoji font is missing. macOS ignores emoji embedded in fonts that the user has chosen, and instead always injects the Apple emoji. Font rendering in macOS and iOS has been the source of numerous crashing and freezing issues of such a similar kind to one another that it is somewhat surprising and interesting that the entire class of such bugs wasn't fixed after the first major incident (as has been discussed on Hacker News recently).
Homebrew is also basically incapable of reliable uninstallation of packages; common advice is to use separate prefixes or wipe your whole installation with a series of commands that force you to reckon with the internal structure of Homebrew. It's not always compatible with other package managers for macOS, so care has to be taken if multiple alternatives are supposed to be usable. The state of Homebrew installations is so frequently a broken one that they have a dedicated subcommand for trying to figure out why Homebrew is broken in `brew doctor`, and sometimes breakages are caused by updates to macOS itself, which are installed via a separate mechanism.
And even when it works, Homebrew is essentially still always operating on fundamentally two distinct kinds of packages (traditional source-based installations in the FHS and macOS-specific `.app` bundles), whose difference is noticed and felt by every user because different subcommands are used for handling such packages, and they end up in different places.
I'd imagine, too, that the fact you had to write your own bootstrap script could be part of what the parent poster was getting at, in that Linux has a ton of choices for configuration management tooling due to its presence on the server.
Homebrew is an awesome effort, and I use it whenever Nixpkgs is missing something I don't feel like packaging myself. The casks are really nice because almost every end-user application on macOS is distributed as a DMG archive that extracts to a .app folder, so there are not as many applications one must use a browser to hunt for as there are on Windows.
I wouldn't want to mock macOS users over this, nor to disparage all of the useful and impressive work that Homebrew contributors have done in retrofitting macOS with a package manager which can do a lot. And to the extent that a bootstrapping script based on tools like Homebrew gets its job done, it is a success in its own right. But Homebrew offers nowhere near the control, speed, or basic featureset of something like apt, Portage, Nix, or zypper. And it's not integrated into the system like the native package manager is on any Linux distro. There's a lot for Linux users to miss from their old package managers when they're using Homebrew on macOS. And the font situation on macOS is a controlling, user-hostile travesty to anyone who expects their OS to do what they tell it rather than the other way around, and disconcertingly coupled with core system components besides.
tl;dr: Homebrew is a great project, but habitual Linux users on macOS know there's no place like home when it comes to package management (or font configuration, for that matter)
Generally everything you're saying about Linux package management vs Homebrew is the opposite of my experience. A coworker uses Linux for his machine and apt's packages always seem out of date or he has problems installing things, whereas Homebrew always just works.
I get what you're saying about source installs and so on, but these seem like more philosophical issues, since Homebrew just works and I install pretty much literally everything on my system through it, including full apps like Chrome, LibreOffice, etc.
> I'd imagine, too, that the fact you had to write your own bootstrap script could be part of what the parent poster was getting at
I'd have to do basically the same anyway. All the bootstrap script does is make sure Homebrew, git, and Python 3 are installed, checks out my repo, and then runs my setup program to set up everything.
> Generally everything you're saying about Linux package management vs Homebrew is the opposite of my experience. A coworker uses Linux for his machine and apt's packages always seem out of date or he has problems installing things, whereas Homebrew always just works.
A TALE OF TWO HOMEBREWS: the collection of build recipes (a.k.a the repos)
The second piece of Homebrew, which deserves to be compared to _distinct_ counterparts in the Linux world, is the ecosystem of homebrew-core, the taps provided by the community, and so on. In these respects, Homebrew is more comparable to a distribution's repositories than its package management tooling. Some Linux distributions are based on very up-to-date upstream sources, much like Homebrew. Nixpkgs, which is a collection of packages for the Nix package manager (usable on NixOS, GNU+Linux distros, and macOS) tends to have the same versions of packages as homebrew-core does— it's very up to date. But many Linux distros and users prefer to use older versions of software (which still receive security updates!) so that other users can suffer all the usual pains of early adoption, and work out some of the kinks for them. Some users just don't like dealing with frequent updates. Ubuntu is often used this way, with users recommending and installing the ‘long term service’ releases, which receive infrequent feature updates, but regular security updates. One unfortunate consequence of this strategy for gaining stability is that it can significantly complicate installing the latest releases of software, and that's what I suspect your friend has run up against.
Here, Homebrew is very similar to the repositories of many Linux distributions (like Arch, Gentoo, or perhaps even Debian Sid), and very dissimilar to others (CentOS, Red Hat Enterprise Linux, SUSE Linux Enterprise, Linux Mint, Ubuntu LTS releases), and I don't feel that there's a fact of the matter about which way of doing things is ‘better’. I will say, however, that Homebrew has a thriving, active, and friendly developer community who are constantly adding new packages, updating existing ones, and working to improve the quality of the packages in their repositories. Homebrew contributors and users should take pride in that.
> Generally everything you're saying about Linux package management vs Homebrew is the opposite of my experience. A coworker uses Linux for his machine and apt's packages always seem out of date or he has problems installing things, whereas Homebrew always just works.
A TALE OF TWO HOMEBREWS: the package management tools
As a technology or stack of technologies for building, installing, upgrading, and configuring software, Homebrew can be compared to package management systems on Linux distros. In my opinion, the package management system is the heart of a Linux distribution. Two distros are essentially interchangeable if they share repositories and a package manager; they're the same system twice, each time with a different desktop environment installed by default. And with a little courage and good ole apt, you can even convert from Ubuntu to Linux Mint! Here, I don't think Homebrew (in particular `brew`) stands up very well.
For example, Homebrew doesn't handle orphaned packages. When a package is installed, it drags in all its dependencies. But when the package is uninstalled, they are left behind. In the Linux world, different tools handle this problem differently. The `aptitude` command-line interface for apt tries to remove all orphaned dependencies every time you install, uninstall, or upgrade. Apt users (Debian, Ubuntu, Linux Mint, PopOS, all their remixes and many more) can also use `apt-get autoremove` to clean up any orphaned dependencies they may have left over. Gentoo users can remove orphaned dependencies with `emerge --depclean`. Fedora users can run `dnf autoremove`. NixOS and GuixSD have a garbage collector for packages.
By contrast, if you run `brew install cowsay` and then `brew uninstall cowsay`, everything that Homebrew installed just to put `cowsay` on your system is left behind. You're accruing ‘cruft’ with each package installation. And sometimes you might then find out that some package you were compiling got a different library version than you expected, and you can't for the life of you figure out why you even have that version of that library installed. It appears at a glance that Homebrew lacks any solution for removing orphaned dependencies after the fact, as with `apt autoremove`, but there is a third-party extension for removing hopefully-obsolete dependencies at uninstall time. It gives you a `brew rmtree` subcommand.
The first thing you'll notice on its GitHub page is a great big warning ( https://github.com/beeftornado/homebrew-rmtree#warning ). One thing this warning reveals is that Homebrew doesn't distinguish between packages that the user has chosen to install and packages that just happen to be present on the system. This is the reason that `brew rmtree` might remove command-line tools that you actually use-- because nothing _else_ you have installed depends on them, even though they're a package you explicitly told `brew` to install, because you wanted it. The author's workaround is a command-line flag `--ignore`, which allows you to list packages you want preserved, presumably after you notice that they got removed when you didn't want them to. The best user experience I can imagine for this feature is aliasing or wrapping the command with a list of your ‘preserved packages’, so that `brew rmtree` becomes safe to use with respect to them.
Not only is this not a problem with the package manager of any decent Linux distro, in addition to tracking which packages were installed on purpose (enabling the automatic removal of unused dependencies in a way that is actually safe to use), Linux package managers also offer a whole range of powerful and sensible tools for handling the trickier cases. On Sabayon Linux, for example, the Entropy package management system provides (vs. the `--ignore` flag on a third-party extension we get with Homebrew, one command-line argument you can use at install time only) a system of package masking, whereby one can specify ranges of versions, prohibit or require that particular packages be bleeding edge releases or that they come from the battle-tried stable repositories, and so on. On openSUSE, with `zypper`, each repository has a priority (they are all the same priority by default), which users can modify. By prioritizing your repositories, you can control the versions of specific pieces of software but still receive security updates. You can also pin packages at specific version or range of versions. In addition, Zypper associates each package with a `vendor`, to make better sense of choosing packages from different sources. This is really nice if, for example, you want your base system to be a stable distro release, but you want Firefox and all of its dependencies to come from a repository that houses the latest stable Firefox builds. At the same time, you may want to install the latest version of your favorite multimedia player, but retain the codecs from your base system, or a repository that ships codecs with the greatest compatibility. Many Linux distros provide excellent tools for easily managing things like this.
To return to Homebrew, on that side we have `brew pin`, which allows you to tell Homebrew not to automatically update a particular package along the way to doing other things you tell it to do in the future. For repository management, Homebrew has the tap system, which offers no real priority but a `brew tap pin` command whose documentation contains the following caveat:
‘Do note that pinned taps are prioritized only when the formula name is directly given by you, i.e. it will not influence formulae automatically installed as dependencies.’
so it does not effect a systemwide change (and presumably no mechanism for doing so is provided). Besides only affecting part of the system, the only function of `brew tap pin` is ‘to prioritize a tap over homebrew/core’ ( https://docs.brew.sh/Taps ). So we get no way to control the relative priorities of taps at all.
Linux distros have been hacking on their package management tools for ages and ages, as core components of entire operating systems. The tools are usually written in C and operate on little databases. They've equipped these systems to roll out configuration changes (after backing up the old ones), safely migrate users to equivalent packages when old forks die, stop and start services, optionally guide users through configuration, install bootloaders, recalculate font caches, tell the desktop environment to reindex its application shortcuts for search. And they do these things in ways that make it possible to disable the ‘hooks’ associated with these packages, (or re-run them whenever), and to lint these packages for all kinds of standards. Macros in the package definition formats make it possible for a single package definition to be usable for multiple Linux distributions, even including different operating system kernels. Homebrew only recently got ‘bottles’, which are a non-integrated mechanism of providing caches of prebuilt binaries for Homebrew's source-based packages; many Linux distros, on the other hand, have been distributing updates as compressed binary deltas between the currently installed version and the latest installed versions, for years.
Distros are working on deep, deep aspects of package quality, as well, in a way that I haven't seen as much outside of those projects. Debian, for example, has been doing a ton of work with upstream projects to make their builds deterministic, so that Debian packages can be built so reliably that one can usually expect bit-for-bit reproducibility. NixOS and GuixSD have pioneered and developed an approach to package management which draws upon the principles of functional programming in order to facilitate exhaustive, declarative configuration and provide guarantees portability, determinism, and the ability to roll back upgrades and installations at will. openSUSE builds every one of their packages by allocating a fresh, empty virtual machine and installing only the dependencies specified in the package, to make it impossible for their packages to have any missing, hidden, or broken dependencies.
And on Linux systems, package managers are tightly integrated into the system in a way that Homebrew will likely never be, not for any lack of expertise or effort on the part of Homebrew developers, but because the choice is ultimately not up to them. On a GNU+Linux system, the same package management tool is used for system upgrades as for application installation, and there's a lot of power, convenience, and predictability which comes from that.
Wow! This turned out really long. HN really wants me to split up these comments. Here is the very last of what I have to say in this reply (I promise!).
FULL APPS ARE ACTUALLY THE TRIVIAL PACKAGES, SOMEHOW
> I get what you're saying about source installs and so on, but these seem like more philosophical issues, since Homebrew just works and I install pretty much literally everything on my system through it, including full apps like Chrome, LibreOffice, etc.
On macOS, ‘full app’ installs are actually the easier part of what Homebrew offers. macOS applications are shipped with duplicates of all their shared libraries, so installing GUI applications doesn't require any kind of dependency management, unlike the source-based installations that Homebrew offers for command-line utilities and development libraries. This approach is the opposite of the traditional Linux package management approach. It's very convenient in some ways, and it can make installations more reliable for end-users in some cases. At the same time, bundling these dependencies can pose a security risk (since there's no central place to update insecure shared libraries), and causes applications to take up significantly more space.
Today, Linux distros are working on provide their own options options (such as Flatpak, Snappy, and AppImage) for application installation that provide many of the same virtues as the macOS ‘.app’ approach, along with better security/privacy/permissions control, and cross-distro compatibility. It will be interesting to see what balance of these tools Linux users end up using, but I think we'll be in a great position to have a base system built upon a robust, fine-grained, native package manager with good deduplication of shared resources and highly compatible app bundles à la macOS that we can use on top of and alongside that system.
I HAVE LITTLE TO SAY ABOUT YOUR SCRIPT BECAUSE IT SOUNDS PRETTY GOOD
> > I'd imagine, too, that the fact you had to write your own bootstrap script could be part of what the parent poster was getting at
> I'd have to do basically the same anyway. All the bootstrap script does is make sure Homebrew, git, and Python 3 are installed, checks out my repo, and then runs my setup program to set up everything.
Sounds like a pretty clean script. :-)
SOME NICE THINGS ABOUT HOMEBREW
Because most of the comparison I've made between Homebrew and various elements of the whole range of package management tools available as core system components in the world of free operating systems, I'd like to include some words about what Homebrew does exceptionally well. I've already mentioned one of Homebrew's strengths, which is the high rate of activity, frequent updates, and the wide and growing range of packages available. But that is not the only area in which Homebrew excels.
When it comes to user interfaces among package managers, `brew` is a decisive leader. The subcommand interface is a thing of beauty. The emoji in the output are a delightful touch. Homebrew's facilities for opening a package definition in an editor directly from a `brew` command are a killer feature, and so is the ability to specify a version (including HEAD from source control!) at install time, directly from the CLI, is a killer feature.
By integrating the Cask and Tap systems into the same command-line tool as everything else, `brew` is also one of the best tools in terms of user experience for managing repositories in simple use cases. Some of my favorite package managers from the Linux world are still catching up with these UX features.
NO TLDR FOR YOU
I can't really summarize what I wrote in a sentence or two, because it was mostly a bunch of examples. But here is the message:
I hope that Hombrew continues to grow and succeed. I also hope it is clear how Homebrew lacks many of the strengths of what are, to my mind, ‘traditional’ package managers.
————
Sorry it took me so long to finish this reply! It has been fun writing it, but I started it late at night and had to split it into two sessions with a couple of days. I have not read through all of it twice, so there may be some typos, inaccuracies, or things I've left out. Please reply with them instead of or inaddition to downvoting me. :-D
And for anyone who cares, I'm not really happy with the downvotes it seems that kbd here has received for their reply. Their account of their experience is perfectly believable and legitimate. I think there are some things they don't see about Linux distro package managers, so I've tried to share them here. But what they said is not wrong and hardly can be— it's an account of personal experience!
————
To kbd: Sorry if much of what I've gone over in this comment is redundant for you. I started out just writing a reply addressed more directly to you, but got caught up in a broader message that emerged from what I was saying. Please don't be offended if some of what I've written includes things you already know, or seems to wander off the topic you started us on.
Why? I have my system config source controlled and even have a bootstrap script to set up a new Mac from scratch that installs Homebrew, which installs git and Python, and then installs via Homebrew all my system packages and casks like Google Chrome, iTerm2, Spotify, etc. plus programming language packages through their respective package managers, etc. And now fonts (which I only discovered the tap for a little while ago). That's one less thing to install/update manually and it's very appreciated.