SeaMeet Desktop 来了 — 录制一切,不错过任何内容。免费下载 →

GitHub 同步设置

第 38 章:GitHub 同步设置

GitHub 同步把你的 SeaMeet 工作区变成一个住在你自己 GitHub 仓库中的私有、版本控制的 Markdown 树。每次你编辑笔记、重命名录音或调整 wiki 页时,SeaMeet 会在后台悄悄提交更改并把它推送到 GitHub。在另一台笔记本电脑上打开 SeaMeet,你的笔记会在第一次启动时拉下来——中间没有 Dropbox,没有 Seasalt 服务器在循环中。仓库是你的,数据是你的,并且如果你愿意可以在 github.com 上直接浏览它。

模型很简单:你的 GitHub 仓库是存储。SeaMeet 不运行同步服务。它在你的账户上安装一个小 GitHub App,获得一个每用户 OAuth 令牌,并使用该令牌直接推送和拉取 Git 提交。因为存储是 GitHub 的免费等级——为你提供无限私有仓库——同步实际上是免费的。并且因为每个 SeaMeet 工作区是自己的仓库,你可以把工作和个人工作区完全分开。


本章目标

读完本章后,你将能够:

  • 在你的账户或组织上安装 SeaMeet GitHub App
  • 通过 OAuth 授权 SeaMeet 并让它为你创建私有同步仓库
  • 阅读同步状态栏并理解同步状态机中的每个状态
  • 识别 OAuth 何时在后台自动刷新,何时你需要手动重新授权
  • 当同一笔记在两个设备上被编辑时解决同步冲突
  • 调整同步设置面板(自动同步、同步间隔、启动时同步)
  • 排查最常见的故障模式

前提条件

开始前,确保你有:

  • GitHub 账户 — 免费等级即可;你不需要 GitHub Pro
  • 有效的同步权益 — 包含在 BYOK Pro 和 Sync Pro 等级中。如果你的计费等级不包含同步,同步设置界面会显示 "Subscribe to enable sync" 横幅。计划详情见第 35 章:订阅与计费
  • 在 SeaMeet 中打开的工作区 — 同步附在活动工作区上,不是整个应用。如果你有多个工作区,每个都是自己的 GitHub 仓库。
  • 可用的互联网访问 — 设置流程会在你的默认浏览器中打开 GitHub

每工作区一个仓库。 SeaMeet 为你连接的每个工作区创建单独的私有仓库。这让工作和个人笔记保持干净隔离,意味着你可以断开一个而不触及另一个。


分步设置

首次设置大约需要 90 秒:在 GitHub 上授权 SeaMeet、让它创建你的仓库、等待初始上传,你就完成了。

步骤 1:打开同步设置

  1. 点击 Settings 齿轮图标
  2. 在左侧栏打开 Sync 标签
  3. 你会看到 "Sync with GitHub" 标题卡

如果你看不到 Sync 标签,你的订阅等级不包含同步——见第 35 章升级。

如果你看到 "Back up your notes to a private GitHub repo with BYOK Pro" 横幅,你有免费账户。点击横幅打开付费墙,或跳过本章其余部分直到你订阅。

步骤 2:点击 "Set Up GitHub Sync"

同步设置空状态显示三个好处磁贴("Free & private"、"Effectively unlimited"、"One repo per workspace")和底部的主 Set Up GitHub Sync 按钮。

点击它。你的默认浏览器会打开到 GitHub 授权页面。

步骤 3:安装 SeaMeet GitHub App(一次性)

你第一次授权 SeaMeet 时,GitHub 会要求你在你的账户上安装 SeaMeet GitHub App。这是每 GitHub 账户(或每组织,如果你想同步到组织拥有的仓库)一次性的步骤。

在 GitHub 安装页面上:

  1. 选择你想要 SeaMeet 写入的账户或组织
  2. 选择 "All repositories""Only select repositories" — SeaMeet App 需要 contents: writeadministration: write 权限以便它可以代你创建同步仓库
  3. 点击 Install & Authorize

GitHub 把你弹回 SeaMeet。同步设置面板现在显示:

