Conventional commits¶
Abstract¶
Spec status: stable; useful. Take it, modify it, use it. (CC-BY-SA)
This document covers a single specification for structured Git commit messages. There are two aspects:
A “profile” of Conventional Commits¶
The profile is based on the Angular guidelines, PyData’s contributing guide, and @commitlint/config-conventional. Types, general scopes, and footers are defined. Projects should derive from this spec, defining their own scopes.
A normalized form of Conventional Commits¶
Conventional Commits is partly ambiguous, inconsistent, and overly flexible. We specify an unambiguous grammar, exact terminology, and additional requirements. Most importantly, this enables simple and reliable parsing.
Definitions¶
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in BCP 14 (which includes RFC 2119 and RFC 8174) when, and only when, they appear in all capitals, as shown here.
Example¶
Commit 1:
depr(api): deprecate v1 api
Deprecates V1 API in favor of V2.
Clients are encouraged to use V2, which is a superset of V1.
New features are described in the [V2 API announcement](https://amazing-api.dev#v2).
DEPRECATED: `/api/v1/` endpoints (use `/api/v2/` instead)
Closes #12
Co-authored-by: Amelia Johnson <amelia@dev.com>
Co-authored-by: Cecilia Johnson <cecilia@dev.com>
Commit 2:
drop(api)!: drop v1 api
Removes V1 API endpoints, as discussed in the [V2 API announcement](https://amazing-api.dev#v2).
See also: [issue #12](https://github.com/amazing-api/apiz/issues/12).
BREAKING CHANGE: `/api/v1/` endpoints (removed)
Closes #24
Reviewed-by: Tom Thompson <tom@hotmail.net>
Commit 3:
fix(api): re-add v1 api
This commit reverts 2a0f4f2.
Re-adds the V1 API, which was removed ahead of schedule.
Also removed Tom Thompson from the contributor list.
Reported-by: Isaac Malone <isaac.malone@gmail.com>
CC: Amelia Johnson <amelia@dev.com>
Approximate pattern¶
<type>[(<scope>)][!]: <subject>
[This commit reverts <commit hash>.]
<body>
[BREAKING CHANGE: <feature, etc.> [\n\n<how to migrate, etc.>] ]
[DEPRECATED: <feature, etc.> [\n\n<how to migrate, etc.>] ]
[Closes #<issue>]
[<trailer>: <author>]*
"""
Specification¶
Core grammar¶
(?x)
(?<type>
feat|fix|security|docs|style|refactor|perf|test|drop|depr|ci|build|chore
)
(?:
\(
(?<scopes>
([a-z]++(?:-[a-z]++)*+)(,([a-z]++(?:-[a-z]++)*+))*+
)
\)
)?+
(?<is_breaking> ! )?+
:\u0020
(?<subject> \S[\S\u0020]*+ )
(?:
\n\n
(?:
This commit reverts
(?<reverts> [0-9a-f]{7}(?: ,\u0020[0-9a-f]{7})++ ).
)?+
(?<body>
(?: \n{0,2} (?: \S[\S\u0020]*+ | \n(?!\n) )+ )*?
)??
(?:
\n\nBREAKING\u0020CHANGE:\u0020
(?<breaking_change> \S[\S\u0020]*+ )
)?+
(?:
\n\nDEPRECATED:\u0020
(?<deprecated> \S[\S\u0020]*+ )
)?+
(?:
\n
(?>
\nCloses \u0020\# (?<closes> \d++ )
|
\n
(?<key> [^\s:]++)
(?: :\u0020 | \u0020\# )
(?<value> \S[\S\u0020]*+ )
)*+
)?+
)?+
Additional requirements¶
Subject¶
As specified by Conventional Commits, the subject SHOULD use imperative mood and present tense, contain only 1 (incomplete) sentence, start with a verb, not mark the end with .
, and describe the change made by the commit (not the behavior of the code).
Important
The description is a short summary of the code changes; e.g.:
fix: array parsing issue when multiple spaces were contained in string
❌ Incorrect: fix: raise error when config is missing
✅ Correct: `fix:
Scopes¶
Projects are encouraged to define their own scopes.
In addition, they should use either the scopes dev-infra
and docs-infra
as defined by the Angular commit message guidelines OR one or more scopes that serve similar purposes. In particular, projects should consider how scopes can be used to organize release notes and to exclude changes from release notes or changelogs.
Breaking changes¶
Breaking changes MUST be indicated by !
. If a body is present, a single BREAKING CHANGE:
footer MUST list the changed feature(s).
Body¶
The body SHOULD be written as CommonMark. The subject SHOULD be assumed to be an implicit level 3 (###
) heading; headings used SHOULD be limited to levels 4 and 5. Present tense is RECOMMENDED (e.g. Fixes
rather than Fix
).
Special body paragraphs¶
Git trailer format does not permit blank lines between trailers, and it does not allow spaces in trailer keys. This document considers BREAKING CHANGE
and DEPRECATES
to be part of the body, which we will formally call special body paragraphs. Both special body paragraphs MUST be below any normal body paragraphs, and BREAKING CHANGE
MUST be listed first if both are present.
True footers (trailers)¶
The Git-trailer-compatible footers defined here are Reverts
, Closes
, and the attribution trailers listed below. Placing Reverts
and Closes
above any other footers is recommeneded.
Custom footers¶
Commits MUST NOT use footers that have not been defined. Projects MAY define additional footers.
- MUST NOT redefine any footer defined here;
- MUST follow the Git trailer syntax;
- MUST use either
:
or#
as a separator; - SHOULD have key matching
[A-Z][A-Za-z0-9]*+(?:-[A-Za-z0-9]++)*+
; and - SHOULD clearly document (i) when it’s allowed and/or required, (ii) the value syntax and meaning, (iii) whether it’s repeatable, and (iv) any aliases for the key.
Attribution trailers¶
These attribution trailers are allowed:
- Acked-by
- Reviewed-by
- Helped-by
- Reported-by
- Mentored-by
- Suggested-by
- CC
- Noticed-by
- Tested-by
- Improved-by
- Thanks-to
- Based-on-patch-by
- Contributions-by
- Co-authored-by
- Requested-by
- Original-patch-by
- Inspired-by
- Signed-off-by
This regex could be used to parse attribution trailers:
(?<key> [A-Z][A-Za-z]*+(?:-[a-z]++)*+)
\u0020
(?<author> [^\s<>](?:[^\s<>]|\u0020)+(?!\u0020) )
\u0020
< (?<email>[\w.+-]++@[\w.-]++\.[a-z]++) >
Differences from other conventions¶
There are differences between these guidelines, the PyData guidelines, and the Angular guidelines. Note that PyData defers to a 2018 Angular revision.
thing | Angular | this spec | rationale |
---|---|---|---|
multiple scopes? | no | comma-separated | Often multiple apply |
dev scope (main) | dev-infra | ← (unchanged) | |
dev scope (docs) | docs-infra | ← | |
deprecation footer | DEPRECATED: | ← | |
issue close footer | GH-recognized † | only Closes # | Prefer single keyword |
PR footer | yes, like issue | no | Handle in issue, not PR/commit |
has revert type | yes | no | Treat it as a normal commit |
revert hash (body) | This commit reverts | ← | Prominent keyword |
has depr type | no | yes | Changelog section |
has drop type | no | yes | Changelog section |
has security type | no | yes | Changelog section |
has style type | removed (2017) | retained | Clearly different from refactor |
has chore type | removed (2017) | discouraged | Preferred to an incorrect type |
body mood | imperative | non-imperative | More readable; de facto in Angular |
body format | plain | CommonMark | More flexible; rendered on GitHub |
! required | no | yes | Important, so specify in subject |
line length | not specified | ≤ 100 encouraged | Consistency and readability |
special paragraphs ‡ | footers | body paragraphs | Conform to Git trailer format |
special paragraph text | ≥ 2 paragraphs | ≥ 1 paragraph | Keep thing simple |
Table 1. Differences from the Angular commit guidelines
† GH-recognized means any phrase that GitHub sees as PR-to-issue links.\ ‡ Whether BREAKING CHANGES
and (if defined) DEPRECATED
are footers or special body paragraphs.