In this session, we’ll walk through the Conventional Commits spec and why it’s useful in practice:
Without a shared convention, git history can easily become:
git logA lightweight convention for commit messages that are:
It “dovetails with SemVer” by making it easy to identify:
Examples:
feat: add portfolio export to CSVfix(api): handle empty scenario setrefactor!: drop legacy endpointCommon, widely-used types:
Scopes are optional, but can help answer “where” a change is relevant, especially in larger codebases:
Examples:
Good scopes are:
Using a “bang” (!) in the header indicates a breaking change:
feat!: remove v1 scenario fieldsIf you need to give more context, you can use a footer in the commit description:
feat!: remove v1 scenario fields
BREAKING CHANGE: v1 fields were removed; migrate to v2 schema
The common automated release mapping goes something like:
fix -> PATCHfeat -> MINOR! or BREAKING CHANGE -> MAJOROther types need to be mapped appropriately. This is still just a convention (not magic) and requires engineers to buy into using the convention consistently.
fix(auth): refresh tokens on 401
Previously, an expired token caused an infinite retry loop.
Now we refresh once and surface an error if it fails.
Refs: STIT-125, #823
ignore stuffchore(git): add build artifacts to .gitignoreIf the repo you are working on uses squash merges the PR title gets squashed into a commit message. Write the PR title as a conventional commit!
feat(ui): add scenario pickerConventional Commits are machine-parseable, so automation can reliably:
Validate messages at commit / PR time
→ catches missing type, malformed scope, or unclear descriptions early
Classify changes from history
→ groups commits into Features, Fixes, Docs, Chores, etc.
Generate release notes / changelogs
→ produces consistent summaries straight from merged work
Decide the next version (if you use SemVer)
→ fix → patch, feat → minor, BREAKING CHANGE / ! → major
Create traceability links
→ connect releases back to PRs/issues via structured footers