┌──────────────────────────────────────────────────────┐
│   ✓ Authorized                                       │
│   ⟳ Creating repository & uploading...               │
└──────────────────────────────────────────────────────┘

为什么是 GitHub App 而不是普通 OAuth 令牌? GitHub Apps 有细粒度的每仓库权限和轮换刷新令牌。SeaMeet 只对你明确选择的仓库有写入访问,OAuth 访问令牌每 8 小时过期——即使泄露,窗口也会很小。(关于 SeaMeet 如何把它对你保持隐形,见下方的 OAuth 自动刷新 部分。)

步骤 4:仓库创建(自动)

SeaMeet 现在代你调用 GitHub API 并:

  1. 创建以你的工作区命名的私有仓库(例如 seameet-work-notes
  2. 如果你的工作区文件夹中还没有本地 Git 仓库,则初始化一个
  3. 运行 git init,写入排除音频/视频/截图文件的 .gitignore,并做一次初始提交
  4. 把新 GitHub 仓库添加为 origin
  5. 推送初始提交

你会看到侧边栏底部的状态栏过渡:

Creating repository...  →  Syncing...  →  Synced · just now

就这样。你的工作区现在由 GitHub 支持。

步骤 5:第一次同步自动运行

从现在起,每当你有未保存的更改时,SeaMeet 自动每 5 分钟(默认)提交一次,并在每次提交后立即推送到 GitHub。在下次 SeaMeet 启动时,应用甚至在你开始编辑前就从 GitHub 拉取——所以在另一设备上的更改在应用打开的瞬间出现。


同步状态机

SeaMeet 的 SyncManager 运行一个小状态机并把其当前状态广播给渲染器。侧边栏 SyncStatusBar 和同步设置面板都读取此状态。理解状态有助于你准确阅读 UI。

                      ┌─────────────┐
                      │    idle     │ ◄──────┐
                      └──────┬──────┘        │
                             │ 文件变化       │
                             ▼               │
                      ┌─────────────┐        │
                ┌────►│   pending   │        │
                │     └──────┬──────┘        │
       文件     │            │ 提交计时器     │
       变化     │            ▼               │
                │     ┌─────────────┐        │
                │     │ committing  │        │
                │     └──────┬──────┘        │
                │            ▼               │
                │     ┌─────────────┐        │
                │     │   pushing   │        │
                │     └──────┬──────┘        │
                │            ▼               │
                │     ┌─────────────┐        │
                │     │   synced    │── 5s ──┘
                │     └─────────────┘
                │
                │     ┌─────────────┐
                ├─────┤   pulling   │  (启动或推送被拒绝)
                │     └─────────────┘
                │
                │     ┌─────────────┐
                ├─────┤  conflict   │  → 用户解决 → syncing → synced
                │     └─────────────┘
                │
                │     ┌─────────────┐
                ├─────┤   offline   │  → 网络恢复 → 重试
                │     └─────────────┘
                │
                │     ┌─────────────┐
                ├─────┤   timeout   │  → 用户点击 Retry
                │     └─────────────┘
                │
                │     ┌────────────────┐
                └─────┤ token-expired  │ → 重新授权卡片
                      └────────────────┘

下面是每个状态在 UI 中的含义:

状态状态栏标签含义
idle"Synced · 2 min ago"无待处理,最后提交干净
pending"Pending..."你有未保存更改;提交计时器会在下一间隔触发
committing"Syncing..."本地 Git 提交进行中
pushing"Pushing..."本地提交完成;推送到 GitHub
pulling"Pulling..."启动同步,或推送被拒绝且我们先在拉取
syncing"Syncing..."在冲突解决后完成 rebase
synced"Synced · just now"刚完成的成功;显示 5 秒,然后返回 idle
conflict"Sync conflict"本地和远程都编辑了同一文件。UI 显示冲突解决流程。
error"Sync error"非网络、非冲突的失败(例如 git 失败)。以指数退避自动重试最多 5 次。
offline"Offline"网络不可达。会在下一次文件变化或 60 秒后重试。
timeout"Sync timed out"git 命令耗时超过 60 秒(见下方同步超时保护)
token-expired"Re-authorize"OAuth 刷新失败,用户必须手动重新授权
installing-app"Installing GitHub App..."等待用户在浏览器中完成 GitHub App 安装步骤
creating-repo"Creating repository..."设置流程正在创建 GitHub 仓库并推送初始提交

如果状态栏显示旋转器,那是正常的后台活动。如果它是琥珀色或红色,见下方的故障排查部分。


OAuth 自动刷新

GitHub Apps 颁发每 8 小时过期的用户访问令牌,加上有效期 6 个月的刷新令牌。SeaMeet 为你管理这些,所以你几乎不必想到它。

工作原理:

  1. 当 SeaMeet 即将推送或拉取时,SyncManager._refreshTokenIfNeeded() 检查当前令牌是否在接下来 5 分钟内过期。
  2. 如果是,SeaMeet 用存储的刷新令牌调用 GitHub 的 /login/oauth/access_token 端点。GitHub 返回新访问令牌并轮换刷新令牌。SeaMeet 把两者写回到磁盘上加密的令牌文件。
  3. Git 命令然后用刚刚刷新的令牌运行。你在屏幕上看不到任何东西——整个刷新远不到一秒。

短暂故障处理: 如果刷新调用因网络不稳或 GitHub 返回 5xx(一个 REFRESH_NETWORK_ERROR)而失败,SeaMeet 不会丢弃现有令牌。相反同步进入 offline 状态并稍后重试。这很重要,因为现有令牌可能仍然有效多几分钟——在短暂网络抖动时丢弃它会不必要地把你从同步中登出。

并发刷新合并: GitHub 每次你使用刷新令牌时都轮换它,所以两个并发刷新会竞争,其中一个会使另一个无效。SeaMeet 把并发刷新调用折叠为单个进行中的 Promise (_refreshPromise),所以启动同步和带重试的推送从不就轮换令牌打架。

当刷新真的失败时: 如果 GitHub 返回 REFRESH_TOKEN_EXPIRED——意味着 6 个月刷新令牌已过期或被撤销——SeaMeet:

  1. 从磁盘删除加密的令牌文件
  2. 进入 token-expired 终止状态
  3. 在同步设置中显示琥珀色卡片:
┌──────────────────────────────────────────────────────┐
│ ⚠  GitHub 授权已过期。请重新                          │
│    授权以恢复同步。                                   │
│                                                       │
│  [ ↻ 重新授权 GitHub ]                                │
└──────────────────────────────────────────────────────┘

点击 重新授权 GitHub。你被送回 OAuth 流程——但因为 GitHub App 已安装,这是单次点击确认,在约 10 秒内完成。SeaMeet 然后在下次推送前从你的本地 git config 剥离任何过期令牌(旧令牌可能嵌入在 origin 的 URL 中),所以你不会在死凭据上循环。


同步超时保护

如果网络在中途沉默,Git 命令可能永远挂起——TCP 套接字可能处于半开状态而从不抛出错误。SeaMeet 用 60 秒 AbortController 超时包装每个 Git 推送和拉取。

如果推送或拉取在 60 秒内没完成,SeaMeet:

  1. 中止 git 子进程
  2. 进入 timeout 状态
  3. 在同步设置中显示琥珀色卡片:
┌──────────────────────────────────────────────────────┐
│ ⚠  同步超时。这可能由网络问题或                       │
│    过期的 GitHub 授权引起。                          │
│                                                       │
│  [ ↻ 重试同步 ]   [ 重新授权 GitHub ]                 │
└──────────────────────────────────────────────────────┘

重试同步 再次运行 commitNow。如果你认为网络只是短暂中断,这是正确的按钮。重新授权 GitHub 再次运行 OAuth 流程;如果超时持续复发,请点击这个,这通常意味着问题是你的令牌而非网络。

即使你不点击任何东西,状态约 30 秒后也会自动返回 idle——同步会在下次文件变化时重试。


冲突解决

冲突发生在同一文件自上次同步以来在两个设备上被编辑时。示例:你在笔记本电脑上的 meetings/2026-06-03-standup.md 中写了一段,然后在朋友机器上又编辑了同一段。当第二台设备推送时,GitHub 拒绝推送,因为历史发散。

SeaMeet 通过以下方式处理:

  1. 用 rebase 拉取远程更改
  2. 检测合并冲突标记
  3. 进入 conflict 状态
  4. 在侧边栏状态栏(变成可点击的)和同步设置冲突面板中显示冲突

冲突解决模态

当同步处于 conflict 时点击状态栏会打开冲突解决模态

┌──────────────────────────────────────────────────────────┐
│  ⚠  同步冲突                       1 / 2            [×]  │
├──────────────────────────────────────────────────────────┤
│                                                          │
│  "2026-06-03-standup.md" 在另一设备上被更改。            │
│                                                          │
│  ┌────────────────────────┐  ┌────────────────────────┐  │
│  │ ✎  手动编辑            │  │ ✦  助手合并            │  │
│  └────────────────────────┘  └────────────────────────┘  │
│                                                          │
└──────────────────────────────────────────────────────────┘

你有两个选项:

手动编辑 — 在系统默认编辑器中打开冲突文件,带 Git 标准的 <<<<<<< / ======= / >>>>>>> 标记。编辑文件解决它们,保存,然后回到 SeaMeet 并点击 Done。SeaMeet 暂存解决的文件并继续 rebase。

助手合并(仅 BYOK Pro,需要 AI 助手已配置)— 把两个版本发送给你配置的 AI 助手(GitHub Copilot 或 Claude Code,见第 36 章:BYOK 设置指南)并要求它生成保留两边意图的合并版本。助手的输出自动暂存;你会看到 "Finishing sync..." 旋转器同时 rebase 完成。

如果一次有多个冲突,模态显示计数器 (1 / 22 / 2),同步设置冲突面板中的雪佛龙箭头让你逐一浏览它们。

"保留我的" / "保留它们的" / "保留两者" 选项在你进入手动编辑器时自然出现:在标记之间只留下你版本的文本、只留下远程版本的文本,或交错两者。助手合并按钮实际上做 "智能地保留两者"。

如果你犯错怎么办? 同步冲突是非破坏性的。Git 在索引中保留原始 "ours" 和 "theirs" 内容,getConflictVersions(filePath) 可在解决期间任何时候检索其中任一。你不会意外丢失工作。


同步设置面板

连接后,同步设置(Settings → Sync)在单个屏幕上给你一切:

┌─────────────────────────────────────────────────────────────┐
│  ✓ 同步 & 备份                                              │
│  你的笔记和 wiki 被自动同步到 GitHub。                      │
│  音频录音、视频录音和截图                                   │
│  不被同步。                                                 │
├─────────────────────────────────────────────────────────────┤
│  ⓘ  https://github.com/you/seameet-work-notes                │
│  🕒 最后同步:4 分钟前                                       │
├─────────────────────────────────────────────────────────────┤
│  自动同步                                       [ ON  ◉ ]   │
│  同步间隔                                       [ 5 分钟 ▾ ]│
│  分支                                                main   │
│  最后同步                                      4 分钟前     │
├─────────────────────────────────────────────────────────────┤
│  更改时自动同步                                 [ ON  ◉ ]   │
│  启动时同步                                     [ ON  ◉ ]   │
├─────────────────────────────────────────────────────────────┤
│  [ ⤓ 立即同步 ]                                             │
├─────────────────────────────────────────────────────────────┤
│  [ ↗ 在 GitHub 上查看 ]    [ 断开连接 ]                     │
└─────────────────────────────────────────────────────────────┘

控件,从上到下:

  • 自动同步 — 后台提交计时器的主切换。关闭意味着 SeaMeet 只在你点击 立即同步 时提交。
  • 同步间隔 — 提交计时器触发的频率。选择是 1 / 5 / 10 / 30 分钟。默认 5 分钟。对于活跃记笔记,1 分钟间隔很好;对于你宁愿批处理提交的低编辑工作区,30 分钟是好的。
  • 分支 — SeaMeet 同步到的 Git 分支。几乎总是 main。UI 中只读。
  • 最后同步 — 上次成功推送的相对时间戳。
  • 更改时自动同步 — 开启时,每次本地提交后立即推送(典型情况)。关闭时,SeaMeet 在本地提交但只在你点击 立即同步 时推送。如果你想批处理推送(例如在按流量计费的连接上)有用。
  • 启动时同步 — 开启时,应用启动的瞬间 SeaMeet 从 GitHub 拉取。除非你连接非常慢,否则推荐。
  • 立即同步 — 强制立即提交并推送循环。不等待计时器。在关闭笔记本电脑前有用。
  • 在 GitHub 上查看 — 在浏览器中打开仓库。
  • 断开连接 — 清除存储的 OAuth 令牌,删除加密的令牌文件,并从你的本地 Git 仓库移除 origin。你的本地 Markdown 文件和 Git 历史未被触及——只是到 GitHub 的链接被切断。

同步什么(不同步什么)

这在部分索引中有文档,但值得在这里重复:

已同步未同步
笔记(.md 文件)音频录音(.webm.mp3
Wiki 页(.md 文件)视频录音(.webm.mp4
录音清单(元数据 JSON)截图(.png.jpg
AI 摘要和转录缓存的 AI 生成
Wikilink 图谱应用设置
.gitignore编辑器临时状态

SeaMeet 写入的 .gitignore 排除所有大型二进制类别。这是有意的:GitHub 的免费私有仓库上限是 1 GB,单个 30 分钟视频会独自吃掉它。SeaMeet 把媒体保留在你的本地磁盘上,只同步轻量级 Markdown。

如果你想要完整媒体同步,那是 Sync Pro 等级——见第 35 章。


故障排查

点击 Set Up GitHub Sync 后立即 "授权失败"

原因和修复:

  • 弹窗阻止 — 如果没有浏览器窗口打开,你的 OS 或浏览器可能阻止了启动。再次点击 Set Up GitHub Sync 并确认任何弹窗提示。
  • 你拒绝了 GitHub App 权限 — 返回流程并接受 contents: write + administration: write 范围。没有 administration: write,SeaMeet 无法为你创建仓库。
  • 状态不匹配错误 — 关闭可能在同一 OAuth 流程上竞争的其他 SeaMeet 窗口,然后重试。

设置期间 "仓库权限" 错误

错误读起来像 "GitHub App has 'contents: read' permission, but needs 'contents: write'."。这意味着你安装了较旧版本的 App。

修复:

  1. 打开 github.com/settings/installations
  2. 在列表中找到 SeaMeet 并点击 Configure
  3. Repository permissions 下,把 ContentsAdministration 改为 Read and write
  4. 保存,然后卸载并重新安装 app — GitHub 只在重新安装时应用新权限
  5. 在 SeaMeet 中重新运行 Set Up GitHub Sync

"无法到达 GitHub" / 同步卡在 "Offline"

网络故障。SeaMeet 会自动在以下时机重试:

  • 你做任何文件更改时(触发立即重试尝试)
  • 上次重试后 60 秒过去

如果你的网络回来但同步几分钟后仍显示 Offline:

  1. 点击 立即同步 强制重试
  2. 如果超时:检查你的防火墙没有阻止 github.com
  3. 作为最后手段,重启 SeaMeet — 启动同步会在启动时触发

同步卡在 "Pending"

这通常意味着自动提交计时器还没触发。默认每 5 分钟触发。不想等?点击 立即同步

如果 立即同步 没把同步移过 Pending,检查:

  • 你在包含同步的计费等级上吗?打开同步设置——如果你看到订阅横幅,同步在权益层被禁用。
  • Markdown 树之外有未提交的更改吗?自动提交计时器只在 _pendingChanges 非空时触发。

"我看到 token-expired 卡片"

这是 OAuth 刷新生命周期的预期结束——你的 6 个月刷新令牌过期、你撤销了 GitHub App,或你更改了 GitHub 密码(这使所有 OAuth 令牌无效)。

修复:在卡片中点击 重新授权 GitHub。流程与初始设置相同但跳过 GitHub App 安装步骤(你已经安装了它)。约 10 秒。

冲突解决面板不关闭

面板只在列表中所有冲突都解决时关闭。如果你看到计数器 (1 / 3),使用同步设置冲突面板中的雪佛龙箭头逐步浏览剩余文件。每一个都需要明确解决(手动编辑 + Done,或助手合并)。

如果面板坚持有冲突但你在文件中看不到任何标记,点击 立即同步 — 过期的 conflict 状态在下次成功同步尝试时会被清除。

"推送被拒绝" 循环

如果同步在 pushingpulling 之间反复交替,GitHub 在拒绝你的推送因为远程一直前进。这可能发生在:

  • 另一个 SeaMeet 实例正在对同一仓库运行并比这个更快地推送 — 关闭另一个实例。
  • 某人(或某工具)在从 SeaMeet 外部提交到 GitHub 仓库 — 暂停外部工具直到你的本地克隆追上。

安全说明

OAuth 令牌存储位置: 通过 Electron 的 safeStorage API 在你的 OS 钥匙串中。在 Windows 上是 DPAPI,在 macOS 上是 Keychain Services,在 Linux 上是 libsecret。加密 blob 以 0o600 文件模式写入 <userData>/github-token.enc。文件持有访问令牌、刷新令牌、过期时间戳,以及 GitHub App 的 client ID、client secret 和 slug。

不存在 argv 中的内容: OAuth 令牌从不作为 -c http.extraHeader=... 参数传给 git,因为 argv 对通过 ps aux 的其他用户可见。相反 Authorization 头通过 GIT_CONFIG_PARAMETERS 环境变量注入,它对进程私有。同一机器上的其他用户看不到你的令牌。

在仓库中磁盘上的内容: 纯 Markdown 文件。没有令牌、没有密钥、没有凭据。.gitignore 排除媒体文件,但你仍应避免把密钥粘到笔记正文中——那些会同步。

撤销访问: 要立即切断 SeaMeet 对仓库的访问,在 github.com/settings/installations 卸载 SeaMeet GitHub App。下次同步尝试会失败并显示 token-expired,SeaMeet 会清除其本地令牌。你的本地笔记未被触及。


快速参考

┌─────────────────────────────────────────────────────────────┐
│                   GITHUB 同步                               │
│                   快速参考                                  │
├─────────────────────────────────────────────────────────────┤
│  打开同步设置          │ Settings → Sync                    │
│  首次设置              │ 点击 "Set Up GitHub Sync"          │
│  所需范围              │ contents: write, admin: write      │
│  仓库命名              │ 每工作区一个私有仓库               │
├─────────────────────────────────────────────────────────────┤
│  默认同步间隔          │ 5 分钟(1 / 5 / 10 / 30)          │
│  强制同步              │ "立即同步" 按钮                    │
│  推送时自动同步        │ 开(同步设置中的切换)             │
│  启动时同步            │ 开(同步设置中的切换)             │
├─────────────────────────────────────────────────────────────┤
│  OAuth 刷新边界        │ 过期前 5 分钟                      │
│  Git 命令超时          │ 60 秒(AbortController)           │
│  自动重试限制          │ 5 次尝试,指数退避                 │
│  令牌存储              │ OS 钥匙串(safeStorage)           │
├─────────────────────────────────────────────────────────────┤
│  冲突 UI               │ 处于冲突时点击状态栏               │
│  手动解决              │ 编辑标记 → Done                    │
│  助手合并              │ BYOK Pro + AI 助手已配置           │
├─────────────────────────────────────────────────────────────┤
│  断开连接              │ Sync Settings → Disconnect         │
│  从 GitHub 撤销        │ github.com/settings/installations  │
│  查看仓库              │ "View on GitHub" 链接              │
└─────────────────────────────────────────────────────────────┘

最后更新:2026-06-04

第 37 章:GitHub Copilot 提供方 | (手册结束 — 返回 索引

Published: