Conventional Commits encourages focus on the wrong things
Conventional Commits encourages focus on the wrong things
Conventional Commits 鼓励人们关注错误的事情
Stop Using Conventional Commits 停止使用 Conventional Commits
You’ve almost certainly encountered Conventional Commits before. It may have reared its ugly head in the changelog of an open source project you’ve used. It may have been the enforced commit format for an open source project you contributed to. A lot of people swear by it. I swear at it. 你几乎肯定遇到过 Conventional Commits(约定式提交)。它可能曾以令人不悦的面目出现在你所使用的开源项目的更新日志中,也可能是你参与贡献的开源项目所强制要求的提交格式。许多人对它推崇备至,而我却对它嗤之以鼻。
Even though it is used by a large number of popular open source projects, Conventional Commits is an actively bad standard which encourages focus on the wrong things and fails to deliver on its promises. 尽管许多流行的开源项目都在使用它,但 Conventional Commits 实际上是一个糟糕的标准,它鼓励人们关注错误的事情,且未能兑现其承诺。
Focus Failure
关注点的偏差
Conventional Commits promises to add semantic meaning to commit messages to aid developers and end-users in understanding the changes made in a commit. However, Conventional Commits fails to do this in spectacular fashion. To demonstrate this, let’s look at the anatomy of a conventional commit. According to the Conventional Commit website commit messages should be formatted as follows: Conventional Commits 承诺为提交信息添加语义,以帮助开发者和最终用户理解提交中所做的更改。然而,Conventional Commits 在这方面做得一塌糊涂。为了证明这一点,让我们看看约定式提交的结构。根据 Conventional Commit 官网,提交信息应按以下格式编写:
<type>[optional scope]: <description> [optional body] [optional footer(s)]
The commit’s subject line has a <type> (something like fix, feat, chore, docs, or refactor) describing the type of change. Following that, there is an optional scope, and then a description. This format has a major failing: type is prioritised over scope. This is exactly backwards.
提交的主题行包含一个 <type>(例如 fix, feat, chore, docs 或 refactor),用于描述更改的类型。紧随其后的是可选的 scope(范围),然后是 description(描述)。这种格式有一个重大缺陷:type 的优先级高于 scope。这完全是本末倒置。
Scope > Type
范围 > 类型
The scope of a change (the subject of the change) is the most important part of a commit. To demonstrate this, let’s consider why each one of the following stakeholders care about the scope of the change more than the type of the change: 更改的范围(即更改的主题)是提交中最重要的部分。为了证明这一点,让我们看看为什么以下每一类相关人员都比关注更改类型更关注更改范围:
-
Contributors: when you are a contributor to a project, you often need to read the commit log to identify changes in the codebase relevant to a certain area of the code. There are many reasons for this including:
- Wanting to catch up on what has happened since the last time you contributed.
- Trying to understand where the project’s overall inertia is.
- Looking for commits that might conflict with your in-progress work when pulling or rebasing. As you read the commit log, you’re looking at what areas were touched. You really do not care about the type of change happening, you care about the scope of the change.
-
贡献者: 当你为项目做贡献时,通常需要阅读提交日志来识别代码库中与特定区域相关的更改。原因有很多,包括:
- 想要了解自上次贡献以来发生了什么。
- 试图了解项目的整体进展方向。
- 在拉取或变基(rebase)时,寻找可能与你正在进行的工作冲突的提交。 当你阅读提交日志时,你关注的是哪些区域被触动了。你根本不在乎更改的类型,你关心的是更改的范围。
-
Debuggers: when investigating a bug, you often want to look through the commit log to see what changes might have touched areas related to the component where the bug manifested. Once again, the scope is the most important piece of information. The type of change is entirely useless because bugs can be introduced in any change regardless of type. (I’m sure we’ve all experienced writing a bugfix that caused another bug.)
-
调试者: 在调查 Bug 时,你通常需要查看提交日志,看看哪些更改可能触及了与 Bug 出现组件相关的区域。同样,范围是最重要的信息。更改类型完全没用,因为任何类型的更改都可能引入 Bug。(我相信我们都经历过修复一个 Bug 却引发另一个 Bug 的情况。)
-
Incident responders: when production is down, scanning the commit log for changes that were made around the time of the outage is an effective way to identify what areas may be causing the problem. Scope is once again the most important piece of information you can have at this point. For example, if you see a commit related to the auth scope at the tip of the spike of inbound API errors, it’s a likely culprit for the problem. And once again, type is irrelevant because bugs could have been added by any change.
-
事故响应者: 当生产环境宕机时,扫描故障发生前后的提交日志是识别问题区域的有效方法。此时,范围依然是你所能获得的最重要的信息。例如,如果你在 API 错误激增的时间点看到一个与
auth范围相关的提交,那么它很可能就是问题的罪魁祸首。同样,类型在这里毫无意义,因为任何更改都可能引入 Bug。
So what does Conventional Commits do? It deprioritises scope so much that it’s optional! Why the hell is scope optional? Having a commit without a scope is like having a sentence without a subject! Then, to add insult to injury, Conventional Commits elevates type to the front of the commit message. Conventional Commits gets the priority of scope and type entirely wrong. 那么 Conventional Commits 做了什么呢?它极大地降低了范围的优先级,甚至将其设为可选!为什么范围会是可选的?没有范围的提交就像没有主语的句子!更糟糕的是,Conventional Commits 还将类型提升到了提交信息的最前面。Conventional Commits 在范围和类型的优先级上完全搞错了。
Type is Redundant and Restrictive
类型是多余且受限的
You might be thinking “so it may be backwards, but commit type is at least still important, right?” and to that I say “no”. A commit’s description should almost always tell you the type of the change! Consider this commit message as an example: 你可能会想:“就算它是本末倒置的,但提交类型至少还是重要的吧?”对此,我的回答是“不”。提交的描述几乎总是能告诉你更改的类型!以这条提交信息为例:
fix(compiler): prevent namespaced SVG <style> elements from being stripped
Even if you only had the description, it’s obvious that it was a bugfix! Space on the subject line of a commit is already at a premium, wasting characters on the type is not helpful! But it’s often even worse than useless; it’s often restrictive. Take this commit message as an example: 即使你只看描述,也很明显这是一个 Bug 修复!提交主题行的空间本来就很宝贵,在类型上浪费字符毫无帮助!而且它往往不仅是没用,甚至具有限制性。以这条提交信息为例:
refactor(core): Update webmcp support to use document.modelContext
This commit updated the webmcp functionality in the core component to support both document.modelContext and navigator.modelContext, so was that a bugfix, refactor, or new feature? I would argue it’s all of them! But again, the only thing that really matters is that it was a change to the core/webmcp component.
这次提交更新了核心组件中的 webmcp 功能,以同时支持 document.modelContext 和 navigator.modelContext。那么,这到底是 Bug 修复、重构还是新功能?我认为它三者皆是!但同样,唯一真正重要的是它对 core/webmcp 组件进行了更改。
Conventional Commits fundamentally focuses on the wrong thing (the commit type) and devalues the scope (which is what people actually care about). Conventional Commits 从根本上关注了错误的事情(提交类型),并贬低了范围(这才是人们真正关心的)。
Broken Promises
破碎的承诺
So we have determined that the format of Conventional Commits sucks, but it must provide some benefit. Let’s read the Why Use Conventional Commits section to see if any of the reasons make any sense. 我们已经确定 Conventional Commits 的格式很糟糕,但它一定提供了一些好处。让我们读读“为什么要使用 Conventional Commits”这一节,看看其中的理由是否有道理。
Automatically generating CHANGELOGs. 自动生成更新日志(CHANGELOGs)。
This is the biggest promise of Conventional Commits: you can run a tool like git-cliff or conventional-changelog to generate a changelog from the commits since your last release. Is this even a good idea? No! The audience of a changelog is entirely different than the audience for a commit log!
这是 Conventional Commits 最大的承诺:你可以运行像 git-cliff 或 conventional-changelog 这样的工具,根据上次发布以来的提交生成更新日志。这真的是个好主意吗?不!更新日志的受众与提交日志的受众完全不同!
A changelog is user-facing, and the user cares about understanding the functional differences between versions. They care about what changed from a business/functional perspective. 更新日志是面向用户的,用户关心的是理解版本之间的功能差异。他们关心的是从业务/功能角度发生了什么变化。
A commit log is developer-facing, and the developers care about reading a story of how the codebase has changed over time. They care about what changed from a scope perspective. 提交日志是面向开发者的,开发者关心的是阅读代码库随时间变化的历程。他们关心的是从范围角度发生了什么变化。
As you can see, these are two entirely different grains, and any efforts to combine them result in subpar results. The reasons for this are multiple: 如你所见,这是两个完全不同的维度,任何试图将它们结合起来的努力都会导致糟糕的结果。原因有很多:
In any moderately complex project, it takes multiple commits to land any notable feature. The process of landing the feature (as documented by the commit log) is valuable for developers and contributors, b… 在任何中等复杂的项目中,实现任何显著的功能都需要多次提交。实现该功能的过程(由提交日志记录)对开发者和贡献者来说是有价值的,但……