设计草案:本文记录一次以 Telegram 12.9.2 基线为背景的迁移方案,包含建议的分支名、阶段目标和历史提交 SHA。它不是当前仓库已执行的分支政策或可直接复制的发布命令。实际同步前请先检查
git remote -v、当前工作树、构建说明及正在使用的上游版本。
本方案用于长期同步官方 TelegramMessenger/Telegram-iOS,同时保留 Regram 功能,并把每次升级的冲突从“整个产品一次性冲突”拆分为“按功能处理的有限冲突”。
核心目标:
- 官方 Telegram 是唯一活跃上游。
- 不直接把新上游合并进当前高度修改的 legacy 工作树。
- Regram 改动按功能形成可重放、可测试、可删除的补丁序列。
- 每次发布都保留不可变的源码、IPA、dSYM 和回滚点。
- 上游结构发生变化时,优先适配新结构,不长期保留旧 Telegram 实现。
非目标:
- 不追求与 Telegram 每个提交实时同步。
- 不继续同时跟踪 Telegram 和 Swiftgram 两个活跃上游。
- 不把所有 Regram 改动重新压成一个五万行的大提交。
Swiftgram GitHub 历史表明,它并不是持续将 Telegram merge 到产品分支中,而是在每个版本重新建立产品树:
- 选择新的官方 Telegram 提交作为基线。
- 在该基线上应用一个完整的 Swiftgram 差异快照。
- 提交一个
Swiftgram Version X大提交。 - 在其后追加少量修复。
- 使用
release/*分支保存旧版本。
以当前公开的 Swiftgram master 为例:
- 官方 Telegram 基线:
6ad963e5b62d354da79040f388ae2b9132fb17b8 - 第一个 Swiftgram 提交:
5ed59da88839fb8cd802e5bf181ce4293044c8c1 - Swiftgram master:
cf8b23beaaac4126a396337ac2d5be13f9f76b66 - master 只比官方 Telegram 多 6 个提交。
- 第一个 Swiftgram 提交修改约 1,035 个文件,约
+53,465/-2,798行。 - Swiftgram 独有历史中没有正常的 Telegram 上游 merge commit。
这证明“在新上游基线上重新应用产品差异”是可行的,但单个巨大快照难以审查、定位和独立回滚。Regram 采用相同的重建方向,但将快照拆成有边界的功能补丁。
telegram:官方TelegramMessenger/Telegram-iOS,唯一活跃上游。origin:Regram 自有仓库。swiftgram:只用于历史追溯和行为对照,不再参与日常同步。
regram/main:当前集成版本。允许在新上游版本发布时重放补丁并更新提交历史。sync/telegram-<version>-<sha>:一次上游同步的工作分支。release/regram-<version>-<build>:已发布版本,只允许紧急修复,不重写历史。archive/legacy-<date>:迁移前旧架构的冻结分支。
release/*永远不可变,是正式发布和回滚依据。regram/main是集成指针,不作为长期发布凭证。- 如果需要重写
regram/main,只能在创建 release/archive 回滚点、CI 全部通过并通知协作者后使用--force-with-lease。 - 禁止对
release/*使用 force push。
Regram 改动应按以下顺序组织。每一组可以包含多个小提交,但不能与其他组混合。
00-build-branding- App target、Bundle ID、图标、资源、Info.plist、Watch、扩展和构建产物名称。
01-platform- App Group、重签名兼容、entitlement 检测、日志和共享容器定位。
02-settings-storageRGSimpleSettings、设置迁移、共享 UserDefaults 和账号级配置。
03-settings-ui- Regram 设置入口、设置页面、功能开关和本地化。
04-notifications- Notification Service 策略、空通知、置顶消息、mention/reply 和外部 session。
05-message-policy- 消息过滤、已读位置推进、反撤回和删除状态展示。
06-translation-and-metadata- 翻译后端、注册日期、消息 JSON 和相关数据服务。
07-privacy-and-pro- Ghost Mode、NSFW、本地 Premium、IAP 和 Paywall。
08-chat-and-ui- 上下文菜单、聊天列表、输入栏、图库、Badge 和其他界面增强。
09-localization-assets- Regram 字符串、图标和非代码资源。
约束:
- 一个提交只实现一个可描述的行为。
- 功能提交必须同时包含必要的 Bazel 依赖。
- 纯重命名、格式化和功能变化不得混在同一提交。
- 每个功能需要记录上游接触点和验证场景。
- 如果上游已经原生实现相同功能,应删除对应补丁,而不是继续覆盖上游实现。
首次迁移是一次性成本,不应直接对当前分支执行大规模 rebase。
- 完成或单独保存当前未提交的工作。
- 创建
archive/legacy-<date>。 - 为最近可发布构建创建 tag。
- 保存对应 IPA、dSYM、构建配置和版本号。
- 建立功能清单,标明保留、重写或删除。
- 从选定的官方 Telegram SHA 创建新的集成分支。
- 不直接 cherry-pick Swiftgram 的
Swiftgram Version X巨型提交。 - 按第 4 节顺序,从 legacy 树逐组迁移功能。
- 每完成一组立即构建和验证,再迁移下一组。
- 旧分支始终保持可构建,用于行为对照和回滚。
当前 Regram 与官方 Telegram 仍共享 6ad963e5b6 基线,因此应优先在下一次官方大版本出现前完成补丁拆分。
同步前必须满足:
- 工作树干净。
- 所有 submodule 干净且指向已提交 SHA。
- 当前
regram/main已有可回滚的 release/archive 引用。 - 当前版本的关键行为测试已通过。
- 已记录当前 Telegram 基线 SHA。
只获取上游,不立即改动产品分支:
git fetch telegram master
git log --oneline --decorate <old-telegram-sha>..telegram/master
git diff --stat <old-telegram-sha>..telegram/master从当前产品分支创建临时同步分支,并把 Regram 补丁重放到新 Telegram 基线上:
git switch regram/main
git switch -c sync/telegram-<version>-<short-sha>
git rebase --rebase-merges --onto telegram/master <old-telegram-sha>只有在首次补丁拆分完成后才使用上述 rebase。legacy 巨型快照不适合直接重放。
建议启用 Git 的冲突复用:
git config rerere.enabled true
git config rerere.autoupdate true按以下顺序解决冲突:
- 构建系统、target 和依赖。
- TelegramCore、Postbox 和数据类型。
- AccountContext、SharedAccountContext 和设置。
- TelegramUI 接入点。
- Notification、Share、Widget 等扩展。
- 资源、本地化、图标和产物脚本。
每完成一个补丁组就运行该组验证,不要等所有冲突解决后才第一次构建。
- 结构冲突默认保留上游新结构,再把 Regram 的最小行为重新接入。
- 禁止对大型冲突文件整体选择
ours或theirs。 - 不复制已经被上游删除的旧实现。
- 如果函数签名或数据流改变,应更新 Regram 适配层,而不是恢复旧签名。
- BUILD 冲突先保留上游依赖,再添加仍然必要的 Regram 依赖。
- 数据结构和持久化 key 的修改必须验证旧版本数据能否升级。
- Notification Service、Share Extension 等必须作为独立进程验证,不能只验证主 App。
- 每个非平凡冲突都记录:上游变化、保留的 Regram 行为、验证方式。
长期目标不是让 Regram 没有上游修改,而是让修改集中且可枚举。
推荐规则:
- Telegram 源码只能直接依赖一个轻量的
RegramIntegration层。 - Telegram 模块不得直接依赖具体的
RGProUI、RGGTranslate、RGPayWall等功能实现。 - 菜单、设置、消息可见性、通知和生命周期通过有限 Hook 接入。
- 新增上游修改必须加入 allowlist,并说明为什么现有 Hook 无法满足。
- 第一阶段将直接修改的上游文件控制在 40 个以内,长期目标为 20 个左右。
MARK: Regram只用于定位,不能代替模块边界和测试。
建议的集成接口:
MessageVisibilityPolicyMessageMutationPolicyContextMenuContributorSettingsSectionContributorNotificationPolicyOpenURLInterceptorAppLifecyclePlugin
同步分支合入前必须完成以下检查。
- 全新 clone + recursive submodule 能复现构建。
git submodule status --recursive无+、-或 dirty 状态。- 不存在依赖手工修改但未提交的 submodule。
- 不存在失效 symlink。
- 构建脚本查找的 IPA、dSYM 和 target 名称与实际产物一致。
- 官方 Telegram 基线在相同工具链下可构建。
- Regram simulator Debug 构建通过。
- Regram device Release 构建通过。
- Notification Service、Share、Widget 和 Watch 配置至少完成编译验证。
- IPA、dSYM、版本号和 UUID 收集正确。
- 设置默认值和迁移。
- App Group 和 entitlement 降级行为。
- 消息过滤和已读位置。
- 反撤回和删除状态。
- 翻译后端选择与 fallback。
- 通知静音、空通知、置顶消息和 mention/reply。
- Postbox 自定义数据向前兼容。
- 登录和账号切换。
- 消息收发、回复、转发、删除和编辑。
- 聊天列表、文件夹和搜索。
- Story 查看和 Ghost Mode。
- 前台、后台、锁屏通知。
- 设置页、Pro 状态和购买入口。
- Share Extension 和深链。
- 升级安装,不清除旧数据。
每次同步应新增一份 docs/upstream-sync/<version>.md,至少包含:
- 旧 Telegram SHA 和新 Telegram SHA。
- Regram 同步分支和最终提交。
- 上游主要功能变化。
- 发生冲突的文件和对应补丁组。
- 被删除、替换或暂时关闭的 Regram 功能。
- 已执行的自动和手工测试。
- 未验证场景与已知风险。
- 回滚 release/tag。
同步完成后:
- 保留旧
release/*分支和 tag。 - 从验证通过的同步分支创建新的 release 分支。
- 保存 IPA、dSYM、构建配置和符号 UUID 清单。
- 经过内部升级安装和通知场景验证后再推广。
- 观察期结束前不得删除旧构建产物。
如果新版本出现严重问题:
- 停止推广新 release。
- 回退到旧 release 构建,而不是在错误的新基线上继续叠加临时补丁。
- 数据迁移不可逆时,禁止直接安装旧版本;必须先提供兼容迁移或修复版本。
- 修复完成后重新执行完整同步门禁。
- 禁止直接在有未提交改动的工作树中同步上游。
- 禁止把 Telegram、Swiftgram 同时作为活跃上游进行双向 merge。
- 禁止继续生成类似
Swiftgram Version X的单个巨大产品快照提交。 - 禁止仅以“编译通过”作为同步完成标准。
- 禁止隐藏或丢弃无法理解的冲突。
- 禁止在没有 release/tag 回滚点时重写
regram/main。 - 禁止发布没有对应 dSYM 的构建。
建议按以下顺序落地:
- 修复仓库可复现性问题:submodule、CI 产物路径、失效 symlink。
- 建立 legacy 冻结分支和发布回滚点。
- 建立功能与上游接触点清单。
- 将现有改动拆分为第 4 节的补丁序列。
- 为高风险功能补充最低限度测试。
- 在当前 Telegram 基线上完成一次无版本升级的演练重建。
- 使用下一次 Telegram 更新执行完整同步流程。
- 根据实际冲突结果继续缩小上游接触面。