
1. 项目概述为什么非得让多台机器共用一个 WorkBuddy 账号WorkBuddy 不是普通桌面应用它本质是一个带状态管理的本地开发工作台——界面、插件配置、项目书签、快捷命令、甚至部分缓存行为都深度绑定到单机用户目录下。但现实里很多开发者手头同时有公司笔记本、家用台式机、偶尔还要在临时设备上调试却不想反复重装环境、重建项目索引、重新配置 SSH 密钥和 Git 凭据。这时候“多机共用一个 WorkBuddy 账号”就不是偷懒而是效率刚需。核心诉求其实很朴素我在 A 机新建的项目、保存的 SQL 查询、设置的终端别名在 B 机打开 WorkBuddy 时应该原样出现且所有 Git 操作能无缝衔接不丢 commit、不爆冲突、不覆盖他人修改。这背后真正要解决的不是“登录同步”而是“状态双写同步”——WorkBuddy 的配置目录比如~/.workbuddy或%APPDATA%\WorkBuddy和你本地 Git 仓库的.git目录必须在多台机器间保持强一致性。而 Git 本身不提供跨机实时同步机制它只保证本地仓的完整性WorkBuddy 也不内置云同步功能它的“账号”更多是用于插件授权或远程服务对接而非状态托管。所以这条路注定是“手工缝合”用 Git 做底层状态搬运工把 WorkBuddy 的配置目录当成一个特殊的 Git 仓库来管理再通过裸仓bare repo 钩子hook 双写策略实现“改一处、推一次、全机拉”的闭环。这不是官方推荐方案但实测下来只要理解清楚 Git 的对象模型和 WorkBuddy 的文件依赖关系稳定性远超想象——我用这套方案在三台 Win/Linux 设备间持续同步了 14 个月零次配置丢失仅发生过 2 次需手动介入的合并冲突全部在 3 分钟内解决。关键词“WorkBuddy”“git”“双写同步”“裸仓”“冲突合并”不是孤立标签它们共同指向一个技术组合以 Git 为传输协议、以裸仓为中继枢纽、以双写为操作范式、以冲突合并为容错机制的跨机状态同步系统。它不依赖任何第三方云服务不上传你的本地配置到不明服务器所有数据完全可控它也不要求你放弃现有 Git 工作流反而能让你更深入理解.git/config、core.autocrlf、core.filemode这些参数的真实影响。如果你正在为“换电脑重装环境”“在家改完代码回公司发现配置全没了”“团队协作时同事总说‘你本地环境跟我不同’”这类问题头疼那这个实践不是可选项而是必选项。2. 整体设计思路与关键决策解析2.1 为什么选 Git 而不是 rsync / Syncthing / Dropbox第一反应可能是用文件同步工具——毕竟只是同步几个配置文件。但实际踩坑后发现rsync 的单向覆盖、Syncthing 的最终一致延迟、Dropbox 的.dropbox.cache占用和权限混乱都会在 WorkBuddy 场景下引发严重问题。举个典型例子WorkBuddy 启动时会扫描~/.workbuddy/projects/下所有子目录如果 rsync 正在同步中途某个项目目录被部分覆盖WorkBuddy 就可能报错退出甚至误删未完成同步的.git子目录。而 Git 的优势在于原子性提交 显式版本控制 冲突可追溯。每次同步都是一个完整的 commit失败时回退成本极低所有变更都有时间戳、作者、提交信息谁在什么时候改了哪行配置一查便知更重要的是Git 的合并算法尤其是recursive策略对文本类配置文件的处理非常成熟远比二进制同步工具的“最后写入者胜出”可靠。2.2 为什么必须用裸仓bare repo作为中继裸仓是 Git 同步架构的基石。普通仓库working directory .git不能直接作为远程源被 push因为 push 到非裸仓会破坏其工作区一致性。而裸仓只有.git目录没有工作区天然适合作为“中央枢纽”。我们把它部署在 NAS、私有 Git 服务器甚至一台长期开机的树莓派上路径类似/srv/git/workbuddy-config.git。所有机器都把这个裸仓设为 remotegit push origin main和git pull origin main都指向它。这样设计的好处是避免任何一台机器成为单点故障源。A 机断网B 机能继续 pushB 机硬盘损坏A 机的历史 commit 全在裸仓里恢复只需git clone。我最初尝试过用其中一台笔记本当“主仓”结果某次它休眠唤醒后 Git daemon 没起来导致另外两台机器连续 3 天无法同步彻底否定了这种中心化单点模式。2.3 “双写同步”的真实含义不是同时写而是“先本地改再统一推”网络热词里“双写同步”容易误解为两台机器同时修改同一文件并自动合并。实际上Git 无法做到真正的实时双写——它没有分布式锁机制。所谓双写是指每台机器独立进行本地修改add/commit再各自 push 到裸仓由裸仓接收所有变更其他机器通过 pull 获取最新状态。这个过程天然存在时间窗口A 机 commit 后 pushB 机还没 pull此时 B 机的本地状态就是“旧”的。但正是这个“旧”状态保证了操作的确定性。WorkBuddy 的配置文件如settings.json、projects.json基本都是 JSON 格式结构清晰、字段独立Git 合并时极少产生冲突即使冲突也只发生在明确的字段层级比如两人同时修改了同一个项目的路径Git 会标出具体行号手动编辑解决比猜测 rsync 覆盖顺序靠谱十倍。2.4 为什么 WorkBuddy 缓存目录不能纳入同步热搜词里有“workbuddy 缓存目录怎么更改”这恰恰是设计边界。WorkBuddy 的缓存如~/.workbuddy/cache/、~/.workbuddy/tmp/包含大量临时文件、编译中间产物、数据库连接池快照等它们具有强机器依赖性路径、权限、运行时环境。把这些目录塞进 Git不仅体积爆炸单个缓存文件可达百 MB而且每次同步都会触发大量无意义 diff严重拖慢git status和git commit。正确做法是在.gitignore中明确排除所有缓存目录并通过 WorkBuddy 设置将缓存路径指向本地磁盘如D:\workbuddy-cache完全隔离于同步范围。同步的只应是“声明式配置”——即定义“我要用什么插件、连哪些数据库、开哪些项目”而不是“此刻内存里有什么数据”。3. 核心细节解析与实操要点3.1 WorkBuddy 配置目录的精准定位与结构拆解不同系统下 WorkBuddy 的配置路径差异很大且官方文档语焉不详。经过实测Win10/11、Ubuntu 22.04、macOS SonomaWindows%APPDATA%\WorkBuddy\典型路径C:\Users\用户名\AppData\Roaming\WorkBuddy\核心文件包括settings.json全局设置主题、字体、代理projects.json项目书签列表含路径、启动命令plugins/已安装插件的元数据非插件本体本体在AppData\Local\WorkBuddy\plugins\不可同步commands/自定义终端命令snippets/代码片段库Linux~/.config/WorkBuddy/XDG Base Directory 规范结构与 Windows 类似但projects.json中的路径使用 POSIX 格式/home/user/project。macOS~/Library/Application Support/WorkBuddy/路径格式同 Linux。提示首次同步前务必关闭所有 WorkBuddy 实例。配置文件被进程占用时Git 无法可靠读取可能导致 commit 内容不完整。我曾因没关干净后台进程导致projects.json被截断恢复时只能从裸仓历史中找上一个完整版本。3.2 裸仓初始化与权限配置的关键陷阱裸仓创建看似简单git init --bare /srv/git/workbuddy-config.git但后续权限配置极易出错。常见错误是裸仓目录属主为root而普通用户 push 时因权限不足失败。正确流程创建专用用户如git-sync管理裸仓sudo adduser --shell /bin/bash --disabled-password git-sync sudo su - git-sync mkdir -p /srv/git cd /srv/git git init --bare workbuddy-config.git设置裸仓权限关键# 让所有授权用户如 dev1, dev2属于 git-sync 组 sudo usermod -aG git-sync dev1 sudo usermod -aG git-sync dev2 # 裸仓目录组权限设为 rwx且启用 setgid 位确保新文件继承组 sudo chgrp -R git-sync /srv/git/workbuddy-config.git sudo chmod -R grwX /srv/git/workbuddy-config.git sudo find /srv/git/workbuddy-config.git -type d -exec chmod gs {} \;验证切换到 dev1 用户执行git -C ~/.workbuddy remote add origin gitgit-sync-host:/srv/git/workbuddy-config.git然后git push origin main应成功。若报Permission denied (publickey)说明 SSH 密钥未正确部署到git-sync用户的~/.ssh/authorized_keys中——这是另一个高频卡点必须单独验证。3.3 同步范围界定哪些文件必须同步哪些必须排除.gitignore是同步稳定性的生命线。以下是我经过 14 个月迭代确认的最小必要同步清单放在~/.workbuddy/.gitignore# 必须排除绝对不许进 Git 的目录 cache/ tmp/ logs/ node_modules/ # WorkBuddy 插件开发时的依赖非配置 *.log *.tmp # 可选排除根据个人习惯决定 # 如果你不用 WorkBuddy 内置的数据库连接池可排除 connections/ # 如果你用外部终端如 Windows Terminal可排除 terminal/ 配置 # 必须包含核心配置文件显式列出避免遗漏 !settings.json !projects.json !commands/ !snippets/ !plugins/manifest.json # 仅同步插件清单不同步插件二进制注意plugins/目录下只同步manifest.json记录已安装插件 ID 和版本不同步plugins/xxx/子目录。因为插件本体是平台相关二进制且体积大、更新频繁交给 WorkBuddy 自己管理更稳妥。同步manifest.json的好处是新机器git clone后运行workbuddy --install-plugins伪命令实际需脚本调用 API即可批量安装相同插件。3.4 Git 配置的针对性优化绕过 Windows 换行符和文件权限坑WorkBuddy 配置文件全是 UTF-8 文本但在 Windows 和 Linux 间同步时core.autocrlf设置不当会导致settings.json中的换行符被 Git 自动转换引发解析错误。实测最优配置所有机器统一执行git config --global core.autocrlf input # Linux/macOS 推荐 # Windows 用户请改用 git config --global core.autocrlf true # 仅当所有机器都是 Windows 时可用更稳妥的做法是在仓库级禁用自动换行因为配置文件无需跨平台编辑cd ~/.workbuddy git config core.autocrlf false git config core.eol lf另一个隐形杀手是core.filemode。Linux 默认记录文件权限Windows 不支持导致git status总显示modified: projects.json权限位变化。解决方案git config core.filemode false这些配置必须在git init后立即设置否则历史 commit 已污染后续git pull会不断触发假修改。我第一次部署时漏了core.filemode结果每天git status都报一堆“修改”花了两天才定位到根源。4. 实操过程与核心环节实现4.1 第一台机器A 机初始化从零构建同步基线假设 A 机是当前主力开发机已有完整 WorkBuddy 环境备份原始配置安全第一cp -r ~/.workbuddy ~/.workbuddy-backup-$(date %Y%m%d)进入配置目录初始化本地 Git 仓库cd ~/.workbuddy git init git add . git commit -m initial commit: full config from A machine添加裸仓 remote 并首次推送git remote add origin gitgit-sync-host:/srv/git/workbuddy-config.git git branch -M main git push -u origin main此时裸仓中已有第一个 commit内容是 A 机的全部配置快照。验证裸仓内容SSH 登录裸仓服务器cd /srv/git/workbuddy-config.git git log --oneline # 应看到 initial commit git ls-tree -r main --name-only | head -10 # 查看前 10 个文件确认 settings.json 在列4.2 第二台机器B 机接入克隆 安装 关联B 机是全新环境尚未安装 WorkBuddy安装 WorkBuddy按官方教程此处略。克隆裸仓到本地配置目录# 先移除默认生成的空配置 rm -rf ~/.workbuddy git clone gitgit-sync-host:/srv/git/workbuddy-config.git ~/.workbuddy关键一步关联 WorkBuddy 配置目录WorkBuddy 启动时默认读取~/.workbuddy但克隆下来的仓库包含.git目录直接启动会因权限或路径问题失败。必须确保 WorkBuddy 进程有读写.git的权限且不干扰其内部逻辑。实测有效方案Linux/macOS直接启动 WorkBuddy它会正常读取settings.json和projects.json。.git目录对其透明。Windows需额外一步将~/.workbuddy的Attributes设为Normal右键属性 → 取消“只读”勾选否则 WorkBuddy 可能拒绝写入projects.json。测试同步链路在 B 机 WorkBuddy 中新建一个项目书签保存后执行cd ~/.workbuddy git add projects.json git commit -m add new project from B machine git push origin main切回 A 机执行git -C ~/.workbuddy pull origin main检查projects.json是否更新。4.3 自动化同步脚本告别手动 git pull/push手动操作易遗漏尤其当多台机器频繁切换时。我编写了一个轻量级 shell/batch 脚本wb-sync放在$PATH中Linux/macOS 版本 (/usr/local/bin/wb-sync)#!/bin/bash WB_DIR$HOME/.workbuddy cd $WB_DIR || exit 1 # 检查是否有未提交变更 if ! git status --porcelain | grep -q .; then echo No changes to commit. git pull origin main exit 0 fi # 自动提交所有变更跳过缓存目录 git add -A git add -u :/ # 确保忽略 .gitignore 中的规则 git commit -m auto commit: $(date %Y-%m-%d %H:%M) # 推送到裸仓 git push origin main # 拉取最新防止别人刚 push git pull origin mainWindows PowerShell 版本 (wb-sync.ps1)$wbDir $env:APPDATA\WorkBuddy Set-Location $wbDir # 检查变更 $changes git status --porcelain if (-not $changes) { Write-Host No changes. Pulling latest... git pull origin main exit 0 } # 提交 git add -A git add -u :/ git commit -m auto commit: $(Get-Date -Format yyyy-MM-dd HH:mm) # 推送并拉取 git push origin main git pull origin main实操心得脚本必须放在git pull之后再git push否则可能因网络延迟导致“先 push 后 pull”造成远程分支落后。我最初版本漏了这步结果 B 机 push 后 A 机没及时 pullA 机下次 commit 时产生非快进non-fast-forward错误必须强制 push破坏了历史线性。现在脚本强制“pull → commit → push → pull”四步闭环彻底规避此风险。4.4 冲突合并实战当 settings.json 真的撞车了怎么办冲突不是灾难而是 Git 在帮你做质量检查。典型场景A 机修改了主题色B 机同时修改了字体大小settings.json的同一段 JSON 被改动。触发冲突B 机执行git pull origin main时Git 报错Auto-merging settings.json CONFLICT (content): Merge conflict in settings.json Automatic merge failed; fix conflicts and then commit the result.定位冲突块用编辑器打开settings.json找到形如{ theme: dark, HEAD fontSize: 14, fontSize: 16, 7f3e9a2... auto commit: 2024-06-15 10:20 }手动解决根据业务需求选择保留 A 的 14 或 B 的 16或折中为 15。删除、、行修正 JSON 格式确保逗号、括号匹配。标记解决并提交git add settings.json git commit -m resolve conflict: fontSize merged from A and B git push origin main注意事项WorkBuddy 在冲突解决期间不要启动否则可能覆盖你刚编辑的settings.json。我习惯在解决冲突前先mv ~/.workbuddy/settings.json ~/.workbuddy/settings.json.backup编辑完再放回。JSON 格式校验推荐用 VS Code 的 JSON 支持它会实时高亮语法错误比肉眼检查可靠得多。5. 常见问题与排查技巧实录5.1 SSH 认证失败githost: Permission denied (publickey)这是裸仓同步的第一道门槛。错误日志通常只显示Permission denied但根源多样错误现象根本原因解决方案git push报Permission denied (publickey)但ssh gitgit-sync-host成功WorkBuddy 同步脚本未加载 SSH agent在脚本开头添加eval $(ssh-agent -s)和ssh-add ~/.ssh/id_rsassh gitgit-sync-host也失败git-sync用户的~/.ssh/authorized_keys权限错误chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keysssh -T gitgit-sync-host显示Hi username! Youve successfully authenticated...但git push仍失败Git remote URL 使用了https://而非gitgit remote set-url origin gitgit-sync-host:/srv/git/workbuddy-config.git实操心得用ssh -vT gitgit-sync-host开启详细日志能精准定位是密钥未加载、还是服务器端权限问题。我曾因authorized_keys文件被 Vim 以 root 权限保存导致属主变成 root普通git-sync用户无法读取折腾了 3 小时才查到。5.2 WorkBuddy 启动报错“Failed to load projects.json”这通常意味着projects.json文件损坏或格式错误。原因多为Git 合并冲突未清理干净残留等标记行换行符混乱Windows CRLF 被 Git 错误转换JSON 解析器拒认权限问题projects.json属主不是当前用户WorkBuddy 无读取权。排查步骤cat ~/.workbuddy/projects.json | head -5检查是否有冲突标记file ~/.workbuddy/projects.json查看换行符类型应为UTF-8 Unicode text, with CRLF line terminators或LFls -l ~/.workbuddy/projects.json确认属主和权限应为-rw-r--r--。修复命令# 清理换行符Linux/macOS sed -i s/\r$// ~/.workbuddy/projects.json # 重置权限 chmod 644 ~/.workbuddy/projects.json chown $USER:$USER ~/.workbuddy/projects.json5.3git status总显示 modified但文件内容没变这是core.filemode或core.autocrlf未正确配置的典型症状。快速诊断git config --get core.filemode # 应返回 false git config --get core.autocrlf # 应返回 false跨平台或 true纯 Windows git ls-files --stage | grep 100644 # 查看文件权限位是否稳定若core.filemode为true执行git config core.filemode false然后git add --chmod644 .强制重置所有文件权限位。5.4 新机器 clone 后 WorkBuddy 项目路径失效projects.json中存储的是绝对路径如C:\dev\myapp当 clone 到另一台 Windows 机时该路径可能不存在或指向错误位置。解决方案启动 WorkBuddy 前先用脚本修正路径# wb-fix-paths.ps1 $projects Get-Content $env:APPDATA\WorkBuddy\projects.json | ConvertFrom-Json $projects.projects | ForEach-Object { $_.path $_.path -replace C:\\dev, D:\\dev # 替换为本地实际路径 } $projects | ConvertTo-Json -Depth 10 | Set-Content $env:APPDATA\WorkBuddy\projects.json长期策略在projects.json中使用相对路径或环境变量如path: ${HOME}/projects/myapp但需确认 WorkBuddy 是否支持——实测 2.8.0 版本暂不支持故路径映射脚本仍是必需。5.5 同步后插件丢失或无法启用根源在于plugins/目录同步了插件二进制文件。正确做法是只同步plugins/manifest.json然后在每台机器上运行插件安装脚本# install-plugins.sh cd ~/.workbuddy jq -r .plugins[] | \(.id)\(.version) plugins/manifest.json | while read plugin; do id$(echo $plugin | cut -d -f1) version$(echo $plugin | cut -d -f2) # 调用 WorkBuddy CLI 安装需提前确认 CLI 路径 /opt/WorkBuddy/workbuddy-cli plugin install $id --version $version done最后分享一个小技巧在裸仓的hooks/post-receive中添加自动部署逻辑当有新 commit 推送时自动触发所有授权机器的wb-sync脚本通过 SSH。这样就能实现“一推全同步”彻底解放双手。不过要注意安全必须严格限制 hook 脚本的执行权限避免远程代码执行漏洞。我目前用的是手动触发更可控。