SiPush V2:Obsidian 与思源笔记双向同步
SiPush V2:Obsidian 与思源笔记双向同步
SiPush V2:Obsidian ↔ 思源笔记双向同步插件
前言
如果你同时使用 Obsidian 和思源笔记,一定有过这样的困扰:在 Obsidian 编辑了笔记,想在思源里也能看到同样的内容;在思源里写了些想法,又想在 Obsidian 里同步回来。
SiPush V2 就是为了解决这个问题而生的——Obsidian ↔ 思源笔记的双向同步插件。
从 V1 到 V2:一次彻底的架构升级
SiPush V1 是一个单向推送插件,只能把 Obsidian 笔记推送到思源笔记。但实际使用中,双向同步才是刚需。V2 的核心架构做了根本性的改变:
哈希驱动的双向同步
V1 使用时间戳来判断同步方向,但这有个致命缺陷:思源的 updateBlock API 每次调用都会刷新文档的 updated 时间戳,导致 Obsidian 刚推送完内容,下一次同步就会误判思源"更新过了",触发不必要的拉取。
V2 改用内容哈希(Content Hash) 驱动同步:
- 每次同步都实时拉取思源当前内容,重新计算哈希
- 与 Obsidian 端的哈希对比,判断内容是否一致
- 如果两边都改过 → 冲突;如果只有一边改过 → 自动推送/拉取
这彻底杜绝了时间戳漂移带来的误判问题。
三层定位:Push ID 持久化关联
为了在 Obsidian 和思源之间建立稳定的文档关联,V2 采用了三层定位策略:
- Obsidian frontmatter:每个同步过的笔记 frontmatter 中写入
custom-si-push-id - 思源自定义属性:同步时在思源文档中设置同名属性,确保即使清除插件数据,关联依然存活
- 插件数据缓存:本地快速查找
这种设计确保了文档关联在插件重装、设备切换后依然有效。
核心功能
1. 单笔记同步
侧边栏图标 🔄,点击即可将当前笔记与思源中对应文档进行双向同步。插件会自动判断哪一边内容更新,进行正确的推送或拉取。
2. 批量同步 + 遗弃文档清理
🔄 批量同步按钮会遍历所有已关联的笔记,逐一执行双向同步。同时,它会扫描思源中带有 custom-si-push-id 属性的文档——如果某个文档在 Obsidian 中已被删除,但思源中还在,就会被自动清理(硬删除)。
这解决了"Obsidian 删了笔记,思源里还留着幽灵文档"的问题。
3. 搜索拉回
在插件侧边栏可以搜索思源中的所有笔记(按标题或路径),选中后一键拉回到 Obsidian。非常适合从思源中"打捞"旧笔记。
4. 冲突处理
当两边同时修改了同一篇笔记时,V2 提供三种冲突处理策略:
| 策略 | 说明 |
|---|---|
| 弹窗确认(默认) | 弹出冲突弹窗,展示两边内容,手动选择保留哪一边 |
| Obsidian 优先 | 自动以 Obsidian 内容为准,覆盖思源 |
| 思源优先 | 自动以思源内容为准,覆盖 Obsidian |
冲突弹窗的两侧分别用不同颜色标注 Obsidian 和思源的内容,直观对比差异。
5. 前端设置
- 服务器地址:思源的 Kernel API 地址(如
http://192.168.2.250:6806) - API Token:思源的 API 访问令牌
- 目标笔记本:推送笔记的目标笔记本(支持下拉选择 + 刷新)
- 默认文件夹:思源中的默认目标路径(如
/Obsidian) - 同步冲突策略:三种冲突处理方式任选
- 推送时包含 frontmatter:勾选后会把 Obsidian 的 frontmatter 也推送到思源
纯 JS 零构建设计
SiPush V2 延续 V1 的纯 JavaScript 开发理念——没有 TypeScript,没有 npm install,没有 esbuild。
插件只包含三个文件:
obsidian-si-push/
├── manifest.json # 插件元数据
├── main.js # 全部逻辑(约 800 行)
└── styles.css # 样式拖到 Obsidian 的 .obsidian/plugins/ 目录,重启,启用,即可使用。
技术亮点
gzip 压缩响应陷阱的修复
思源 API 默认返回 gzip 压缩的 JSON 响应。浏览器在处理 gzip 响应时不会暴露 Content-Length 头,如果用 parseInt(resp.headers.get("content-length")) 来判断响应是否为空,会得到 0,导致误判为空响应而跳过读取响应体——这正是 V2.0.18 之前的版本一直报"思源文档无内容"的根因。
V2.0.19 移除了 Content-Length 判断,只在 status === 204 时跳过响应体,其余情况一律读取 response.text() 解析 JSON。
内容规范化
Obsidian(Windows)和思源(Linux)的换行符不同(\r\n vs \n),且思源在导出 Markdown 时会自动添加 # 标题 行和 frontmatter。V2 通过三重防护确保哈希一致性:
stripSiYuanFrontmatter:剥离思源 frontmatter +# 标题行contentHash:统一换行符、去除尾部空白、剥离# 标题- 哈希对比时也剥离
# 标题,确保两端格式一致
遗弃文档清理的防重复删除
思源删除文档后,SQL 查询中仍会返回已删除的文档(归档到 Trash 但记录未删除)。V2 用 deletedPushIds 集合标记本轮已删除的文档,避免同一文档被反复删除并重复报入同步报告。
安装方式
- 从网盘下载插件包:
SiPush-obsidian-si-push-v2.0.19.zip - 解压到 Obsidian 的
.obsidian/plugins/obsidian-si-push/ - 重启 Obsidian,在「第三方插件」中启用 SiPush
- 在设置中配置思源服务器地址、Token、目标笔记本
- 开始使用侧边栏的 🔄 同步按钮
总结
SiPush V2 不仅仅是一个推送插件,而是一个完整的Obsidian ↔ 思源笔记双向同步解决方案。从哈希驱动的同步逻辑,到遗弃文档清理,到冲突弹窗——每一步都经过了实际使用中的打磨。
对于我这样的 Obsidian + 思源双栈用户来说,它解决了最核心的痛点:两边内容永远一致,不用手动来回复制。
项目信息
- GitHub: https://github.com/lwysg/obsidian-si-push
- 版本: V2.0.19
- 更新时间: 2026-07-03
暂无评论
还没有评论,快来抢沙发吧!