☰
WorkBuddy多机同步方案:Git裸仓实现跨设备workspace状态双写
2026/10/8 10:02:08 网站建设 项目流程

1. 项目概述:为什么非得让多台机器共用一个 WorkBuddy 账号?

WorkBuddy 不是传统意义上的 IDE,它更像一个带状态的「开发工作台中枢」——本地缓存目录里存着你最近打开的项目路径、编辑器布局、调试配置、甚至未提交的草稿变更。当你在公司笔记本上改完半截代码,回家想接着调,却发现 WorkBuddy 在另一台机器上压根没加载出那个项目窗口;或者更糟:两台机器各自保存了不同版本的 workspace.json,重启后一方覆盖另一方,刚配好的断点全没了。这不是体验问题,是开发流被硬生生掐断。

我最早遇到这问题是在给客户做远程交付时——手头三台设备(MacBook Pro、Windows 台式机、Ubuntu 笔记本)轮着用,但 WorkBuddy 的账号体系默认只绑定单机状态。官方文档里提过「云同步」,但实测发现它只同步极少量元数据(比如收藏夹链接),真正的 workspace 状态、本地 Git 仓库映射关系、自定义快捷键组、插件启用状态,统统不走云端。换句话说:WorkBuddy 的「账号」本质是个登录凭证,不是状态容器。

所以「多机共用一个账号」这件事,表面看是账号复用,实际核心诉求是跨设备 workspace 状态一致性。而「双写同步」这个说法很精准——不是单向备份,而是两台机器同时可读可写,且能自动收敛冲突。我们最终没走 WorkBuddy 官方通道,而是把它的本地状态目录(.workbuddy)当作一个 Git 仓库来管理,用裸仓 + 预提交钩子 + 同步脚本组合拳,实现近乎实时的状态同步。整个方案不依赖任何第三方云服务,所有数据留在自己可控的 Git 服务器上,连 SSH 密钥都复用现有 Git 基础设施。你不需要重装 WorkBuddy,也不用改任何源码,只需要理解它怎么存状态、Git 怎么管变更、以及哪些文件绝对不能进 Git。

提示:这个方案的前提是你已经有一套稳定的 Git 工作流。如果你还在用「复制粘贴 config 文件」的方式同步开发环境,那先别急着搞双写——先把 Git 的 commit / push / pull 流程跑通再说。WorkBuddy 同步只是 Git 状态管理的一个延伸场景。

2. 核心设计思路:为什么选裸仓 + 双写,而不是云盘或 rsync?

很多人第一反应是「用坚果云/OneDrive 同步.workbuddy目录」,或者写个 rsync 脚本定时推拉。我试过全部三种方案,结论很明确:裸仓 + Git 双写是唯一能兼顾原子性、可追溯性、冲突可见性的方案。下面拆解每种方案的致命缺陷:

  • 网盘同步(坚果云/OneDrive/ iCloud):
    表面最省事,但实际踩坑最多。WorkBuddy 的.workbuddy目录里有大量小文件(每个项目对应一个project-xxxx.json,还有workspace-state.json、layout.json、extensions/下的插件元数据)。网盘客户端对高频小文件变更极其敏感,经常出现「文件正在被占用无法同步」、「本地修改被云端覆盖」、「同步延迟导致两台机器同时写入同一文件」。更麻烦的是,网盘没有 commit 历史,一旦同步错乱,你根本不知道哪次修改丢了,只能靠手动比对时间戳恢复——而 WorkBuddy 的 JSON 文件里很多字段是毫秒级时间戳,肉眼根本没法比。

  • rsync 定时同步:
    比网盘稍好,至少能控制同步时机。但我用rsync -avz --delete搭配 cron 每5分钟跑一次,依然遇到两个硬伤:一是 rsync 无法识别「逻辑冲突」——比如 A 机改了workspace-state.json的布局,B 机改了同一个文件里的调试配置,rsync 默认按时间戳覆盖,谁晚谁赢,但你根本不知道覆盖了什么;二是 rsync 没有事务概念,如果同步中途断电或网络中断,.workbuddy目录可能处于半更新状态,WorkBuddy 启动直接报错「invalid json format」,必须手动删掉整个目录重建。

  • Git 裸仓双写:
    这才是正解。Git 天然解决三个核心问题:

    1. 原子性:每次git push是完整提交,要么全成功,要么全失败,不会出现「只同步了一半文件」的情况;
    2. 可追溯:每条 commit 记录谁、什么时候、改了哪些文件,git log -p一眼看出两次修改的差异;
    3. 冲突可见:当两台机器同时修改同一文件,git pull会明确提示 conflict,你必须手动 resolve,而不是静默覆盖。这对开发环境状态来说,不是麻烦,是刚需——你得知道 workspace 哪里被改了,而不是稀里糊涂丢掉配置。

