Learn Semantic Release - Conventional Commits & Commit Message Standard
Episode 3 of 23

Learn Semantic Release - Conventional Commits & Commit Message Standard

Mastering the commit format of type, scope, and subject along with ten commonly used types. Including how to mark a breaking change so that a major release is detected, complete with examples of correct and incorrect commits.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Introduction

In episode 2 we dissected semantic-release's architecture: the commit analyzer reads commit history and determines the release type. Now we learn the language it reads — because the commit analyzer is only as smart as the commit message format you write. A messy commit is like feeding the machine foreign-language text it can't parse.

Conventional Commits is a lightweight specification that turns commit messages into a parseable format: type(scope): subject. The specification is popular because it's easy for humans to learn and easy for machines to read — exactly the combination release automation needs. No essays required; just one honest line about the kind of change.

Main Discussion

Basic Format

The core format is just one line:

Basic format: type(scope): subject
type(scope): subject
feat(auth): add login page
fix(validator): fix email validation
  • type: a required keyword stating the kind of change, e.g. feat or fix.
  • scope: optional, marks the affected part of the code, e.g. auth, validator, api.
  • subject: a summary of the change, written in the imperative, without a trailing period.

A good subject answers the question: "what does this commit change?" Visually: feat(auth): add login page means "in the auth part, there's a new feature that is a login page."

Ten Common Types

TypeMeaningExample Subject
featNew featureadd login page
fixBug fixfix email validation
perfPerformance improvementspeed up list rendering
refactorInternal change, not a bugtidy up auth module
docsDocumentation changefix setup guide
testAdd or change testsadd login flow tests
choreRoutine non-functional taskupdate security dependencies
buildBuild system changeupdate bundler config
ciCI configuration changemove to setup-node v4
revertRevert a commitrevert commit 3f2a1b0

Impact of Types on Releases

The commit analyzer maps types to release types. With the default preset, only feat and fix trigger a release; the rest need to be configured via releaseRules as this repo does.

TypeRelease Impact
featminor
fix, hotfixpatch
perf, refactor, chore, revertpatch
docs, test, ci, styleno release
Breaking changemajor

Note

The default Angular preset only recognizes feat bumping minor and fix bumping patch. Additional mappings like perf and refactor bumping patch, or chore triggering a release, are the result of customizing releaseRules — not default behavior. We'll build our own in episode 5.

Breaking Changes

Changes that break compatibility are marked with a BREAKING CHANGE: footer or an exclamation mark ! after the type or scope. Both trigger a major release.

Marking a breaking change with a footer and exclamation mark
feat(auth): migrate to JWT-based tokens
 
BREAKING CHANGE: the old token format is no longer supported
 
feat!: drop Node 16 support

Important note: the BREAKING CHANGE keyword must be in the footer, separated from the subject by a blank line. This repo even registers BREAKING CHANGE and BREAKING CHANGES in parserOpts.noteKeywords so that both forms are recognized.

Correct and Incorrect Examples

Commits that are correct and commits that mislead
fix(auth): fix login failing with uppercase email   # correct
feat: add dashboard page                            # correct
update email validation                             # wrong
fix bug                                             # wrong

The most common mistakes: not using a type at all, or a subject that is too vague like fix bug — what was fixed? where? The machine can't guess, and the resulting changelog will be useless.

Warning

fix bug and update can't be parsed as fix. As a result, that commit doesn't trigger a release, and its fix never reaches users until another correctly formatted commit arrives. A lazy commit message is a hidden cost: the changelog gets corrupted and releases get delayed.

Tips for Writing Commits

  1. Write an imperative, short subject — keep it around 50-72 characters.
  2. Use lowercase for both type and subject.
  3. Don't end the subject with a period.
  4. Put breaking changes in the footer, not the subject.
  5. If a change is large, split it into several small well-formed commits — the changelog will be much more readable.
Conventions for writing commit subjects
"add login page"            # imperative
"adding login page"         # gerund, avoid
"add login page."           # ends with a period, avoid

Conclusion

In episode 3 you learned:

  • The type(scope): subject format with a required type and optional scope.
  • Ten common types: feat, fix, perf, refactor, docs, test, chore, build, ci, revert.
  • Type-to-release mapping: feat minor, fix patch, breaking major.
  • Breaking changes via a BREAKING CHANGE: footer or the ! exclamation mark.

In episode 4 we'll look at where those commits live: the Git Flow branching strategy with staging as the release candidate and main as the stable branch. See you in episode 4!