对中国开发者最具吸引力的科技企业有哪些?快来为你 pick 的企业投票! 了解详情
写点什么

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

2019 年 7 月 21 日

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

作者所在的飞冰(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 年 7 月 21 日 08:007544

评论

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

LeetCode题解:77. 组合,递归回溯,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

《Python:Python编程简介:计算机编程和机器学习入门指南》

计算机与AI

Python

真香,数位Ali高级工程师遍览中外名书,终成顶级网络编程笔记

周老师

Java 编程 程序员 架构 面试

架构训练营 - 第7周课后作业 - 学习总结

Pudding

架构师训练营第一期 - week8

习习

害怕重构?都怪我太晚和你介绍该如何重构,现在我来了

小Q

Java 学习 程序员 面试 重构

揭秘在召唤师峡谷中移动路径选择逻辑?

华为云开发者社区

算法 地图 最短路径

百亿级数据分表后怎么分页查询?

艾小仙

Java MySQL 数据库 编程语言 分库分表

终于啃完了Java核心原理+框架“面试圣经”成功五面上岸美团

小Q

Java 学习 编程 架构 面试

魏际刚:精准谋划我国供应链发展新方位

CECBC区块链专委会

供应链 物流

一款区块链钱包开发需要多少钱?数字资产钱包开发搭建

13530558032

【涂鸦物联网足迹】涂鸦云平台接口说明

IoT云工坊

人工智能 物联网 API sdk 云平台

价值超10亿美元的直播系统架构图是什么样子的?

冰河

系统架构 高并发 高性能 亿级流量 直播架构

USDT承兑支付平台技术开发,承兑商币支付交易平台搭建

13530558032

从智慧计算的点、线、面,读懂浪潮AI的进化轨迹

脑极体

帮助企业摆脱困境,名企归乡工程师:能成功全靠有它!

Philips

敏捷开发

浅谈API网关(API Gateway)如何承载API经济生态链

华为云开发者社区

API 网关

如何稳扎稳打推进数字货币进程

CECBC区块链专委会

数字货币

Apache DolphinScheduler 是如何走进Apache的

海豚调度

大数据任务调度 数据湖调度 DolphinScheduler Apache DolphinScheduler

架构师训练营第 1 期第 7 周总结

du tiezheng

极客大学架构师训练营

又一道比较运算符相关的面试题让我明白基础很重要

Gopher指北

golang

CDN是什么?

德胜网络-阳

金融科技的未来

CECBC区块链专委会

金融

做个别人家的网页

MySQL从删库到跑路

html/css 网页设计

谈谈敏捷开发概念和迭代开发方案

Learun

敏捷开发

【运维思考】如何做好云上运维服务?

嘉为蓝鲸

云计算 运维 数字化转型 数据中心 云服务

架构师训练营 - 第 7 周课后作业(1 期)

Pudding

爆料!前华为微服务专家纯手打500页落地架构实战笔记,已开源

996小迁

架构 面试 分布式 微服务 程序人生

数字货币OTC交易所开发,交易所搭建方案

13530558032

从一场“众盟科技云滇之播”,我们发现了美食直播的商业与公益价值

脑极体

初级工程师职场生存要点

javaadu

程序员 职场成长 开发日志

滴滴 Logi 日志管理与分析平台

滴滴 Logi 日志管理与分析平台

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