裸仓(bare repository)是关键设计。它不包含工作区,只存 Git 元数据(objects、refs),相当于一个纯「存储中心」。所有机器都把这个裸仓作为 remote,git push到裸仓,git pull从裸仓拉取。这样避免了「某台机器意外成为 central repo 并被误操作」的风险——裸仓本身不能 checkout,不能 commit,只能收发数据,彻底杜绝人为破坏。

注意:裸仓必须部署在你完全可控的服务器上(比如家里 NAS、VPS 或公司内网 Git 服务),绝不能用 GitHub/GitLab 公共仓库。原因很简单:.workbuddy目录里可能包含本地路径(如"projectPath": "/Users/xxx/project")、调试密钥、甚至临时生成的 token。这些信息一旦上传到公共仓库,等于把你的开发环境钥匙交出去。

3. 实操细节:裸仓搭建、同步脚本与 WorkBuddy 状态文件筛选

3.1 裸仓初始化与权限配置

裸仓必须放在所有机器都能通过 SSH 访问的位置。我用的是家里的 Synology NAS,路径是/volume1/git/workbuddy-bare.git。初始化命令非常简单:

# 在 NAS 上执行(确保你有 ssh 权限) ssh admin@nas-ip mkdir -p /volume1/git/workbuddy-bare.git cd /volume1/git/workbuddy-bare.git git init --bare

关键点在于权限设置。WorkBuddy 的.workbuddy目录默认权限是755,但 Git 推送时需要写入objects/和refs/目录。我遇到过多次remote: fatal: Unable to create '/volume1/git/workbuddy-bare.git/objects/xx/xxx': Permission denied错误,根源是 NAS 的共享文件夹权限没开足。解决方案分两步:

  1. 在 NAS 管理界面,找到git共享文件夹,编辑权限,确保你的用户组(如administrators)有「读写」权限;
  2. SSH 登录后,执行chmod -R g+ws /volume1/git/workbuddy-bare.git,给组添加 sticky bit,确保新创建的子目录继承组写权限。

验证裸仓是否可用:

# 在任意一台机器上测试 git clone ssh://admin@nas-ip/volume1/git/workbuddy-bare.git test-clone cd test-clone echo "test" > README.md git add . git commit -m "test init" git push origin master

如果push成功且test-clone目录下能看到README.md,说明裸仓就绪。

3.2 WorkBuddy 状态文件筛选:哪些该进 Git,哪些必须排除?

这是最容易翻车的环节。WorkBuddy 的.workbuddy目录结构如下(macOS 示例):

.workbuddy/ ├── config.json # 全局配置(含代理、主题等) ├── extensions/ # 插件安装记录(不含插件二进制文件) ├── projects/ # 每个项目一个子目录,含 project.json、workspace.json ├── workspace-state.json # 当前窗口布局、打开的标签页、活动编辑器状态 ├── layout.json # 编辑器面板位置、大小 ├── cache/ # 缓存文件(绝对不能进 Git!) ├── logs/ # 日志(动态生成,忽略) └── tmp/ # 临时文件(忽略)

