11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

如何管理一个大型开源仓库?

  • 2019-07-21
  • 本文字数:3543 字

    阅读完需:约 12 分钟

如何管理一个大型开源仓库?

作者所在的飞冰(ICE)团队在 2018 年 2 月开源了 alibaba/ice 这个仓库,经过不到一年的时间终于在 2018 年末达到了 1w+ stars 的里程碑,在管理这个仓库以及运营社区的过程中我们积累了一些或大或小的最佳实践,希望能分享出来帮助到其他开源或者没开源的 git 仓库管理者。


合理的拆分仓库

当我们说管理仓库的时候,其实面向的不是一个单一的仓库,而是一个产品、一个项目甚至一个业务,这背后可能会有多个仓库也可能只有一个仓库,因此在前期的规划上要尽量梳理清楚,核心避免两个误区:


误区 1:每个职责都建一个仓库

这个方案可能是多数人的直觉反应,但是这种方式会让产品对应的仓库数快速增多,导致长期管理成本陡增:


  • 仓库权限管理成本高且容易混乱

  • 代码开发提交成本高

  • issue/PR 太过零散,难以统计管理

  • ……


实际上,飞冰(ICE)原先在内部的时候,我们开发了很多业务组件,每个业务组件都是一个单独仓库,然后最近在做统一升级(工具、规范或者其他变更导致)的时候给我带来非常大的困扰:


  • 有的组件(仓库)已经不再维护但没有任何标记

  • group 权限管理太过松散导致出现一些跟官方无关的组件

  • 升级过程中需要频繁切换仓库操作


因此,我们需要避免过于零散的管理方式,结合实际场景做适当的聚合。


误区 2:所有的职责都用一个仓库承载

在前端社区里,随着 lerna 这个批量发布包工具的出现,这种方式越来越流行,一些非常热门的项目比如 babel、React、jest 等都逐渐迁移到这个方案。先抛开 lerna 这个工具提供的能力,这种聚合式的管理方式给仓库管理者节省了很多成本,比如:


  • 只需要管理一个仓库

  • issue/PR/wiki 等都收敛到一个地方管理


但是在实践这种方式的时候有可能会走偏,还是以我所在的 ICE 团队做反面教材,踩了误区 1 的坑之后,在做开源版本的时候我们果断把所有包都放到同一个仓库,然后通过目录结构来保证职责清晰,这个方式也同样如上面所提到的给我们的管理带来了诸多便利,但在经历了一年的迭代之后目前也遇到了一些问题:


  • 职责多代表代码多,然后随着历史记录的增长,仓库 clone 速度一日不如一日,尤其在一些小公司的慢速网路环境下(即便加了 --depth)

  • 目录结构较为复杂,对有心贡献代码的社区同学不够友好


因此我们推荐「在方案 2 的基础上按照职责再做一层拆分」,结合 alibaba/ice 这个仓库,我们已经通过职责将 ice-devtools/ice-scripts/react-materials 等拆为独立仓库,这些仓库职责上足够清晰同时相关依赖聚合在一起不至于太过分散。


建立团队内的操作规范

笔者曾经有幸参与过淘宝前端团队的代码规范制定以及相关工具落地,因此深知规范之于团队的重要性,同时也有一些制定规范的原则:


(1) 规范首先保证正确,其次提升质量;


(2) 规范不能过多影响到效率(两者的权衡需要结合实际场景)。


以下就是我们目前在遵循的一些规范:


保护分支


根据仓库情况设定保护分支,禁止直接往保护分支提交代码,在非常特殊的情况下 admin 账户可以绕过。


新建分支规则


  • 分支名称需要有语义,比如 ice-scripts/fix-foo-bug

  • 如果需求比较简单,时间周期比较短,那么直接从 master 切一个分支,然后通过 PR 合并后到 master,合并之后发布对应包的版本

  • 如果需求包含多个变更点,比如 iceworks 发布版本,往往涉及到多个功能点,开发周期一般会在一周左右,如果每个 PR 都往 master 上合并,很难把控整体的进度。因此我们有以下约定:

  • a. 先从 master 切出 release 分支(如 release/iceworks-2.16.0),然后提一个基准 PR,PR 中需要补充当前版本包含的功能列表以及发布先后顺序等,该 PR 主要用于管理此次版本开发进度,release 分支不允许直接推送代码,同时合并到 master 时也无需 Review

  • b. 然后每个功能变更都从 release 分支切出新分支,同时 PR 也需要合并到对应 release 分支,切出的分支不需要包含版本信息(比如 iceworks/fix-xxxx 即可)

  • c. 等所有 PR Review 完成并且合并到 release 分支之后,在 release 分支进行发布,发布完成后再将 release -> master 的 PR 合并(此处不在 master 分支发布的原因是担心发布时可能会出各种问题,需要再次做代码变更)


