This document is intended to be a template of sorts. It is written in the context of this repository to provide concrete examples, but changes to this repository may not always adhere to the guidelines below.
Commit messages adhere to the Conventional Commits specification. General structure, Type and Scope are adapted from Angular's commit message guidelines.
<header>
<!-- <BLANK LINE> -->
<body>
<!-- <BLANK LINE> -->
<footer><type>[(<scope>)][<bang>]: <summary>
│ │ │ │
│ │ │ └─ `MUST` be present-tense, periodless, `Uncapitalize<string>`
│ │ │
│ │ └─ `MUST` include `!` for breaking changes; `MUST` omit otherwise
│ │
│ └─ `MUST` be a subdirectory of `apps/*` or `packages/*`, `devtools`, or a root directory (e.g. `infra`)
│
└─ `MUST` be `build|chore|ci|docs|feat|fix|refactor|test`<type>MUST be a Type<scope>, if set, MUST be a Scope<scope>MUST exist if<bang>(!) doesn't exist<scope>SHOULD exist if<bang>(!) exists<bang>MUST NOT exist iftype==chore|ci|docs|refactor|test<summary>MUST be present-tense<summary>MUST be uncapitalized<summary>MUST omit ending "."
A commit's type provides insight into the commit's changes and their impact.
typeMUST be one of the following:
| Type | Changes | Example paths | Version | ! |
Example commit message |
|---|---|---|---|---|---|
build |
Dependencies, build system | **/package.json |
+0.0.1 |
- |
build: bump pnpm to v10.21.0 |
chore |
Devtools | **/eslint.config.js |
- |
- |
chore: warn on ESLint issue |
ci |
Workflows | .github/workflows/** |
- |
- |
ci: run tests on PR to main |
docs |
Comments, documentation | **/README.md, docs/** |
- |
- |
docs: mark APIs @internal |
feat |
Functionality | **/src/** |
+0.1.0 |
+1.0.0 |
feat: add support for dark mode |
fix |
Behavior | **/src/** |
+0.0.1 |
+1.0.0 |
fix: disallow weak password |
refactor |
Code structure | * |
+0.0.1 |
- |
refactor: extend shared tsconfig |
test |
Unit/E2E | **/test/** |
- |
- |
test: snapshot Tab component |
Common type(s) intentionally excluded:
perf: slow performance is considered a bug, and thus covered byfix
Commit types with a Version of -:
- Public API MUST NOT change if
type!=feat|fix - Release SHOULD trigger if
type=build|feat|fix|refactor - Version SHOULD NOT change if
type!=build|feat|fix|refactor
A commit's scope indicates a commit's area of impact. Omit scope if changes span multiple areas (e.g. refactor) or aren't related to a specific package (e.g. docs).
- If supplied,
scopeMUST be one of the following:
| Scope | Example Changes | Example Scope | Example paths |
|---|---|---|---|
A directory in apps/* |
Standalone apps in apps/ |
www |
apps/www |
A directory in packages/* |
Shared packages in packages/ |
logger |
packages/logger |
Root directory besides apps/packages |
Infrastructure as code in infra/ |
infra |
infra/environments/prod |
devtools |
Developer tooling | devtools |
.zed |
Generally, scope should be a package. In this repository, scope tends to be the name of the app that the changes affect OR a directory in packages/.
Tip
scope serves to inform readers where a change occurred. scope generally helps us do two things:
- Organize the CHANGELOG
- Determine a commit's area of impact
Consider the following:
- Breaking changes are read carefully:
<header>,<body>(s), and<footer>(s). - Non-breaking changes are more often represented by their
<header>in a CHANGELOG.
It follows that scope is most important for non-breaking changes.
If a commit introduces a breaking change, the ! character MUST be present in the <header>.
The following Types should never have a ! in the <header>:
chore: Changes to developer tooling MUST NOT affect the public API or end-user functionality.ci: Changes to CI/CD MUST NOT affect the public API or end-user functionality.docs: Changes to documentation MUST NOT affect the public API or end-user functionality.refactor: Changes to code structure MUST NOT affect the public API or end-user functionality.test: Changes to tests MUST NOT affect the public API or end-user functionality.