必须纳入 Git 的文件:

  • config.json:全局设置,比如"theme": "dark"、"autoSave": true,这些是跨设备一致的偏好;
  • projects/**/project.json:项目元数据,含路径、启动命令、调试配置;
  • projects/**/workspace.json:单个项目内的编辑器状态(打开的文件、光标位置);
  • workspace-state.json:整个 WorkBuddy 的窗口状态;
  • layout.json:UI 布局,保证你在 Mac 上调好的三栏布局,Win 上打开也是同样结构。

必须排除的文件(写入.gitignore):

  • cache/:缓存文件体积大、内容动态,且含绝对路径,Git 会疯狂报 conflict;
  • logs/:日志纯属 debug 用,每天生成新文件;
  • tmp/:临时文件,生命周期短;
  • extensions/*/package.json:插件元数据可进 Git,但extensions/*/node_modules/绝对不能进——体积太大,且不同系统编译产物不同;
  • *.lock:锁文件,Git 不该管;
  • **/node_modules/**:同上,WorkBuddy 插件可能自带 node_modules。

我的.gitignore内容精简为:

# WorkBuddy specific cache/ logs/ tmp/ *.lock **/node_modules/** # OS specific .DS_Store Thumbs.db

实操心得:第一次git add .之前,务必用git status --ignored检查被忽略的文件是否合理。我曾漏掉cache/,结果git add .把几百 MB 缓存全塞进暂存区,git commit卡死半小时。后来养成习惯:git add -n .(dry-run)先预览,确认无误再真加。

3.3 同步脚本编写:自动 push/pull + 冲突防护

核心逻辑是:每次 WorkBuddy 退出时自动git push,每次启动时自动git pull。但直接监听 WorkBuddy 进程不现实(macOS 的launchd、Windows 的Task Scheduler、Linux 的systemd触发机制差异太大),所以我采用「文件监控 + 定时兜底」双保险。

启动时同步(pull):
在 WorkBuddy 启动脚本里插入 pull 命令。WorkBuddy 支持自定义启动参数,我在 macOS 的~/.zshrc里重定义workbuddy命令:

alias workbuddy='~/scripts/workbuddy-sync.sh && open -a "WorkBuddy"'

workbuddy-sync.sh内容:

#!/bin/bash WB_DIR="$HOME/.workbuddy" CDIR="$PWD" # 进入工作目录 cd "$WB_DIR" # 拉取最新状态 git pull origin master --no-edit 2>/dev/null # 检查是否有冲突 if [ $? -ne 0 ]; then echo "⚠️ WorkBuddy 同步冲突!请手动 resolve:cd $WB_DIR && git status" # 弹窗提醒(macOS) osascript -e 'display notification "WorkBuddy 同步冲突,请检查终端" with title "Sync Alert"' fi cd "$CDIR"

退出时同步(push):
WorkBuddy 没有退出钩子,但它的workspace-state.json文件会在每次窗口变化时实时写入。我用fswatch(macOS)或inotifywait(Linux)监控这个文件,5秒内无变更即认为用户已稳定,触发 push:

# macOS 版本(需 brew install fswatch) fswatch -o "$HOME/.workbuddy/workspace-state.json" | while read _; do sleep 5 cd "$HOME/.workbuddy" git add workspace-state.json layout.json git commit -m "sync: workspace state $(date '+%Y-%m-%d %H:%M')" 2>/dev/null git push origin master 2>/dev/null done

Windows 用户可用 PowerShell 的FileSystemWatcher,逻辑相同:监听workspace-state.jsonLastWriteTime 变更,延迟 5 秒后 commit push。

注意:git push必须配置免密 SSH。如果每次 push 都输密码,用户会疯掉。ssh-keygen -t ed25519生成密钥,ssh-copy-id admin@nas-ip复制公钥到 NAS。验证方式:ssh admin@nas-ip 'ls /volume1/git',不输密码就能列出目录,说明 OK。

4. 关键环节实现:冲突处理、SSH 认证与跨平台路径适配

4.1 冲突处理:不是 Bug,是设计的一部分

Git 冲突在双写场景下不是异常,而是常态。WorkBuddy 的workspace-state.json里有"activeEditor": "/Users/xxx/project/src/main.js"这样的绝对路径字段。当你在 Mac 上用/Users/xxx/,在 Windows 上用C:\Users\xxx\,同一项目在不同系统打开,Git 必然冲突。这时候不能粗暴git checkout --ours,必须人工介入。

我的冲突处理 SOP:

  1. WorkBuddy 启动时检测到冲突,弹窗提醒并暂停加载 workspace;
  2. 终端自动打开vim ~/.workbuddy/workspace-state.json(或你惯用的编辑器);
  3. 手动编辑冲突标记<<<<<<< HEAD和>>>>>>> origin/master之间的内容;
  4. 重点修复三类字段:
    • activeEditor:保留当前机器的绝对路径,删除另一方的;
    • folders:数组形式,保留双方都有的项目路径,删除只在一方存在的;
    • layout:width/height数值保留,x/y坐标按当前屏幕分辨率重算(比如 Mac Retina 屏是 2x 缩放,Win 是 1.25x);
  5. git add workspace-state.json && git commit -m "resolve: workspace path conflict";
  6. WorkBuddy 重启生效。

实操心得:我写了个 Python 小工具wb-resolve.py,自动提取冲突块,把 Mac 路径/Users/xxx/替换为 Win 路径C:/Users/xxx/,反之亦然。虽然不能全自动 resolve,但节省 80% 手动编辑时间。核心逻辑就一行:line.replace('/Users/', 'C:/Users/').replace('/', '\\')。

4.2 SSH 认证失败排查:90% 的问题出在这里

ssh: connect to host nas-ip port 22: Connection refused或Permission denied (publickey)是新手最大拦路虎。我整理了完整排查链:

现象可能原因解决方案
ssh: connect to host nas-ip port 22: Connection refusedNAS 的 SSH 服务未开启Synology:控制面板 → 终端机和 SNMP → 启用 SSH 服务;群晖默认端口 22,确认防火墙放行
Permission denied (publickey)公钥未正确复制到 NASssh-copy-id -i ~/.ssh/id_ed25519.pub admin@nas-ip;手动检查 NAS 的~admin/.ssh/authorized_keys是否包含你的公钥
fatal: Could not read from remote repositoryGit 路径错误git remote set-url origin ssh://admin@nas-ip/volume1/git/workbuddy-bare.git;注意路径是 NAS 上的绝对路径,不是共享文件夹名
Host key verification failedNAS IP 变更导致 known_hosts 冲突ssh-keygen -R nas-ip清除旧记录,再ssh admin@nas-ip重新确认

特别提醒:Synology NAS 的admin用户默认禁用 SSH 登录。必须在「控制面板 → 用户账户 → 编辑 admin → 启用 SSH 服务」。否则ssh-copy-id永远失败。

4.3 跨平台路径适配:Mac/Win/Linux 的绝对路径陷阱

WorkBuddy 的project.json里path字段是绝对路径,这是双写最大的兼容性挑战。我的方案是「路径抽象化 + 启动时映射」:

  1. 统一用相对路径存 Git:
    修改所有project.json的path字段,从/Users/xxx/project改为../projects/my-app。这样 Git 里存的是相对路径,不随系统变化。

  2. 启动时动态映射:
    在workbuddy-sync.sh里加入路径映射逻辑:

    # macOS sed -i '' 's|\.\./projects|/Users/xxx/projects|g' projects/*/project.json # Windows sed -i 's|\.\./projects|C:\\Users\\xxx\\projects|g' projects/*/project.json

    这样 Git 存干净的相对路径,本地运行时再替换成真实路径。

  3. WorkBuddy 配置开关:
    在config.json里加一个"useRelativePath": true字段,告诉 WorkBuddy 启动时优先读相对路径。虽然 WorkBuddy 官方不支持,但它的源码里路径解析逻辑是开放的,我用patch命令打了轻量补丁(仅 3 行代码),不影响升级。

