上游做出了破坏性变更 上游出现了一个尚未修复的 BUG 上游缺乏本项目需要的功能特性

  • 更新
  • 沟通
  • 贡献

思路

目前主要推荐的方案还是将自己二次开发的代码, 这部分因为是比较熟悉的. 进行重构, 尽可能让他对上游相关文件的修改小, 然后拆分成patch形式, 这里的一个点是由于我们不太可能合并到上游, 因此后续对上游的更新是必然要合入的.

这里有一个最大的冲突, 从维护成本角度, 合入上游最低. 只需要处理一次冲突. 因此我们的方案里, 除了核心代码的部分, 其实缺陷部分, 可能是推荐向上游合入的.

如何合入更新

此时就有两种选择 1. 我们作为patch, 使用高版本社区合入时, 处理我们的patch的冲突进行合入. 2. 社区的更新作为patch, 我们手动合入我们的. 这块的比较其实还是显而易见的,社区的更新人员远不止10多人, 每历经一批小版本提交的commit 远比我们多. 而且对commit的理解程度, 显然是维护人员更高. 我们去理解并合入社区的修改的工作量相当巨大. 反而还不如仅维护我们自己修改的patch部分.

社区其他人也是这么思考的, 我们作为下游, fork的人员, 开发人力是没有上游多的.

下一个问题, 我们的patch应该如何管理?

  1. 类似centos/openEuler下游社区那种, 创建单独的patch文件, 和社区版本的release版本压缩包放一起维护

那这个patch的生成是手动吗? 是否有办法批量生成patch? 从而减少维护成本? [没办法, 有冲突, 不存在批量]

svn应该是可以基于commit拆分patch.

但是svn的commit提交是无法覆盖的, 那么我们做重构的动作, 也就没办法变成基于一个稳定的设备版本拉出的多条commit操作了. 要做这个动作, 就必须是基于git完全完成重构之后, 才能往svn合入了. 然后此时拉出patch.

而这个patch, 后续会在每次更新版本时, 需要重新处理一次.

那这样的话, 看着好像确实没必要单独维护一个svn来放源码了? 因为只是为了生成patch, 完全可以本地基于release版本初始化, 然后手动合入patch, 并修改. 修改后本地commit导出新的patch.

那重构的过程, 是否有必要初始化git? svn是否有帮助? (svn没有帮助, git merge有帮助)

重构的过程, 其实也可以svn. 只需要选择指定2个版本之间输出patch即可. 且最终这个分支就停止迭代了其实. 所以这个源码分支, 是可以类似git的branch那样, 持久保留的. 就是确实没有社区那种rebase的git log那么干净

如果需要, 倒也可以除了开发分支, 拉出一个重构完成后的干净分支. 这个比较推荐, 作为最终归档.

待确认效果: git merge具有比patch更强的处理冲突能力, 对于行定位错误, git merge的算法一定程度上可以处理成功. 因此, 我们在处理冲突时, 是需要有一个具有我们自己的修改的git分支的.

具体差异参考下文

修改开源软件以后仍保持更新同步_51CTO博客_软件源更新失败

(关键, 值得专项进行讨论设计)其中最重要的部分就是重构的解耦性了. 决定了后续每次冲突处理的共性基本代价. (社区重构引发的那种就没办法了), 其实和开源合规性的关联也比较大. 拆出独立库加载, 也刚好符合了LGPL约束.

测试先行?
TODO: 找一条这个思路重构的?
PR拆解成小PR的 RWL缓存实现

原始PR Sharded BlueStore - 3 - resharding tool by aclamk · Pull Request #29087 · ceph/ceph

拆解小PR rbd/cache: Replicated Write Log core codes part 1 by lixiaoy1 · Pull Request #31279 · ceph/ceph rbd/cache: Replicated Write Log core codes part 2 by yison · Pull Request #31963 · ceph/ceph

backport的脚本做了些什么? 描述了backport所需遵守的规则

  • 使用github token和trakcer.ceph.com token指定源PR和目标合入的里程碑分支版本, 自动化创建关联tracker issue单和PR
  • 自动根据需要backport的PR拉出对应的backport用分支并开发cherry-pick 合入PR中的commit, 直到第一条冲突报错, 处理后继续调用会继续自动合入.

ceph/SubmittingPatches-backports.rst 在 main ·ceph/ceph

我们似乎没有一个关联系统, 类似github的PR, 发起backport的PR, 关注进展.

对于考虑合入的点, 要保持和上游的沟通(话语权, 方案是否被上游接受挺考究上游社区对你的信任度)

开源产品的维护思路?

一般社区流程是,

  • 基线分支
  • 轻量开发分支(轻量级的, 短时存在, 需要临时处理的冲突一般较少)
  • 长期特性开发分支
    • 独立迭代, 分支内部评审合并轻量开发分支(这里的轻量开发分支指代的是个人branch, 因为一般有合并的权限管理)
    • 定期合并上游的变更
    • 稳定后合入基线分支
  • 发布分支(长期, 后续只cherry-pick基线分支的一些关键必须得修改) ### ceph 像ceph, 基线开发, 然后到时间拉出分支, 后续如果有要合入的功能或缺陷修复, 通过backport进行合入, 此时负责人对代码进行微量重构. 相比我们的更新基础版本后需要做冲突处理, 他们是在提交时就进行了.

一般ceph在拉出新分支时, 一般这个版本要使用的功能应该

TODO: 看看squid分支上, 和master分支, 一些特性究竟谁先谁后?

参考这两条, 从id上就很明显了, squid分支的提交是backport的

TiFlash

Merge TiKV 6.0 into Proxy by CalvinNeo · Pull Request #55 · pingcap/tidb-engine-ext

android kernel

trunk->LTS stage暂存进行测试->LTS分支

Linux 稳定内核版本合并  |  Android 开源项目  |  Android Open Source Project

其他公司的考量

企业与开源软件:「上游优先」,与善良无关 | 爱范儿

上游优先可以显著降低自己的维护成本, 技术债, 因此对于非关键特性, 合入上游对于降低自己将来的维护成本, 以及借助社区的能力, 非常关键.

生产力供应不足的社区创造的 Fork 则会在短暂的喧闹后自然地被遗忘,其收益远远不如采用 Upstream First 战略。[^6]

回归上游优先的例子:著名的商业案例有Google之于Android内核分支、AWS终究还是拥抱KVM,独立维护XEN太吃力

  1. 把开源项目新的 feature 更新到已经魔改过的自用版本上的最佳姿势是什么? - V2EX
  2. 【综合】上游优先地开发-华为开发者论坛 | 华为开发者联盟
  3. Git 分支管理与版本发布 | 夜天之书
  4. 开源不是商业模式 | 夜天之书
  5. 经验分享: 上游优先的故事 | 开源小镇
  6. 2022-25: 开源当以上游优先
  7. 我们如何消除两个开源项目之间长达 4 年的分叉-PingCAP | 平凯星辰