Important
This gist is temporary until the new documentation (docs.doomemacs.org) and community wiki (wiki.doomemacs.org) have been published.
Doom has adopted conventional commits (with a few minor tweaks). I summarize it here, temporarily, until our new documentation is up.
[SUBJECT]
[BODY]
[FILE-LOG]
[FOOTER]
Where [SUBJECT] is:
TYPE[!][(SCOPE)]: SUMMARY
As of
afdd5f5,
use doom run commit-linter HEAD in a git repository to lint your last commit locally.
The commit type indicates, at a glance, what kind of change was made. Here are the types our projects recognize:
-
All projects:
-
dev: for work on project infrastructure: build scripts, CI/CD config files (e.g..github/*), ignore files, etc. -
docs: changes to user-facing documentation such as module docs, manuals, function docstrings, and output from CLI commands likedoom helpordoom doctor. Also for file templates like init.example.el or yasnippets in the file-templates module. -
feat: code introducing a brand new feature or behavior. -
fix: Resolves a bug or misbehavior. I.e. "This should've been working from the start" Also applicable when fixing stale code that was missed during a recent bump. -
nit: cosmetic changes to comments, formatting, or spelling/grammar with no effect on any behavior whatsoever. -
perf: A refactor or tweak intent on incrementally improving startup/runtime performance, specifically. Usefixinstead if the performance issue being addressed is so severe that it renders Doom difficult/impossible to use. -
refactor: code changes with little effect on user-facing behavior (unless paired with!--to indicate a breaking change--in which case it indicates the wholesale removal of code/features). -
revert: Undoes a previous change. Must be followed by one of:- Doom groups/modules, listed in the same format as the
doom!macro (when reverting module bumps) - Space-delimited package names (when reverting bumps)
- The full subject of the reverted commit (and add
Revert HASHto FOOTER).
If you are reverting another commit in a same PR, please rebase the earlier commit out instead.
- Doom groups/modules, listed in the same format as the
-
test: Added/removed/modifications to the contents of tests (but not changing testing infrastructure; usedevfor that) -
tweak: Changes that tune the default settings to better accommodate existing functionality, in general. The less specific your motivation for the change, the more appropriatetweakis over the other tyes. For example:- Use
fixif the tweak is done to solve specific and known issues/bugs. Usetweakif it's meant to solve a poorly defined set of potential issues. - Use
featif the tweak's intention is to introduce brand new behavior. Usetweakif new behavior/features are the side-effect or consequence, rather than the goal. - Use
perfif the tweak solves a specific and known performance problem, rather than a general (and possibly untested) one.
Example: if I increase
read-process-output-maxto makelsp-modeclients run faster, useperf. If I change it to make IPC faster for all processes, usetweak. If I do it because the old value caused memory errors, usefix - Use
-
merge: used for merge commits. E.g.merge: pull request #1234 from username/branchname -
release: used to announce new tagged releases of the project. E.g.release: 3.0.0(only a maintainer should use this type)
-
-
doomemacs/modules{,-contrib}:
module: Changes to our module list: adding, removing, moving, or deprecating modules.-
Not for changes /within/ modules.
-
Place scope after colon.
module: add :lang zigmodule: move :feature evil to :editor evilmodule: remove :ui fill-column With Emacs 26.x support dropped and display-fill-column-indicator-mode introduced in Emacs 27.1, this module is reduced to a single line, and so has become too trivial to warrant its own module. -
bump: Package updates or code/doc changes intended solely to reflect changes upstream. Userevert:when downgrading packages. Must include bump commit diffs:bump: [:CATEGORY [MODULE...]|PACKAGE [PACKAGE...]|*] user/repo@a1b2c3da1b2c -> user/repo@z9y8x7wz9y8x user/repo@a1b2c3da1b2c -> user/repo@z9y8x7wz9y8x user/repo@a1b2c3da1b2c -> user/repo@z9y8x7wz9y8x [BODY] [FILE-LOG] [FOOTER]
-
-
doomemacs/themes:
theme: changes to the list of themes: adding, removing, moving, or deprecating themes.
-
doomemacs/snippets:
snippet: changes to the list of snippets: adding, removing, moving, or deprecating snippets.
Scopes may be one or more of the following:
- All projects:
- For
devcommits only:ci-- affects continuous integration/delivery infrastucture.
- For
- For doomemacs/doomemacs:
- A module's name without the category:
nit(python):,test(doom-dashboard):,dev(popup):,docs(everywhere): - A category without the module, implying it affects all or many modules inside:
fix(:lang):,feat(:editor):, .. - One of these special scopes:
cli: for anything concerning Doom's CLI:lisp/doom-cli.el,lisp/cli/*.el, orbin/*.
- A module's name without the category:
- For doomemacs/themes:
base-- affects the base theme (or all themes)- The name of any of its themes, minus the
doom-prefix and-themesuffix. E.g.feat(one): ...)fordoom-one, orfix(gruvbox-light): ...for doom-gruvbox-light. - The name of any of any
doom-themes-ext-X.elextension, minusdoom-themes-and.el. E.g.feat(ext-org): ...
- For doomemacs/snippets:
- Any major mode, minus the
-modesuffix. E.g.fix(org): ...for a bugfix in an org-mode snippet.
- Any major mode, minus the
The scope may be omitted if:
- The change affects many parts.
- The change affects "core" code.
- Using a scopeless type, like
bump,revert,release, ormerge(as well asthemefor doomemacs/themes andmodulefor doomemacs/doomemacs). For these, the scope belongs in their SUBJECT.
Warning
Does your change touch multiple Doom modules? Only mention the target
scope(s). For example, a fix or update for :tools lsp that affects LSP
implementations in various :lang modules only needs to specify lsp as
its scope.
Warning
No issue/PR references in SUBJECT. See Footer below.
-
Should be present tense and imperative mood.
feat: add Xinstead offeat: added Yfix: replace A with Binstead offix: replaced A with B- When
TYPEis a verb, it may be used as part of the SUBJECT:- Bad:
fix: fix TAB breaking when focus is lost - Good:
fix: TAB breaking when focus is lost
- Bad:
-
The first word in
SUBJECTshould not be capitalized – unless it’s a code reference or a proper noun, e.g.- Good:
fix: TAB breaks when focus is lost - Good:
fix: remove buggy code - Good:
fix: John Jacob jingled Heimer's Schmidt - Bad:
feat: Add new shenanigans
- Good:
-
Do not quote symbol references and inline code:
tweak: gc-cons-threshold = (* 128 1024 1024) -
Only quote key sequences if they are ambiguous in their context:
- Good:
feat: add C-; keybind - Good:
refactor!: remove C-c C-; keybind - Bad:
fix: make SPC s m a reality - Good:
fix: make 'SPC s m' a reality - Bad:
fix: bind 'SPC '' to ivy-resume - Good:
fix: bind "SPC '" to ivy-resume
A single quote is preferred. Switch to double quote if
'is present in sequence, otherwise backquote. If all three characters are present, know that the ancient ones don’t take kindly to your summoning methods - Good:
BODY is optional and should explain the commit's changes in greater detail. It has no restrictions on tense, but should follow these conventions:
-
Line width must not exceed 72 characters, except for:
- Machine generated lines, like bump diffs:
user/repo@HASH -> user/repo@HASH - Long URLs
- Long symbol references (e.g. a long function name)
- Machine generated lines, like bump diffs:
-
Code blocks should be indented by 2 spaces from the previous paragraph, and separated from them with a blank line (before and after).
fix(foo): bar Before: (+ 1 2) After: (+ 2 1) Ref: #1234 -
Inline code should be surrounded by backquotes, ala sub-shell syntax:
fix(foo): bar `foo` calls the juxtapose of `(+ 1 2)`, i.e. `(+ 2 1)`.
For more complex commits whose changes span many files or multiple areas of the project, consider including a per-file changelog at the end of BODY (unless the changes are all pretty much identical and entirely summarized by BODY already). For example:
refactor!: rename foo to bar
BREAKING CHANGE: This changes the semantics of the `foo` function to do
X and Y, instead of Z. Any uses of this function must be updated to
reflect this.
* some/file.el (func-that-used-bar): remove `bar` use as it's no longer
needed.
* another/file.el (bar-hook, other-bar-hook): update call
* foo.el (maybe-calls-bar): update call
* a/big/file.el:
- (maybe-calls-bar): update in case of Z instead of X
- (variablename): change default to accommodate Z instead of Y
The precise format of a file log entry is either:
* FILENAME[ (SUBSCOPE[, SUBSCOPE]...)]: SUMMARY
Or, for multiple changes in one file:
* FILENAME:
- (SUBSCOPE[, SUBSCOPE]): SUMMARY
- (SUBSCOPE[, SUBSCOPE]): SUMMARY
- ...
Strive to document all non-trivial changes this way, so that readers (and parsers) can detect where a symbol was changed.
- A file log entry isn't necessary for:
- The core change itself (e.g. where
foowas changed tobar). - Changes that are trivial and have no impact on program correctness or behavior (e.g. reformatting, grammar/spelling, etc) unless it's directly relevant to the core change of the commit.
- The core change itself (e.g. where
SUBSCOPEcan be any arbitrary identifier, but 99% of the time should refer to the local symbol(s) affected.- If a change is too broad, the
SUBSCOPEs may be omitted, but this is discouraged. A long list ofSUBSCOPEs is preferred over few/no scopes, for posterity. - If a change affects a file's top-level, and doesn't affect any particular symbol, then the scope may be omitted.
- Please sort the file list lexicographically (i.e. make it match the order they're displayed in, in
git statusor the magit diff). - No blank link in between log entries.
FOOTER is where commit trailers go. Each line should be comprised of:
- A keyword followed by a colon:
Fix: REF|HASH|URL-- This commit resolves a Github issue. UseRefif it isn't certain that this commit will fix the issue.Ref: REF|HASH|URL-- Consult this resource for more information about this commit.Close: REF-- This commit supersedes a Github PR or closes a Github issue (but does not resolve it; e.g. if a commit makes the issue obsolete or indicates a decision not to address the issue).Revert: REF|HASH-- For commits that completely revert an earlier commit or un-bumps packages (repins them to earlier commits). For half-reverts useAmend.Amend: REF|HASH-- This commit addresses an issue introduced within the same release (or PR). This merges or hides the commit from the changelog generator (E.g. to avoid announcing a breaking change to behavior that was introduced before it was released).- One of Github's supported trailers, e.g.
Co-authored-by:orSigned-off-by:
- A single reference:
- An issue or PR
REFerence:#123,user/repo#123,https://git.forge.fake/repo#123 - A 12-character commit
HASH:3bedae38dd9f,user/repo@3bedae38dd9f,https://git.forge.fake/repo@3bedae38dd9f - An
URLto an external website: e.g. a mailing list, reddit discussion, etc.
- An issue or PR
Examples:
Amend: #666
Amend: 3bedae38dd9f
Close: #55
Close: user/repo#952
Fix: #1
Fix: #25
Fix: https://git.forge.fake/repo#123
Fix: user/repo#84
Ref: #4
Ref: #5
Ref: 3bedae38dd9f
Ref: https://en.wikipedia.org/wiki/Git
Ref: https://git.forge.fake/repo#123
Ref: user/repo#25
Ref: user/repo@3bedae38dd9f
Revert: 3bedae38dd9f
Co-authored-by: John Doe <john@doe.com>
Signed-off-by: Jane Doe <jane.com>
Warning
Order of trailers don't matter, but please group like-keywords together.
- Append a
!to the TYPE to indicate a breaking change. - Prepend
BREAKING CHANGE:to BODY, followed by an explanation of what is broken (and ideally, how to get around it).
Examples:
-
refactor!: remove X functionality BREAKING CHANGE: Without X, A and B will not work. Enable Y to get similar behavior. -
fix!(zig): remove lsp support BREAKING CHANGE: removing LSP support reduces how much Microsoft you must ingest to write Zig, but it means no more LSP. Only workaround is to meme on the internet, especially in obscure git convention guides that only a handful of people will ever read.