注意:路径替换必须在git pull之后、WorkBuddy 启动之前执行。顺序错了,WorkBuddy 会读到错误路径直接报错。

5. 常见问题与排查技巧实录:从 SSH 失败到 Git 目录泄露

5.1 典型问题速查表

问题现象根本原因解决方案避坑指数 ★★★★★
WorkBuddy 启动后项目列表为空projects/目录未被git add,或.gitignore误删了projects/git status查看projects/是否在 untracked 列表;检查.gitignore是否有projects/行★★★★★
git push后裸仓里看不到新 commit裸仓权限不足,git receive-pack无法写入objects/ssh admin@nas-ip登录 NAS,执行ls -ld /volume1/git/workbuddy-bare.git/objects/,确认组有w权限;chmod g+w /volume1/git/workbuddy-bare.git/objects/★★★★☆
同步后 WorkBuddy 报错Error loading workspaceworkspace-state.json格式损坏,通常是手动编辑时少了个逗号git checkout HEAD -- workspace-state.json回退到上一个正常版本;用jsonlint校验 JSON 语法★★★★☆
两台机器同时 push,裸仓提示non-fast-forward有人先 push 了,你的本地分支落后git pull origin master && git push origin master;切忌git push --force,会丢历史★★★☆☆
Windows 上git pull报错fatal: invalid path路径含非法字符(如:、*),WorkBuddy 自动生成的项目名带冒号重命名项目,去掉:;或在.gitattributes里加* text=auto eol=lf统一换行符★★☆☆☆

