跨机器同步数据
本文介绍如何用 GitHub + GNU Stow 跨机器同步配置文件
由于我有多台服务器,并且经常重装服务器,于是怎么高效地存储并同步 .bashrc、Claude Code skills 等数据变得至关重要。
我最初的想法是维护一个 GitHub repo,在每台机器上部署该 repo,然后用软链接链接到该 repo。缺点是每次需要手动链接,写成脚本也不方便控制链接哪一部分,于是我找到了 GNU Stow,它可以用一行命令快速创建链接,例如 stow -t ~ bash git claude tmux 就可以一次性配置好 .bashrc、.gitconfig 等指定的数据,有需要的话再加 stow -t ~ proxy 可以把代理配置一起部署了。
示例 repo 在这里:
为什么选这套方案
- 零冗余:配置文件只有一份,修改后
git push即可同步到所有机器,不存在多份拷贝不一致的问题 - 按需部署:服务器只装服务器需要的包,本地机器只装本地需要的包,互不干扰
- 易于迁移:新机器
git clone+stow两条命令即可还原全部配置 - 历史可追溯:每次改动都有 commit 记录,可以随时回滚
- AI 工具配置同步:Claude Code 的用户级
CLAUDE.md、OpenClaw skills 等配置也纳入仓库统一管理,在任意机器上都能获得一致的 AI 辅助体验
思路
GitHub repo │ ├─ git clone ──▶ 机器 A(本地 Mac) ├─ git clone ──▶ 机器 B(远程 Ubuntu 服务器) └─ git clone ──▶ 机器 C(...)所有机器共享同一份配置,通过 git pull / push 同步变更;用 stow 把仓库里的配置文件以符号链接的形式部署到 ~;每台机器只 stow 自己需要的包,不需要的跳过即可。
仓库结构
每个目录是一个独立的 stow 包,可以按需单独部署:
dotfiles/├── bash/ # Bash 配置│ └── .bash_aliases # 通用 alias 和函数(跨机器同步)├── zsh/ # Zsh 配置│ ├── .zshrc│ └── .zsh_aliases├── git/ # Git 配置│ ├── .gitconfig│ └── .gitignore_global├── ssh/ # SSH 客户端配置│ └── .ssh/config├── tmux/ # tmux 配置│ └── .tmux.conf├── proxy/ # 代理开关脚本│ └── .bash_proxy├── claude/ # Claude Code 配置│ └── .claude/│ ├── CLAUDE.md│ ├── settings.json│ └── commands/└── .bashrc # 仅备份,不通过 stow 部署为什么不同步 .bashrc?
.bashrc 包含大量机器相关的设置(路径、环境变量等),各机器差异大,强行统一反而麻烦。因此:
- 同步:
bash/.bash_aliases——通用 alias 和函数,所有机器共享 - 不同步:
.bashrc——机器自带,各自管理;仓库里保留一份 Ubuntu 默认.bashrc作参考备份
.bashrc 里只需保留这几行来加载 aliases:
if [ -f ~/.bash_aliases ]; then . ~/.bash_aliasesfiUbuntu 默认 .bashrc 已经包含这一段,无需额外处理。
使用方法
1. 安装 stow
# Ubuntu / Debiansudo apt install stow
# macOSbrew install stow2. 克隆仓库
git clone git@github.com:<your-username>/dotfiles ~/dotfilescd ~/dotfiles3. 部署配置
# 按需选择要部署的包,例如:stow -t ~ bash git tmux
# 部署全部stow -t ~ bash zsh git ssh tmux proxy claudestow 会在 ~ 下创建符号链接,指向仓库中对应的文件。
4. 取消部署
stow -D -t ~ bash # 删除 bash 包的符号链接日常同步工作流
# 在任意机器上修改配置后,提交并推送cd ~/dotfilesgit add -Agit commit -m "update: ..."git push
# 在另一台机器上拉取最新配置cd ~/dotfilesgit pull# 符号链接已存在,配置立即生效,无需重新 stowStow 注意事项
冲突规则
stow 部署时,若目标路径不存在或已是指向同一文件的符号链接,则正常创建链接;若目标路径已存在且内容不同,则报错退出,不会覆盖。
这套方案从设计上就规避了冲突:仓库只同步那些在新机器上本来就不存在的文件(如 .bash_aliases);而各机器上本已存在的文件(如 .bashrc)则不纳入同步,从根本上避免了冲突。
目录折叠原则
stow 采用最少链接原则:它会尽量在最高层级创建链接,而不是逐个链接每个文件。对于带有多层目录的文件,stow 会依次检查各层目录是否存在,在第一个不存在的层级创建链接。
以 claude/.claude/commands/openclaw.md 为例:
~/.claude | ~/.claude/commands | stow 的行为 |
|---|---|---|
| 不存在 | — | 链接整个 .claude/ 目录 |
| 已存在 | 不存在 | 链接整个 commands/ 目录 |
| 已存在 | 已存在 | 仅链接 openclaw.md 文件 |
这对 claude 包有两点影响:
claude 包Claude Code 安装时会创建 ~/.claude/ 并写入自己的运行时文件(对话记录等)。若提前 stow claude,~/.claude/ 还不存在,stow 会将整个目录链接到仓库,导致 Claude Code 的运行时文件也被写入仓库。
commands/ 目录应在部署前不存在当 commands/ 不存在时,stow 会将整个目录链接到仓库,后续在仓库中新增的 command 文件会自动在所有机器上生效。若 commands/ 已存在(例如 Claude Code 自行创建),stow 只能逐个链接已有文件,新增文件不会自动同步——此时需先删除 ~/.claude/commands/,再重新 stow claude。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!