commit message 规范


好的 commit message 可以让人快速了解代码意图,加速 review 进程,未来对于整个代码仓库的历史追溯也会更加方便,关于这一点社区有足够多的规范可以参考,此处不再一一赘述,有兴趣可以参考末尾的参考链接。


PR 合并流程


github 默认提供了三种合并 PR 的方式,关于三种方式的区别可以参考文末的相关链接,我们认为大多数情况应该选择 Squash and merge,因为 squash 会将当前 PR 的多个 commit 合并,让整个提交历史更加干净清晰。但是在将上文提到的 release 分支合并到 master 时建议使用普通 Merge,因此此时我们需要保留那些有效的 commit 记录。同时在合并 PR 的时候 Reviewer 有责任重新编写 commit message 以保证语义更加准确。


这里简单追溯一点历史:在最早期的时候,github 还没有提供 squash merge 的方式,当我们向开源仓库提交一个 PR 时,在仓库作者 review 完成之后一般会要求提交者将 commit 合并,因此很多人都有谷歌过「如何合并 commit」这样的关键词,而如今只需要点一下按钮即可,这也是工具对效率提升的一个体现。


发布流程

对于管理工具包的同学,都应该熟悉并且遵循 Semver 规范(语义化版本),这是原则,在此基础上需要遵循以下规范:


  • 测试版本:版本号需要遵循 x.y.z-n 的规则,通过 npm publish --tag beta 发布,很多同学包含笔者本人经常会忘记 --tag beta,不知道有没有更加有效的方式约束?

  • 正式版直接通过 npm publish 发布

  • 正式版本发布之后,需要同时创建对应的 git tag,tag 命名规则:产品名/x.y.z,比如 ice-scripts/1.0.2,然后在 GitHub 上填写 Release 信息


其他

如何保证规范落地

结合曾经在淘宝前端团队推动的规范落地以及当下在 ICE 团队制定的规范,两点结论可供参考:


  • 规范需要保证多数人认可,然后由松到紧逐步迭代,人跟着规范逐步成长

  • 小团队靠素养,大团队靠工具:在小团队内制定规范,需要做的就是反复强调,逐渐让每个人形成习惯;而在大团队里显然是没法关注到每个人的,此时需要借助工具,比如 eslint,commit-check 以及像门神这种强流程的工具


如何迭代历史版本

上文说的一些工具包的发版,假设我有一个工具包 ice-scripts 在 1.6.5 的基础发布了一个 break change 的版本 2.0.0,正常情况下我们肯定是在 master 分支(2.0.0 的代码)的基础上逐步迭代,但 1.x 的版本可能还有用户使用,当我们需要修复 1.x 的一个 bug 时如何去做?这里推荐一个流程:


  • 首先基于 git tag ice-scripts/1.6.5 切出一个 stable/ice-scripts-1.x 的分支(幸亏之前打了 tag,否则要找到对应的 commit 还是有点工作量的)

  • stable/ice-scripts-1.x 设为保护分支,可以理解为 1.x 版本的 master 分支

  • stable/ice-scripts-1.x 切出新分支 ice-scripts-1.x/fix-bar,然后修改代码提交 PR 到 stable/ice-scripts-1.x 分支上

  • Review 完成后合并代码,然后在 stable/ice-scripts-1.x 分支上进行发布


如何做好答疑

运营社区的过程一定需要频繁面对用户的疑问,如何在满足用户的同时又能保证自身投入不影响到正常工具显得极为重要了,对于技术产品,根据面向用户群体的不同目前两种主流答疑方式:


  • GitHub issue: 纯异步交流,保证所有问题讨论都能沉淀下来,同时因为异步沟通有成本,大家会努力一点表达清楚自己的意图,相对来讲沟通质量更高,但响应速度之类的无法保证

  • 类钉钉群:同步交流,响应速度快,但是对于维护者来说时间容易被打碎,降低工作效率


