Bisecting

From NixOS Wiki

Bisecting is a feature of version control systems such as Git and Mercurial to easily pinpoint regressions. Owing to their reproducibility, Nix and NixOS are well-suited to this. As a result, we will list a few tips for using tools like this in the Nix context.

Commit selection

There are different ways to tweak git bisect's commit selection to reduce the required builds:

  • git bisect start flag --first-parent: select merge commits, which depending on the repository can help for caching as well as commit stability.
  • hydrasect: select cached commits cached by Hydra - broken
  • nixpkgs-staging-bisecter (nix-build only): reduce number of derivations to be built.

Automating bisects

  • git bisect run: runs the selected command until the culprit is found.
  • nix-bisect: helps better judge outcome (git bisect's good vs bad skip) and gives nicer outputs than git bisect run.

Bisecting dependencies

While for regressions from changes in a Nix project itself we can bisect following the regular process, bisecting regression in dependencies is a bit different in the sense the repository you would build is separate from the repository you are bisecting. One can do this by running a bisect from a local checkout of the dependency that induced the regression.

Bisecting inputs of Flake projects

For dependencies managed using Flakes, such a bisect run can be used with Nix Flake commands' flag --override-input to override specific inputs to use the bisected dependency in its inputs.

Using git bisect run from your local checkout of the dependency that caused the regression, the flake directory to run a command for can be overridden for a NixOS configuration, for example, using nixos-rebuild's --flake flag. If we can reproduce the issue using a dry-build, this might then look like: git bisect run nixos-rebuild dry-build --override-input $DEPENDENCY_NAME $(pwd) --flake <NIXOS_CONFIG_DIR>#<FLAKE_ATTRIBUTE>.

For a regular Nix Flake project, we do not have a command flag like nixos-rebuild's --flake to specify the directory of your project. We might then address this by wrapping the Nix command in a script changing directory there, for example using: git bisect run sh -c "cd <PROJECT_DIR>; nix flake check --override-input <DEPENDENCY_NAME> $(pwd)".