5.2 独家避坑技巧

  • 裸仓备份策略:每周rsync -av /volume1/git/workbuddy-bare.git/ /backup/git/workbuddy-bare-$(date +%F).git/。裸仓本身是 Git 数据,但物理损坏风险永远存在。我经历过一次 NAS 硬盘坏道,裸仓目录部分损坏,幸好有 3 天前的备份,git fsck修复后完整恢复。

  • Git 目录泄露防护:WorkBuddy 的.workbuddy如果被误设为 Web 服务器根目录,.git/目录可能被外部访问。我在 Nginx 配置里加了全局屏蔽:

    location ~ /\.git { deny all; }

    同时在裸仓所在目录的.htaccess(Apache)或web.config(IIS)里做同样限制。安全无小事。

  • 插件同步陷阱:WorkBuddy 的extensions/目录里,有些插件会生成settings.json(含 API Key),这些绝对不能进 Git。我在.gitignore里加了extensions/**/settings.json,并定期git ls-files | grep settings.json扫描漏网之鱼。

  • SSH 连接超时优化:NAS 默认 SSH 连接空闲 5 分钟断开,导致git push中途失败。在客户端~/.ssh/config加:

    Host nas-ip ServerAliveInterval 60 ServerAliveCountMax 3

    这样每 60 秒发心跳包,连续 3 次失败才断开,稳如老狗。

  • WorkBuddy 缓存目录迁移:官方说workbuddy 缓存目录怎么更改,其实很简单。config.json里加"cachePath": "/path/to/new/cache",然后mkdir -p /path/to/new/cache,重启即可。我迁移到 SSD 分区,打开大项目速度提升 40%。

最后分享个小技巧:在~/.workbuddy/projects/目录下建个README.md,写明「此目录由 Git 双写同步管理,请勿手动修改」。每次新同事入职,看到这个文件就知道规矩,比写 10 页文档都管用。技术方案的价值,最终体现在能不能让人一眼看懂、放心使用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询