Understand why a package is updated

I’ve been using nixos for a while, I’m happy so far but I would like to have more understanding and control of the update process.
In particular when I’m a running sudo nixos-rebuild switch --upgrade, sometimes I see that a lot of packages are going to be updated and downloaded and it is not clear for me why.
I understand that probably is a change in some base library that it is triggering a mass rebuild, but I would like to know

  • which library is causing the rebuild (or better, with packages has been updated due to a change, and which just as a dependency)
  • ideally, the dependency tree
  • ideally, why the package has been updated (pointing to a git revision change maybe?)

Is there any magic parameter to nixos-rebuild or some tool/helper that I was not able to discover yet that it is able to provide this information?


1 Like

There is nix-store -q which can output the graph in several ways, but you’ll have to do the diff manually (I’m sure there are third-party tools that might help with that). Besides, it won’t help a lot if you want to know what was the upstream change that lead to the change in the graph, eg. if there was a change in glibc, you’ll see a whole lot of packages but you’ll probably miss other changes in packages that depend on glibc.

So in order for this to be more helpful, you could query the git revisions and use git log on the commit range (possibly with the --stat argument).

Here is a small (and untested) script that you can use in place of nix-channel --update[^1] and which uses the GitHub API to fetch the commit messages of the changes:

#!/usr/bin/env nix-shell
#!nix-shell -p nix jq -i bash
oldrev="$(< "$channelDir/.git-revision")"
nix-channel --update nixos
newrev="$(< "$channelDir/.git-revision")"

curl "$url" | jq -r '.commits | map(.commit.message) | .[]'

[^1]: nixos-rebuild ... --upgrade is nothing more than a shorthand of nix-channel --update followed up by the actual rebuild


Thanks for the script, it is working correctly (it is possible to use curl -s "$url" to reduce verbosity if you want).

About the update itself, I’m aware of the query parameter in nix-store, but I don’t understand how can I use it to know why a package is updated; I assume that I have to query the dependencies of all required packages before updating the channel and afterwards, and then compare somehow the trees: is this your idea? Or there is something easier?

Yep, basically, but since eg. /nix/var/nix/profiles/per-user/root/channels is also a Nix profile, you can also query older generations, eg. nix-env -p /nix/var/nix/profiles/per-user/root/channels --list-generations and of course you also get symlinks like /nix/var/nix/profiles/per-user/root/channels-N-link, where N is the generation. That way it should be easy to find out the differences even after the --upgrade.