GLEP 66: Gentoo Git 工作流程
作者 | Michał Górny <mgorny@gentoo.org> |
---|---|
类型 | 标准轨道 |
状态 | 最终 |
版本 | 1.1 |
创建 | 2017-07-24 |
上次修改 | 2018-09-18 |
发布历史 | 2017-07-25, 2017-09-28, 2017-10-11, 2018-09-18 |
GLEP 源代码 | glep-0066.rst |
内容
摘要
本 GLEP 规范了使用 Git 与 Gentoo ebuild 仓库的 基本标准和建议。它只涵盖 Gentoo 特定的策略,并不打算成为一个完整的指南。
更改日志
- v1.1
- 更新了签署人脚注标签描述以反映新批准的版权政策。
动机
尽管 Gentoo 主仓库已经使用 Git 两年了,但开发者仍然缺乏关于如何一致使用 Git 的官方文档。大多数开发者从其他人那里学习口头的标准并遵循它们。这最终在一定程度上带来了统一性,但并非最佳。此外,它导致用户不得不以艰难的方式学习,而不是有适当的文档可供参考。
一段时间以来,已经尝试了几次将 Git 使用标准化。最值得注意的是 Gentoo Git 工作流程 [1] 和 Gentoo GitHub [2] 文章。但是,它们都不是任何官方标准,而且它们的关注面太广,无法成为一个标准。也曾尝试过一个初始的 GLEP,但它甚至没有进入草稿阶段。
本 GLEP 的目标是最终为 Gentoo 仓库中使用 Git 提供基本标准化。它旨在纯粹关注 Gentoo 特定的标准,而不是 Git 的一般使用。这并不意味着它是一个完整的指南,而是一个正式的基础,官方指南可以建立在该基础之上。
规范
分支模型
Gentoo 仓库的主分支是master分支。所有 Gentoo 开发者都将他们的工作直接推送到 master 分支,前提是提交满足最低质量标准。master 分支也直接用于持续的用户仓库部署。
由于多个开发者同时在 master 上工作,他们可能需要多次变基才能进行推送。请求开发者不要使用可能阻止其他人推送的工作流程,例如频繁推送单个提交,而不是将它们暂存并使用单个推送。
开发者可以使用额外的分支来促进对大规模长期项目的审查和测试。但是,由于 Git 默认情况下会获取所有分支,因此应该谨慎使用它们。对于较小的项目,首选使用本地分支或仓库 fork。
除非另有说明,本规范设置的规则仅适用于 master 分支。开发分支可以使用更宽松的规则。
禁止重写 master 分支的历史记录(即强制推送)。
合并提交
在 Gentoo 仓库中强烈不鼓励使用合并提交。通常,最好使用变基来代替。但是,开发者可以在有正当理由的情况下使用合并提交。合并提交只能用于合并额外的分支,使用隐式的git pull合并是完全禁止的。
在直接提交到 Gentoo 仓库的合并提交中,第一个父项应引用实际的 Gentoo 提交(在合并之前),而其余父项可用于引用源自外部仓库的提交。第一个父项祖先路径上的提交(直到下一个合并提交)需要符合本规范。其余祖先路径上的提交可以使用更宽松的规则。
OpenPGP 签名
Gentoo 仓库中的每个提交都必须使用提交者的 OpenPGP 密钥进行签名。此外,对仓库的每次推送都必须使用属于执行推送的开发者的密钥进行签名(通过 SSH 密钥匹配)。
OpenPGP 密钥的要求由 GLEP 63 [3] 涵盖。
拆分提交
Git 提交是轻量级的,鼓励开发者将他们的提交拆分,以提高可读性和回滚特定子更改的能力。在选择如何拆分提交时,开发者应考虑以下三个规则
- 使用原子提交 - 每个逻辑更改一个提交。
- 在逻辑单元(包、eclass、配置文件等)边界处拆分提交。
- 避免创建“损坏”的提交 - 例如,不完整的提交,包含无法安装的包。
在技术上不可能始终遵循所有三个规则,因此开发者必须根据自己的判断在它们之间取得平衡。由其他更改隐含的附带更改(例如,由于某些更改而导致的版本号更改)应包含在需要它们的第一个提交中。提交应按顺序排列以避免损坏,并在可能的情况下遵循逻辑顺序。
示例
- 在执行版本号更改时,通常将每个必要的逻辑更改拆分为单独的提交是不合理的,因为中间提交将对应于一个损坏的包。但是,如果包有一个活动的 ebuild,那么在活动 ebuild 上执行拆分的逻辑更改可能是合理的,然后创建另一个逻辑步骤的发布。
- 在执行一个或多个需要版本号更改的更改时,在包含第一个更改的提交中更改版本号。将更改拆分为多个逻辑提交,而无需进一步更改版本号 - 由于它们将在一个推送中被推送,因此用户不会接触到中间状态。
- 在添加应该被屏蔽的包的新版本时,可以将package.mask编辑添加到添加它的提交中。或者,可以在添加屏蔽的提交之前将其添加到一个拆分的提交中。
- 在对大量包进行微调更改时,在一个提交中进行操作是合理的。但是,在进行重大更改(例如,版本号更改)时,最好在包边界处拆分提交。
提交信息
标准的 Git 提交信息由三个部分组成,按顺序排列:摘要行、可选的主体和可选的标签集。各个部分用一个空行隔开。
摘要行包含在简短的日志中(git log --oneline,Gitweb、GitHub、邮件主题),因此应该提供一个简短但准确的更改描述。摘要行以逻辑单元名称开头,后跟冒号、空格和对最重要更改的简短描述。如果某个错误与更改相关联,那么它可以作为bug #nnnnnn包含在摘要行中。摘要行不得超过 69 个字符,并且不得换行。
建议的逻辑单元名称格式为
- 对于一个包,category/package: …;
- 对于一个 eclass,name.eclass: …;
- 对于其他目录或文件,它们的路径或文件名(只要开发者能够从提交信息中判断出是什么) - 例如licenses/foo: …, package.mask: ….
主体包含在完整的提交日志中(git log,Gitweb/GitHub 上的详细提交信息、邮件正文)。它是可选的,如果摘要行不足以描述提交,则可以使用它来更详细地描述提交。通常,最好重复摘要中包含的信息(逻辑单元除外),因为摘要通常被格式化为标题,而不是与主体相邻。主体应该在 72 个字符处换行。它可以包含多个段落,用空行隔开。
标签部分包含在完整的提交日志中,作为正文的扩展。它由一个或多个行组成,这些行由键、冒号和空格组成,后跟值。Git 不强制执行任何键的标准化,并且标签格式 *不* 用于机器处理。
一些常用的标签是
- 与用户相关的标签
- Acked-by: 姓名 <email@example.com>— 提交由另一个人批准(通常没有详细审查),
- Reported-by: 姓名 <email@example.com>,
- Reviewed-by: 姓名 <email@example.com>— 通常表示完整的审查,
- Signed-off-by: 姓名 <email@example.com>— GCO/DCO 批准(由 GLEP 76 [4] 定义),
- Suggested-by: 姓名 <email@example.com>,
- Tested-by: 姓名 <email@example.com>.
- 与提交相关的标签
- Fixes: commit-id (提交信息)— 表示修复了早期的提交,
- Reverts: commit-id (提交信息)— 表示撤销了早期的提交,
- 与 bug 跟踪器相关的标签
- Bug: https://bugs.gentoo.org/NNNNNN— 引用一个 bug;提交将在注释中链接,
- Closes: https://bugs.gentoo.org/NNNNNN— 自动关闭 Gentoo 错误(RESOLVED/FIXED,链接提交),
- Closes: https://github.com/gentoo/gentoo/pull/NNNN— 自动关闭 GitHub、GitLab、BitBucket 或兼容服务(镜像提交)上的拉取请求,
- 包管理器标签
- Package-Manager: …— 由 repoman 用于指示 Portage 版本,
- RepoMan-Options: …— 由 repoman 用于指示 repoman 选项。
基本原理
分支模型
从 CVS 中保留了多个开发人员同时向包含所有包的存储库推送的模型。开发人员已经讨论了使用其他模型的可能性,特别是使用多个分支来开发人员,这些分支随后会自动合并到主分支中。然而,他们确定目前没有必要使用更复杂的模型,并且使用它们的潜在问题超过了其益处。
重新基准的必要性是并发工作的一个自然结果,以及禁止反向合并提交。由于重新基准多个提交可能需要几秒钟甚至更长时间,因此其他开发人员有时会在此时提交,强制进行另一次重新基准。
在过去,有一些开发人员使用自动化脚本,这些脚本创建单一提交、运行 repoman 并将它们直接推送到存储库。这导致了每 10-15 秒从单个开发人员进行一次推送,这使得其他开发人员无法重新基准更大的提交批次。因此,强烈不建议使用这种工作流程。
创建多个短期分支是不鼓励的,因为它意味着对克隆存储库的用户来说额外的传输和额外的维护负担。自 git 迁移以来,开发人员已经在存储库中创建了一些分支,但没有维护它们。基础设施团队必须向开发人员查询分支的状态并清理它们。将分支保留在本地或在 Gentoo 基础设施之外托管它们(例如在 GitHub 上)减少了对我们用户的负担,即使开发人员没有清理自己。
合并提交
合并提交在各种媒体(特别是 IRC)中多次被讨论。他们有非常强烈的反对者,他们的主要论点是它们使历史不可读。同时,人们经常指出合并提交具有有效的用例。为了满足两组人,本规范强烈不鼓励使用合并提交,但在合理的情况下允许使用。
最重要的是,由git pull创建的隐式合并提交是禁止的。这些合并没有实际价值或合理的用例,并且由于它们是默认情况下隐式创建的,历史上曾有过开发人员无意中推送它们的案例。明确禁止它们是为了强调调整 git 配置以适应开发人员的必要性。
在处理合并提交时,重要的是要明确区分代表“真实”Gentoo 历史的父项和代表外部分支的父项。前者可以是现有的 Gentoo 提交,也可以是开发人员在合并分支之前(在现有的 Gentoo 历史之上)准备的提交。因此,重要的是要对该父项及其之前的提交强制执行 Gentoo 政策的全部集合。另一方面,外部分支可以像开发分支一样对待。放宽外部分支的规则也使得能够合并用户贡献,并保留原始用户 OpenPGP 签名,同时在合并提交之上添加最终的开发人员签名。
使用git merge foo时,第一个父项代表当前HEAD,第二个父项代表合并的分支。这是规范使用的模型。
OpenPGP 签名
签名要求严格对应于基础设施团队部署的 git 设置。
提交签名提供了一种验证整个 Gentoo 存储库历史记录(到 git 转换点)中所有提交真实性的能力。推送签名主要用于对开发人员推送特定一组提交的额外身份验证。
拆分提交
提交拆分规则的目标是在避免对开发人员施加过多开销的同时,最大限度地利用 git,并优化以避免中间破损提交。
按逻辑更改拆分提交可以提高可读性,并使在保留剩余(不相关)更改的同时更轻松地还原特定更改。当审阅者能够以作者执行的特定顺序(而不是与其他更改组合在一起)来跟踪开发人员所做的更改时,更容易理解这些更改。
自 CVS 时代以来,一直在使用按逻辑单元边界拆分提交。它主要通过使在提交消息中包含单元(包、eclass 等)名称成为可能来提高可读性——这样,开发人员就能了解更改影响了哪些特定包,而无需查看 diffstat。
要求提交不“损坏”是为了保留存储库的优质 git 历史记录。这意味着用户可以检出中间提交,而不会冒发生重大问题(例如缺少依赖项,这些依赖项将由后续提交添加)的风险。它也使以更低的暴露破损风险来还原最新的更改更加安全。
这些规则部分重叠,在这种情况下,预计开发人员会使用常识来确定给出最佳结果的操作步骤。此外,要求严格遵循规则意味着开发人员需要做很多额外的工作,并且需要进行很多额外提交,而没有真正的益处。
提供这些示例是为了让开发人员能够了解如何使用这些规则。
提交信息
基本提交消息格式类似于其他项目使用的格式,并提供了对结果的合理可预测的显示。
摘要行旨在提供对更改的简洁摘要。它包含在简短日志中,应该包含所有信息来帮助开发人员确定他们是否有兴趣查看提交详细信息。包含逻辑单元名称是为了说明大多数 Gentoo 提交都是针对这些单元的(例如包)。长度限制是为了避免包装简短日志——这会导致难以阅读git log --oneline或在 GitHub 上出现难看的单词中间省略号。
正文旨在提供提交的详细信息。它通常以原样显示,使用段落和换行是为了提高可读性。正文应该包含摘要中包含的信息,因为两者有时确实是不相干的,并且期望用户将正文作为摘要的延续来阅读是令人困惑的。例如,在git send-email中,摘要行用于构建邮件的主题,因此与正文是不相干的。
标签部分是表达类似机器可读数据的传统方式。但是,提交消息并不真正适合机器使用,只有少数标签会被脚本实际处理。规范试图提供一组简洁的、可能很有用的标签,这些标签是从各种项目(Linux 内核、X.org)中收集的。这些标签可以与正文中的纯文本解释互换使用。
git 本身定义的唯一标签是签署人行,它由git commit -s创建。虽然 git 没有定义它的确切含义,但它通常用于引用来源签署证书。
受机器处理的标签是Bug和Closes行。两者都由 git.gentoo.org 用于处理 Gentoo Bugzilla,后者也由 GitHub 用于自动关闭拉取请求(和问题——但是,Gentoo 不使用 GitHub 的问题跟踪器)。GitHub、GitLab、Bitbucket、git.gentoo.org 还支持Fixes和Resolves标签(以及前三个的一些变体),但是Closes已经建立在 Gentoo 中,并用于一致性。
所有剩余的标签纯粹是为了用户方便。
历史上,Gentoo 一直使用一些以X-开头的标签。然而,这种做法被放弃了,因为人们指出 git 并没有强制执行任何标准标签集,因此指示非标准标签毫无意义。
Gentoo 开发人员仍然经常使用Gentoo-Bug标签,有时后面跟着Gentoo-Bug-URL。同时使用两者是毫无意义的(它们是冗余的),使用前者与在摘要或正文中使用经典的#nnnnnn形式相比没有优势。
在Closes中使用完整的 URL 是必要的,以便将操作正确地命名空间到 Gentoo 服务,并避免在提交被镜像或 cherry-picked 到另一个存储库时意外关闭不正确的 issue 或拉取请求。为了保持一致性,它们也用于Bug,并且应该用于可能引入的任何未来的标签。这也确保了 URL 会被各种工具自动转换为超链接。
在提交消息的摘要中包含错误编号会导致 willikins 在#gentoo-commits.
向后兼容性
上自动扩展该错误。大多数新策略将适用于其批准后的提交。向后兼容性在那里并不相关。
一个特别影响提交追溯的点是 OpenPGP 签名。但是,自 git 切换以来,基础设施一直强制执行这一强制性要求。因此,所有 git 历史记录都符合这一点。
参考实现
所有需要在 git 基础设施上明确实施的元素都已经实施。特别是,这包括
- 阻止在master分支上进行强制推送,
- 要求在master分支上进行强制推送,
- 上进行签署提交,
要求对存储库进行签署推送。
RepoMan 建议从提交 46dafadff58da0 [5] 开始,提交消息以包名称开头。
参考文献
[1] | (1, 2) Gentoo Git 工作流程(在 Gentoo Wiki 上) (https://wiki.gentoo.org/wiki/Gentoo_git_workflow) |
[2] | Gentoo GitHub(在 Gentoo Wiki 上) (https://wiki.gentoo.org/wiki/Gentoo_GitHub) |
[3] | GLEP 63: Gentoo GPG 密钥策略 (https://gentoolinux.cn/glep/glep-0063.html) |
[4] | GLEP 76: 版权策略 (https://gentoolinux.cn/glep/glep-0076.html) |
[5] | (https://gitweb.gentoo.org/proj/portage.git/commit/?id=46dafadff58da0220511f20480b73ad09f913430) |
版权
此作品根据知识共享署名-相同方式共享 3.0 未移植许可协议授权使用。要查看此许可证的副本,请访问 https://creativecommons.org/licenses/by-sa/3.0/。