OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 032

flake.lock 回退与手动编辑

保留已有改动后恢复锁文件,并区分依赖回退与系统代际回退。

所在专题Flakes:项目与依赖管理 ↗
约 6 分钟阅读开始阅读

系统更新翻车后的自救:回退 flake.lock 是恢复可复现状态的常见手段,但不等于系统已经回滚。


flake.lock 的本质#

flake.lock 是给 nix 读的纯文本 JSON——nix 只认内容不认来源。你可以:

  1. 手动编辑(改 rev、改 URL、改 narHash)
  2. git checkout 回退(优先考虑)
  3. 从别处复制一个 lock 文件

只要 narHash 和 rev 对得上、包能构建,nix 就会采用。


回退方式一:git checkout(保留当前改动后使用)#

配置仓库本身是 git 仓库时,回退 flake.lock 可优先从已知好的 Git 版本恢复:

# 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>"

为什么它最安全:

  • 指定 commit 是已知能工作的版本(更新前)
  • 不用猜 narHash
  • 有 git 历史可追溯

回退方式二:系统代际回退#

如果问题出在系统本身(不只是依赖锁定),可以回退整个 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

完整教程见 Generation 管理指南。新系统完全进不去时,重启在 GRUB 菜单选旧代际("NixOS - All configurations")即可。


GC 警示#

NixOS 代际是"堆叠"的:每次 switch 生成新代际,旧的不会自动删除,直到显式删除代际。GC 只回收不再被根引用的 Store 路径。重要配置更新前别跑 nix-collect-garbage——普通 GC 不会删除仍被代际引用的路径;nix-collect-garbage -d 会删除旧代际并回收不再引用的内容,可能失去回退路径。


手动编辑的坑#

  1. narHash 必须准确:nix 用 narHash 校验下载内容。rev 改了但 narHash 是旧的 → 报 hash mismatch。手动改 rev 通常要配新的 narHash。
  2. 有专门命令,不一定要手改:
    • 回退到指定 commit:在 flake.nix 中将 nixpkgs.url 固定到 github:NixOS/nixpkgs/<rev>,再运行 nix flake update nixpkgs
    • 但通过声明输入并由 Nix 生成 lock 通常比手改 JSON 更容易检查,因为配置本身就是 git 仓库。
  3. flake.lock 是版本锁定文件:锁住每个 input 的确切版本,保证可复现。手动编辑 = 手动改变锁定版本,完全合法。

操作对照表#

操作 方式
回退到已知好的旧版本 git restore --source=<commit> -- flake.lock(会覆盖工作树中的该文件,先备份)
更新到最新 nix flake update
更新单个 input nix flake update nixpkgs
手动改特定 rev 手编辑,但需配 narHash(麻烦,少用)

核心:只要配置是 git 仓库,回退 flake.lock 可优先从已知好的 Git 版本恢复,不用手改。手动编辑更像"高级技巧",多数时候不需要。


参考与延伸

  1. Nix Flake 手册 ↗
  2. Nix flake update ↗
  3. Nix flake check ↗
  4. NixOS 系统回退 ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Flakes:项目与依赖管理

  1. 01Flake 结构:inputs 与 outputs
  2. 02flake.lock 与可复现性
  3. 03Flake Utils 与项目模板
  4. 04外部 Flake 引用与协作
  5. 05将 NixOS 配置迁移到 Flakes
  6. 06Flakes 项目与依赖管理教程
  7. 07Flake 更新机制
  8. 08flake.lock 回退与手动编辑
CONTINUE READING / 下一篇Home Manager 集成与模块化

比较独立模式和 NixOS 模块模式,再拆分用户配置。