Eh. I've been using nixOS for years now and still find that I often desperately, desperately wish I could upgrade just one program that I need a new version of without risking that, you know, any individial single one of my installed packages has a change between the last update and now that messes up my workflow. Or that I could pin a version of a software that I'm happier with that version of without essentially rolling my own package repo. It is, in fact, the only package manager I'm aware of that makes it such a pain to do that. It's only because people in this thread are insisting it's doable that I say 'such a pain' instead of just 'impossible'.
A few weeks ago I needed to update firefox for a bug fix that was causing a crash, but of course that meant updating all of nixpkgs. When I finished the switch, the new version of pipewire was broken in some subtle way and I had to roll it back and have been dealing with firefox crashing once a week instead. I can't imagine pitching this to my team for development when I'm having this kind of avoidable issue just with regular packages that aren't even language dependencies.
To those who say 'if you want to lock your dependencies for a project, you can just build a nix flake from a locked file using the <rust | python | npm> tools' I say, why the hell would I want to do that? Being able to manage multiple ecosystems from the same configuration tool was half the draw of nix in the first place!
Creating overlays on nixpkgs is fairly trivial. There was a bug a couple of weeks ago with yt-dlp, which was fixed in the nightly version. But even today the new version is not yet available in nixpkgs-unstable. Did I wait all this time with a broken yt-dlp? No! I created a derivation that overrides the git commit of the original yt-dlp, and added it as an overlay to nixpkgs. Once nixpkgs has the newer version, I'll remove the overlay and customized derivation. This is a 5-lines-of-code change. You don't have to use flakes if you don't want to, it works without flakes as well.
Now compare the above with how you would customize a version in other systems, like Debian with apt-pkgs ...
Um? That's trivial with flakes (and I think it was doable without flakes, but I don't really remember/care). For one-offs (I'd probably do this for your firefox example but YMMV), just tell it the version to run:
$ nix run nixpkgs#firefox -- --version
Mozilla Firefox 138.0.1
$ nix run github:nixos/nixpkgs/nixos-unstable#firefox -- --version
Mozilla Firefox 139.0.1
$ nix run github:nixos/nixpkgs/b98a4e1746acceb92c509bc496ef3d0e5ad8d4aa#firefox -- --version
Mozilla Firefox 122.0.1
Or, if you want to actually incorporate it into your system, tell the system flake to pull whatever versions you want:
and then when you pull packages say which one you want:
packages = with pkgs; [
dillo # from stable nixpkgs
nixpkgs-unstable.firefox # from unstable
nixpkgs-b98a.whatever # from some exact commit of nixpkgs
]
I assume you could do the same thing for project-level flakes, but TBH I don't usually do that so I don't have the code to hand. (In contrast with grabbing system packages from whatever version of nixpkgs I want, which I know works because I pulled the example code from the config on the machine I'm typing this comment on.)
Bingo. Nix doesn't give you a generalizable-across-languages-and-ecosystems way of specifying specific versions without blowing up your package size, unless you hand Nix to your users (which we didn't want to do)
Maybe we were holding it wrong, but, we ultimately made the call to move away for that reason (and more)
A few weeks ago I needed to update firefox for a bug fix that was causing a crash, but of course that meant updating all of nixpkgs. When I finished the switch, the new version of pipewire was broken in some subtle way and I had to roll it back and have been dealing with firefox crashing once a week instead. I can't imagine pitching this to my team for development when I'm having this kind of avoidable issue just with regular packages that aren't even language dependencies.
To those who say 'if you want to lock your dependencies for a project, you can just build a nix flake from a locked file using the <rust | python | npm> tools' I say, why the hell would I want to do that? Being able to manage multiple ecosystems from the same configuration tool was half the draw of nix in the first place!