At this point I should know better than to install postgres via homebrew, but unwanted/unasked-for upgrades is not a feature I'm looking for in a package manager.
What's your experience with other package managers for macOS? Currently looking into macports & nix and not sure which one to choose...
---
Homebrew upgrades dependencies and dependents of those dependencies (which, admittedly, can feel like unrelated) on installation and upgrade. As mentioned in other comments, you can customise this behaviour with `HOMEBREW_NO_INSTALL_UPGRADE` or `HOMEBREW_NO_AUTO_UPDATE`.
Homebrew does this because the alternative is sometimes breaking things. An example:
- you want to install `virtualenv` that depends on `python@3.10`
- the binary package for `virtualenv` you want requires the newest `python@3.10`
- this upgrades `python@3.10` on installation
Now, Homebrew has a choice. Either we upgrade _everything_ that depends on `python@3.10` that you have installed or we knowingly break some of the things you have installed that depend on `python@3.10`. We choose the safer option by default.
The more time left between updating/upgrading, the more likely to have more dependencies updated which requires more dependents to be updated.
---
Regardless, I appreciate this is a problem and we're still figuring out potential solutions for this problem. A reminder that we're a volunteer run project so it's not always as easy as we'd like it to be to get these changes out quickly.
1. Nix has very limited support for GUI applications of the kind that you'd find in `brew cask`. Not no support, some of them are there, but limited support compared to brew. If you use brew as an out-of-the-box install-everything setup like me, you'll not be able to replicate that easily with Nix.
2. Nix can't currently build Swift applications because of some Xcode something I didn't fully understand.
3. I found a small number of packages that are broken on Nix on my aarch64 / M1 MacBook Air (and marked broken, so when you try to install it complains) and a small number that are broken without being marked broken. In specific, I think R was one that surprised me -- this is a major programming language and although the build requirements are onerous (it's a mix of C and Fortran), I would think it would work.
That being said the actual process of installing, updating, and upgrading seems much faster and dramatically less shitty than homebrew, and so I recommend migrating stuff off of brew anyway.
You shouldn't use the system package manager on Ubuntu or Red Hat or whatever the way you're using Brew, either, unless you're exactly matched to your deployment target—same distro, same version, and you don't upgrade locally unless the servers are getting upgraded—and are scripting your local package installations and upgrades with the same script you use to deploy on the server.
I find it much faster now, which is quite funny to me because back when Homebrew was new (and a lot less opinionated) it was much faster than MacPorts, especially with the bottles (binary packages) feature.
Today, MacPorts has binary packages, doesn't randomly force incredibly slow updates when I just want to quickly install something or run a package search, has entirely opt-in telemetry through installing a package (mpstats) and still lets me customise packages (through the variants system, which is more powerful than the with --with-feature system Homebrew seems to have abandoned).
The only pain point I've found is upgrading to new macOS releases, though I've often found just reinstalling MacPorts itself will get me going again in a pinch without having to take inventory of my installed ports and reinstall everything from scratch.
Macports has this appearance of being 'dated', and not the cool kid compared to Homebrew. But it doesn't have an opinion on what version of software you can install. Want postgres 9.4? Go ahead and install it. Want some ancient version of some other library? That's fine.
Dealing with custom port files and repositories isn't quite as easy, I suppose, but that's not really much different to setting up a debian repo in that it's a use case you won't encounter nearly as often as just installing stuff.
I also used nixpkgs at one point, many moons ago. That was also nice but not the most practical on a Macbook with 128GB storage, when you also have Docker, npm/ruby dependencies, and your native Mac software in the mix.
Fortunately Homebrew has lots of helper scripts to upgrade DB’s like Postgres. You probably saw some scroll back with a command to upgrade from 12 to 13 or 13-14 etc. It will even download and install an old version in order to upgrade safely.
I understand the frustration but what is the alternative? Pinning every dependency? The reason so many of your packages were updated was likely because a core dependency was upgraded like OpenSSL.
It's confusing, but we'll get there. You'll need/want:
- nix, the tool/build system.
- nixpkgs, the world's most up-to-date and underfunded package repository.
- nix-darwin, bringing a NixOS experience to Darwin. Not perfect, but pretty damn great.
And optionally,
- home-manager, a nix-based opinionated tool to manage dotfiles and other stuff in your home directory.
And finally, some things to avoid and experimental features to use:
- do not ever use `nix env -i` to install things ala homebrew, apt, etc. This is a trap. You don't want this.
- use nix flakes. Sure, it's experimental, but it's what you _do_ want. Reproducible, version-pinned builds.
- if you use direnv, or are familiar with it, check out nix-direnv, which is like direnv on crack. Instead of managing your packages globally, manage them per workspace or project.
https://github.com/Homebrew/brew/blob/7d31a70373edae4d8e78d9...
Since then i moved to manage everything that needs to stay frozen by either a versioned formula/cask (python@3.9 and so on) or use brew to install a version manager (asdf,pyenv,pipx) and then use that. Results are much better once I did that
Although versioned casks/formula exists you will still get minor versions - python@3.9 will update from 3.9.0 to 3.9.1 is that ever exists. so while completely protecting you from upgrades it does minimize the the risk
Also, there is really no need to install virtualenv directly from brew. A very bad practice. Of course doesn't change the fact that brew did things that are unrelated to what you asked of it
I recommend using Nix alongside a couple other systems so you have escape hatches.
- Nix
- pkgsrc or MacPorts ‘just in case’ they're more convenient for some package for any reason
- Homebrew, exclusively to use for Casks (which are really a separate system from the rest of Homebrew)
To get the most out of Nix, you'll need to take some time to really learn it. For managing services like postgres, it's nicest to use Nix-Darwin (a module system for managing services and programs, including automatic startup via LaunchD) but if you want to always keep the same Postgres with Nix-Darwin, you'll have to learn how to pin packages.If you use Nix with Flakes, it'll feel a lot faster (much faster than Homebrew). If you use old-school Nix, it'll be slow if you call some deprecated commands.
For instance: arkade get kubectl@v1.22.1 yq helm faas-cli
It's not got anywhere near the catalog of brew, and doesn't compile software, or help you find lib-xyz for your Yubikey, but it is really fast and has a growing community behind it.
It works on MacOS, Linux, Windows and arm hosts to determine the correct download URL and pull in a binary.
[1] https://github.com/alexellis/arkade
Contributions are welcome.
If I had to use a Mac my solutions would be to alway use Docker, a virtual machine, or a remote dev environment of some kind.
Ports have a long history from the BSD Unices and Macports keeps that ethos. It installs neatly in /opt and doesn't screw around with MacOS except in the approved ways (eg for Java and Python frameworks).
I still use Macports and it's had everything I've needed and when I hit bugs during the Big Sur beta, they were fixed quickly and directly, while still complying with Apple's beta policies.
I've dabbled with Nix, but it's a bit too* prescriptive for me.
I've tried the nix.dev installation + nix-darwin instructions 4 or 5 times but never make it very far.
Seems like I should generally prefer a multi-user install? Does nix-darwin play well with that?
As I supposed to `sudo -i nix-channel --add / update` or not use sudo? Is unstable the generally recommended channel? Do I use sudo with nix-darwin, since it's supposed to be kind of like NixOS / system-wide?
And then I usually give up, count my blessings for homebrew, and resolve to never again waste another 2 days trying to figure out nix.
Rinse and repeat in 1 month.
Been running with homebrew for at least a decade since, and I cannot recall any negative encounter other than the hassle of grabbing xcode command line tools when I upgrade a major version of Mac OS, which is a minor detail.
I get the appeal of MacPorts & a dedicated separate package path but it caused all sorts of problems for me v. the integrated approach of homebrew.
O there was another negative now I remember -- had to uninstall brew version of MacVim & install manually. But that not a big issue either & typically, all of the brew packages are CLI only for me.
[1]: <https://rubenerd.com/using-netbsds-pkgsrc-everywhere-i-can/>
[2]: <https://news.ycombinator.com/item?id=27293108>
[3]: <http://www.pkgsrc.org/>
Even on a system like that, many times when I interact with package managers like conda, it ends up compiling some huge package from scratch. I consider that a failure.
I instructed you, brew to install something. Not to spend an eternity autoupdating things.
export HOMEBREW_NO_AUTO_UPDATE=1
in my zshnev so long ago that I forgot about it, and just enjoyed a great product from a great community.Is it a bad default? Sure, probably, spooky-action-at-a-distance is not great. But it's just a default, if you don't like it, change it, one line of shell config is simpler switching distros.
1. Python has built in virtual environment support. python -m venv should do the trick. 2. Use docker for running Postgres, MySQL etc with some directory mounted for data.
EDIT: Personal PC is running NixOS not Windows.
I don't want to have to keep updating brew just to keep from having to wait ever-increasing amounts of time when I want to install a new package or upgrade a specific one. I never have these issues with macports, and won't have them with nix.
Macports primarily for system level dep. use this whenever packages available.
Fall back to homebrew when not available on Macports. This includes brew cask which is unique.
This dual setup may requires you to carefully separating the 2 when installing and updating. I do this by installing brew in custom location (not /use/local) which is now the default on ARM. Also some shell functions that selectively control the environment (essentially I use an environment that only sees port to update port, vice versa.)
Lastly, conda for dev environments, mostly for Python stack. But it is also useful for other stuffs (conda is a cross platform package manager and in this sense it is similar to brew which also support Linux.) Obviously selections is not as broad comparing to brew.
On computing facilities, I used to use linuxbrew to install some “system” dependencies that’s missing, including zsh, mosh, tmux, tree, etc. But obviously I cannot install in the recommended path by brew, which means compiles from source. And it is not robust (and they also say this is not a supported pattern.) I now use conda for this and is very robust (conda uses a hack to install precompiled binaries to arbitrary prefix.)
Use Homebrew only for tools and not for critical services like databases and use a cloud server or local virtualization like VMware Fusion (which is free these days for personal use) to run services because major distro packages have far more eyes to check for stability issues.
I never understand people trying to run every parts of the development environment through a local machine's third party package managers which would forbid anyone else being able to check your work right then as you're only running it as localhost, not to mention the power can be down at any moment you're not using your machine and you can't even switch machine yourself to work from easily.
And then when deploying, you'll be running it on Linux anyway which would likely bring little consistency issues.
Do yourself a favor, either spend $5/mo for a cloud Linux and run your stuff remotely or run a locally virtualized Linux and stop using third party package managers no one is using to run on production.
And you can happily keep Homebrew and also install Homebrew on Linux to have unified tool sets on your Mac and Linux CLI tools.
Personally, I find that the whole Homebrew "theme" where every command/thing is named after something alcohol/brewing-related (cask, bottle, formulae, tap, keg, etc) is a huge turnoff.
I hate it, but Anaconda might work too, so long as it's not a corporate laptop where you need a license.
- Homebrew is rolling - always was and never claimed otherwise.
- OTOH for key packages (say databases) it has available versioned bottles. for postgresql one have:
- postgresql@10
- postgresql@12
- postgresql@9.4
- postgresql@9.6
- postgresql (points to latest)
- postgresql@11
- postgresql@13
- postgresql@9.5
- Finally, no one is forced to update everything at all.
run `brew outdated` and pick whatever you want updated then `brew update foo`...In short, none of what happened to the OP is due to inherent flaws in homebrew... QED.
It is my first choice since a while and if it's not there I go to homebrew
Check [2] https://pkgsrc.se/ before, to see if the availability and the 'freshness' of packages fits your needs.
edit:
[3] http://pkgsrc.joyent.com/install-on-osx/ if you don't want to compile and have binaries instead.
Try:
python -m venv
To fix the very real issue you describe, I would like to see a --isolate option for mission critical packages. All the dependencies would be contained in a separate, package specific directory within /opt or /local. The rest of the dependency management could happen without affecting the isolated package.
- Python already includes the venv module, you don't need to install anything, just run `python -m venv - You should manage multiple versions with pyenv instead of brew. Pyenv can be installed with brew.
not optimal, but sadly necessary.
Here are some arguments why it may be worth it this time :)
EDIT: for me this is a minor issue. i'll continue using `brew` as it does the job quite well
If you forget to include the extensions, you can add them all later.
Also, I'm 100% certain all it did was update the formulae (similar to apt-get update, NOT apt-get upgrade).
I've been using homebrew for years and this is the default behavior, so unless you purposefully set it up to upgrade everything this is PEBKAC.
AFAIK the only time it upgrades everything is when you do a blanket `brew upgrade`. And if you're pinned to something like postgresql@10 it will stay at that major version.
python -m venv /my/directory
I’ve never had any problem with homebrew in over a decade’s usage. But yes, don’t use it for python development tooling: use pyenv and python -m venv and pip for that.
Just wondering.