chezmoi:管理与同步个人配置
chezmoi 用来管理终端、编辑器、命令行工具等程序的个人配置,并把适合共享的部分带到其他机器。此类文件常统称为 dotfiles,因为 Unix 下不少配置文件以点开头,例如 .bashrc 和 .gitconfig;这个称呼也包括 .config 目录里的普通文件。
假设你在两台电脑上使用相同的终端主题,但字体大小不同。把配置放进 Git 可以记录修改,却还需要决定:文件放到哪里、哪部分因机器而异、程序自己写进去的状态要不要同步。chezmoi 负责把这些约定应用到本机文件,Git 则负责版本记录和机器之间的传输。
先分清源文件和正在使用的文件
在默认文件模式下,chezmoi 不会把每份配置都软链接回仓库,而是根据源文件生成并更新目标文件。官方快速入门将源目录设在 ~/.local/share/chezmoi,也允许另行配置。
因此,chezmoi edit 改的是源文件,chezmoi diff 比较期望结果与实际文件,chezmoi apply 才把变化应用到实际文件。仅仅编辑源文件,不会立即改变程序的配置。
安装
按系统选择官方安装页列出的方式,不需要把每种方法都执行一遍:
Omarchy 可以使用自己的包管理入口 omarchy pkg add chezmoi。安装后运行 chezmoi --version 确认命令可用。下文的本地示例已用 chezmoi 2.72.1 检查;不同安装渠道的版本可能不同。Shell 示例使用 Linux、macOS 或 WSL 的 POSIX 风格终端,不是 PowerShell 语法。
用一个小文件走完流程
以下假设你还没有配置 chezmoi,且示例文件不存在。已经在使用它的读者可跳过初始化,并换一个空闲的示例路径,不要覆盖现有配置。
chezmoi init
mkdir -p ~/.config/chezmoi-demo
printf 'theme = "dark"\n' > ~/.config/chezmoi-demo/settings.toml
chezmoi add ~/.config/chezmoi-demo/settings.toml
init 创建本地源仓库;add 把选中的文件纳入管理,不会上传它。现在打开源文件,把 dark 改为 light,保存并退出编辑器:
chezmoi edit ~/.config/chezmoi-demo/settings.toml
接着预览,再应用:
chezmoi diff ~/.config/chezmoi-demo/settings.toml
chezmoi apply --dry-run --verbose ~/.config/chezmoi-demo/settings.toml
chezmoi apply ~/.config/chezmoi-demo/settings.toml
实际文件此时应为 theme = "light"。再执行同一条 diff 命令,预期没有差异。apply 修改的是文件;应用是否立即生效,仍取决于它是否支持热加载,必要时需重新加载配置或重启应用。
忘记源目录或某个文件的源位置时,可以查询:
chezmoi source-path
chezmoi source-path ~/.config/chezmoi-demo/settings.toml
chezmoi managed
程序自己会改配置时怎么办?
有些程序把主题、默认模型等偏好,与最近打开的项目、窗口位置、信任记录放在同一个文件里。整份文件共享,会把本机状态也带走;把它软链接到 Git 仓库,程序的写入又会直接修改仓库内容。
chezmoi 默认管理整份文件。如果程序修改了它,下次 apply 可能把这些变化覆盖回去。换一个管理工具不会自动解决“哪些字段应该共享”的问题。
当只有少数设置需要统一时,可以用官方的 modify_ 模板:它读取本机文件的现有内容,只改指定字段,再生成结果。
把示例改成只管理主题
接着上一节的普通 TOML 文件操作。在源目录中,把原文件改名为带 modify_ 前缀的文件;查询实际源路径可以避免猜测 chezmoi 的目录名:
source_file="$(chezmoi source-path ~/.config/chezmoi-demo/settings.toml)"
mv "$source_file" "$(dirname "$source_file")/modify_$(basename "$source_file")"
chezmoi edit ~/.config/chezmoi-demo/settings.toml
用下面的内容替换编辑器里的源文件。它是一段 chezmoi 模板,不是应用会读取的 TOML:
{{/* chezmoi:modify-template */}}
{{- $config := .chezmoi.stdin | fromToml -}}
{{- $before := $config | toJson -}}
{{- $config = setValueAtPath "theme" "light" $config -}}
{{- if eq $before ($config | toJson) -}}
{{ .chezmoi.stdin }}
{{- else -}}
{{ $config | toToml }}
{{- end -}}
第一行标记让 chezmoi 将它当作修改模板;这种文件不要再加 .tmpl 后缀。.chezmoi.stdin 是当前目标文件的内容,fromToml 解析它,setValueAtPath 只设置 theme。如果值已经一致,就返回原始文本,避免无变化时反复改排版。
现在模拟应用写入一条最近项目记录:
printf '\nrecent_project = "/example/project"\n' >> ~/.config/chezmoi-demo/settings.toml
chezmoi diff ~/.config/chezmoi-demo/settings.toml
chezmoi apply ~/.config/chezmoi-demo/settings.toml
因为主题已经是 light,此时 diff 应为空,recent_project 也会留在本机文件中。源仓库保存的是主题规则,而不是这条项目记录。如果应用把主题改为 dark,下一次 apply 会恢复 light,同时保留其他字段的值。
只有实际修改字段时,这个例子才重新序列化 TOML;那时注释和排版可能丢失。需要精确保留注释的文件,应选支持往返编辑的格式工具,或利用应用自身的 include、本地覆盖文件机制。已经由软链接管理的真实配置,应先备份并解除旧链接,再迁移,避免两个工具同时管理同一路径。
不同机器使用不同值
对于由你完整维护、程序不自行写回的配置,可以使用普通模板。首次添加文件时使用 chezmoi add --template 文件路径,然后用 chezmoi edit 文件路径 编辑模板。
模板可以读取系统类型 .chezmoi.os,也可以读取本机 ~/.config/chezmoi/chezmoi.toml 中 [data] 下的自定义值。例如虚构应用的配置模板可以写成:
font_size = {{ if eq .chezmoi.os "darwin" }}14{{ else }}12{{ end }}
这里 macOS 使用 14,其他系统使用 12。它只是一个条件示例;Windows 与 WSL 也可能使用不同的配置位置,不能只替换一个数字就假定所有程序都兼容。
普通模板生成整份文件,modify_ 模板保留现有文件再修改。针对一个目标选合适的一种,不要把上节的修改模板再当普通 .tmpl 文件添加。
通过 Git 带到另一台机器
确认源仓库只包含准备共享的非敏感配置后,可以按官方跨机器流程使用 Git。先在自己的 Git 托管服务创建一个空的私有 dotfiles 仓库,再进入 chezmoi 的源目录:
chezmoi cd
它会打开一个子 Shell。在这个 Shell 中执行下面的命令,把 YOUR_USER 替换为自己的账号;已有远程仓库时不要重复添加 origin:
git status --short
git add .
git diff --cached
git commit -m "Manage example app settings"
git remote add origin git@github.com:YOUR_USER/dotfiles.git
git push -u origin HEAD
exit
私有仓库仍不是存放密码、Cookie、私钥或认证文件的地方。这里只提交明确选择的非敏感配置,不要把整个主目录或应用目录一股脑导入。
另一台尚未配置 chezmoi 的机器安装工具并具备仓库访问权限后,分步初始化和应用:
chezmoi init git@github.com:YOUR_USER/dotfiles.git
chezmoi diff
chezmoi apply --dry-run --verbose
chezmoi apply
只使用自己控制或已经检查过的源仓库;chezmoi 仓库还可以包含执行脚本。第一次接入时,先看差异比直接使用 init --apply 更容易发现平台不匹配或已有配置冲突。
日后希望先获取更新、再决定是否应用,可以执行:
chezmoi git -- pull --ff-only
chezmoi diff
chezmoi apply
如果 Git 报告分叉或本地修改冲突,先处理差异,不用强制覆盖。另有便捷命令 chezmoi update,但它默认既拉取又应用,默认 Git 拉取还使用 autostash 和 rebase;不要把它当成只下载更新的命令。
从哪些配置开始?
先选一两份体积小、不含秘密、变化容易看懂的文件。终端主题和编辑器快捷键适合先练习整份文件管理;混有最近项目、信任或窗口状态的文件,则先决定受管字段,再使用修改模板。应用若本来支持共享配置加本地覆盖,优先沿用它的分层方式。
这样无需一次迁移所有工具,也不需要自己编写一套通用配置同步器。每增加一个文件,只需清楚地回答:哪些值要共享,哪些值留在本机,下一次 apply 会改变什么。