Commit conventions (Conventional Commits)
Why a convention for commit messages
A commit message is a note to the future — to you and the team six months from now. Conventional Commits is a simple standard that gives messages structure, so that history stays readable and tools can generate changelogs and version numbers from it.
Format
<type>(<optional scope>): <description>
<optional body>
<optional footer>
Examples:
feat(dashboard): dodaj widżet MFA
fix(auth): popraw redirect po wygaśnięciu sesji
docs(readme): uzupełnij instrukcję deployu
refactor(api): wydziel walidację do osobnej funkcji
Commit types
| Type | Meaning |
|---|---|
feat | New functionality |
fix | Bug fix |
docs | Documentation only |
style | Formatting, no logic change |
refactor | Code change with no new feature or fix |
test | Adding/improving tests |
chore | Configuration, dependencies, tooling |
ci | Changes to the CI/CD pipeline |
perf | Performance optimization |
Link to versioning (SemVer)
The types map to semantic versioning:
fix:→ a PATCH bump (1.2.3 → 1.2.4)feat:→ a MINOR bump (1.2.3 → 1.3.0)- BREAKING CHANGE → a MAJOR bump (1.2.3 → 2.0.0)
You flag a breaking change with ! or a footer:
feat(api)!: zmień format odpowiedzi raportów
BREAKING CHANGE: pole "total" zwraca teraz wartość netto zamiast brutto.
Tip: Write the description in the imperative, as if completing the sentence "If applied, this commit will …": "add X", "fix Y" — not "added", "adds". This is the convention used by Git itself.
Enforcing the convention in CI
You can check the format automatically. Locally via the commitlint hook, and in the pipeline as a GitHub Actions step:
name: Lint commits
on: [pull_request]
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v6
Good habits
- One commit = one logical change.
- First line ≤ ~72 characters, no period at the end.
- In the commit body explain why, not just what (the what is visible in the diff).
- A scope (
dashboard,auth) makes searching the history easier.
The end benefit
Consistent commits let tools like release-please or
semantic-release automatically create the changelog and tag versions based
on the history alone — zero manual release notes.
Summary
Conventional Commits is a small cost and a big convenience: type(scope): description in
the imperative mood. The types map to SemVer, and CI with commitlint guards the format.
The result is a readable history and automatic changelogs.