OFFSET偏移
← All articlesOFFSET / FIELD NOTESNO. 032

Rolling back and manually editing flake.lock

Preserve existing changes before restoring the lock file, and distinguish dependency rollback from system-generation rollback.

English translation · Code and commands follow the Chinese original.

IN THESE READING PATHSFlakes: project and dependency management ↗
About 3 min readStart reading

Recovering from a failed system update: reverting flake.lock is a common way to restore a reproducible state, but it does not mean the system itself has been rolled back.


What flake.lock Really Is#

flake.lock is plain-text JSON for nix to read: nix cares about its contents, not where it came from. You can:

  1. Edit it manually (change rev, URL, or narHash)
  2. Revert it with git checkout (the preferred option)
  3. Copy a lock file from elsewhere

As long as narHash matches rev and the packages can be built, nix will use it.


Rollback Method One: git checkout (Preserve Current Changes First)#

If your configuration is in a git repository, prefer restoring flake.lock from a known-good Git revision:

# 1. 查看提交历史,找到更新前的 commit
cd ~/nixos-config
git status --short
# 先备份当前锁文件,保留尚未提交的更新
cp flake.lock /tmp/flake.lock.before-rollback
git log --oneline -5 flake.lock

# 2. 回退 flake.lock 到某个 commit 的版本(<known-good-commit> 是更新前)
git restore --source=<known-good-commit> -- flake.lock

# 3. 验证配置能评估(不实际构建)
nix flake check --no-build
nixos-rebuild dry-build --flake .#my-host

# 4. 检查差异;dry-build 不会构建或激活系统
git diff -- flake.lock
# 确认需要保存本次回退后再提交
git add flake.lock
git commit -m "revert(flake): roll back flake.lock to <known-good-commit>"

Why this is the safest approach:

  • The specified commit is a known-working version from before the update
  • No need to guess narHash
  • Git history provides traceability

Rollback Method Two: Roll Back the System Generation#

If the problem is in the system itself, rather than just dependency locking, you can roll back the entire generation:

# 列出所有历史系统代际(按时间倒序)
ls -l /nix/var/nix/profiles/system-*-link

# 回到上一个代际(立即生效)
sudo nixos-rebuild switch --rollback

# 回到指定代际(如第 5 个)
sudo /nix/var/nix/profiles/system-5-link/bin/switch-to-configuration switch

For the full tutorial, see the Generation Management Guide. If the new system will not boot at all, reboot and select an older generation in the GRUB menu ("NixOS - All configurations").


Garbage Collection Warning#

NixOS generations are "stacked": each switch creates a new generation, and older ones are retained until explicitly deleted. GC reclaims only store paths that are no longer referenced by roots. Do not run nix-collect-garbage before an important configuration update. Ordinary GC does not delete paths still referenced by generations; nix-collect-garbage -d deletes old generations and reclaims unreferenced content, potentially removing your rollback path.


Pitfalls of Manual Editing#

  1. narHash must be correct: nix uses narHash to verify downloaded content. If rev changes but narHash is still the old value, you get a hash mismatch. Manually changing rev usually requires a corresponding new narHash.
  2. Dedicated Commands Mean Manual Editing Is Not Always Necessary:
    • Roll back to a specific commit: 在 flake.nix 中将 nixpkgs.url 固定到 github:NixOS/nixpkgs/<rev>,再运行 nix flake update nixpkgs
    • However, declaring inputs and letting Nix generate the lock file is usually easier to review than editing JSON manually, since the configuration itself is in a git repository.
  3. flake.lock is a version lockfile: it locks each input to an exact version for reproducibility. Editing it manually means manually changing the locked version, which is entirely valid.

Operation Reference#

Operation Method
Revert to an older, known-good version git restore --source=<commit> -- flake.lock (overwrites this file in the working tree; back it up first)
Update to the latest version nix flake update
Update a single input nix flake update nixpkgs
Manually change a specific rev Edit manually, with the corresponding narHash (cumbersome; use sparingly)

The key point: if your configuration is in a git repository, prefer restoring flake.lock from a known-good Git revision rather than editing it manually. Manual editing is more of an "advanced technique" and is usually unnecessary.


References & further reading

  1. Nix Flake manual ↗
  2. Nix flake update ↗
  3. Nix flake check ↗
  4. NixOS system rollback ↗

Adapted from technical notes. Examples use generic names.

Continue along a reading path

Flakes: project and dependency management

  1. 01Flake structure: inputs and outputs
  2. 02flake.lock and reproducibility
  3. 03Flake Utils and project templates
  4. 04External Flake references and collaboration
  5. 05Migrating NixOS configuration to Flakes
  6. 06A tutorial on Flake projects and dependency management
  7. 07How Flake updates work
  8. 08Rolling back and manually editing flake.lock
CONTINUE READING / NEXT ARTICLEHome Manager integration and modular configuration

Compare standalone and NixOS module modes, then split user configuration into modules.