大概就是对 tag 的用法少根筋。
用 tag 标记 tag 主要是两个用途:传统的 release tag ,以及某个开发周期起始时的 checkpoint (鼓励一个范围内的固定起点,以避免任意位置建分支导致任何处理不同分支——包括合并——时潜在的工作量膨胀)。
master 分支是默认分支,一般放公共主线,本来就不是放 release 用的。一般用于 release 的 tag 都是在各个 release 计划中拉出来的具体版本的 release 分支的最后的公开 commit 打,用 master 分支上面打 tag 是极端偷懒行为,几乎只适合只有一个人开发的情形。
还有一种 tag 是专门用来做 checkpoint 的助记符。这种 tag 基本就是应该在 maintainer 负责的分支打,如果项目没多层 maintainer 那就是顶层主线也就是 master 分支。
一些成熟的项目会明确在两者中区分,例如 GCC 迁移到 git 后就有 releases/和 basepoints/。
原理:因为 maintainer 和某个 release 的负责人通常不总是同一位,区分 release 分支对区分责任和防止 release 阶段的提交冲突是极其有必要的。要是 maintainer 在过了 merge window 还要傻等 release branch 上的提交包括 release tag 同步却因为个别负责人的意外造成整个项目本不必要的阻塞和延期,那就真特么搞笑了。
当然,虽然原则上限制了 DVCS 的潜力,如果中心集权到 Linus Torvalds 这样总能确保 master 上面快速发版,其他开发者会老实允许你周期性足够短地 freeze master ,那两种 tag 都塞在 master 上也不是实际不可行(像
docs.kernel.org/maintainer/rebasing-and-merging.html 建议的 merge ff 用的 tag 其实是 checkpoint )。但做不到那还就是笑话。注意虽然对组织内保持权威一般不难,但是外部开发者未必有听你话的义务,全窝在 master 上发版节奏太拉胯惹毛了外部开发者,别人直接 fork 也不是不行。
但那个图里最大的问题还不是这个,而是临时分支居然叫 release ,成心给 release engineering 找不痛快。正常讲,这种临时分支一般都是匿名的,从来不指望不同阶段复用,非得命名也是叫 prerelease/rc 之类的。需要事后维护倒是最好约定命名,如
www.freebsd.org/releng 。
@
GeruzoniAnsasu 虽然相互合并通常是 evil ,但是无视分支目的教条主义更加 evil 。
在 DVCS 中 master 分支存在的目的几乎就是全项目单一来源的全局主线(只是要实现配置管理分锅或者跨厂商管理的目的,可以 fork 整个 repo ,不需要窝同一个 origin ),因此负责人或者说 owner 大多数时都需要对其中的内容完全负责并有在整个项目中协调发布节奏的绝对权威。
如果禁止自主 merge master 造成滞后(特别是预期就会跨 release tag 的大改动),到时候差异过大再 merge 回来,会严重阻碍中心 PM 负责人的吞吐量乃至整个项目的分支同步效率。这在上规模的(日常 master 成天管合并 PR 就够忙了)项目中是不可接受的。