如何管理 issue

结合治理 ICE 的历史 issue 提供一些建议仅供参考:


  • 通过 issue 模板提升 issue 质量:ICE 仓库里早期的 issue 质量非常低,很多问题都无法复现

  • 基于产品纬度建立对应的标签分类,每个 issue 关联标签,然后由对应负责人统一处理

  • issue 不要求及时处理,但鼓励能通过沟通或其他方式快速明确问题,防止时间长了不理解 issue 的描述然后又无法跟 issue 作者沟通


如何运营社区

ICE 团队目前维护着 6 个钉钉答疑群(每个 1000 人)以及技术论坛的官方帐号,但整体活跃度都比较一般,目前无论是精力上的投入还是运营产品的经验都比较缺失,希望能得到一些建议或者支持。


有趣的机器人

github 上有很多方便的机器人(or App?),这里推荐个人觉得比较有用的两个机器人:


  • delete-merged-branch:合并 PR 之后会自动删除对应分支,防止无用分支的堆积

  • Weekly Digest:每周创建一个 issue,汇总仓库一周内的动态,比如:新增了哪些 issue/PR,有哪些人 star 了仓库等,示例 Weekly Digest (30 December, 2018 - 6 January, 2019)「https://github.com/alibaba/ice/issues/1264


本文转载自公众号淘宝技术(ID:AlibabaMTT)


原文链接


https://mp.weixin.qq.com/s/HwlN36eZlXd-6z1q3Iz-xA


2019-07-21 08:008315

评论

发布
暂无评论
发现更多内容

编程培训班怎么才能选择出靠谱?

小谷哥

开发者,有没有完全自主的国产化数据库技术?

Albert Edison

数据库 云原生 中间件 8月月更 开源SPL

武汉大数据培训班学习要多久

小谷哥

2022秋招,Java岗最全面试攻略,吃透25个技术栈Offer拿到手软

退休的汤姆

面经 社招 Java工程师 秋招 Java八股文

Go Go 简单的很,标准库之 fmt 包的一键入门

梦想橡皮擦

Python 爬虫 8月月更

嘎嘎牛逼!对标P7+)互联网Java高级架构师面试标准手册

Geek_Yin

阿里巴巴 程序员人生 P7架构师 #java 程序员面试、

加密世界的福音,Galaxy Project上领取专属Zebec OAT

EOSdreamer111

大数据编程培训班怎么样?

小谷哥

Python自学教程2:大牛们怎么写注释

和牛

Python 测试 8月月更

App Deploy as Code! SAE & Terraform 实现 IaC 式部署应用

阿里巴巴中间件

阿里云 Serverless Terraform 阿里云云原生

前端mcok原来可以如此丝滑

Liam

前端 前端开发 Postman Mock 前端工具

【Java秋招面试宝典300题】阿里P8爆肝2个月呕心整理,挑战30天打卡秋招上岸!(基础、Spring、MySQL、JVM、微服务分布式)

退休的汤姆

Java 面经 校招 Java工程师 秋招

Python 教程之输入输出(8)—— print() 中的 Python 结束参数

海拥(haiyong.site)

Python io 8月月更

Zebec社区利好频传,Galaxy Project上领取专属Zebec OAT

股市老人

字节大佬的「算法界Top1笔记」火爆Github,短时间获上万star

Geek_Yin

编程 程序员 数据结构 算法 #java

上海大数据培训学习怎么样

小谷哥

web前端课程培训班哪里好?

小谷哥

2022秋招,Java岗最全面试攻略,吃透25个技术栈Offer拿到手软

Geek_Yin

编程 程序员 java面试 金九银十 #java

你需要的露营预约管理系统来啦!最新的露营案例奉上!

天天预约

SaaS应用 预约工具 露营 营地管理

出海季收官,速来 Get 全球化发展实操手册

融云 RongCloud

jdk11或以上的module错误

Geek_5829b6

jdk Module

2022年最新【Java经典面试800题】面试必备,查漏补缺;多线程+spring+JVM调优+分布式+redis+算法

Geek_Yin

编程 程序员 金九银十 #java Java面试八股文

如何管理一个大型开源仓库?_开源_刘雄_InfoQ精选文章