Conventional Commits
Conventional Commits is a specification for adding human and machine-readable meaning to commit messages. Versu relies on this standard to automatically determine version bumps.
Commit Format
The basic format of a Conventional Commit is:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]Types
The standard types and their default version impacts are:
| Type | Meaning | Default Version Impact |
|---|---|---|
feat | A new feature | Minor bump |
fix | A bug fix | Patch bump |
docs | Documentation only | Patch bump |
style | Changes that don't affect code meaning (whitespace, formatting) | Patch bump |
refactor | Code change that doesn't fix a bug or add a feature | Patch bump |
perf | Code change that improves performance | Patch bump |
test | Adding or updating tests | Patch bump |
chore | Changes to build process, dependencies, etc. | Patch bump |
ci | Changes to CI configuration | Patch bump |
build | Changes that affect the build system | Patch bump |
Custom types are also allowed and will default to a patch bump unless configured otherwise.
INFO
Out of the box, every recognized commit type triggers at least a patch bump - only feat (minor) and breaking changes (major) go higher. If you prefer types like docs or chore to not bump versions at all, map them to "none" in your configuration (see the example below).
TIP
You can customize the types and their version impacts in your versu.config.js if you want to treat them differently.
Breaking Changes
A breaking change is indicated by adding BREAKING CHANGE: in the footer or by adding an exclamation mark ! after the type/scope.
Example with Footer
feat: send email notification to user
BREAKING CHANGE: The email notification API has changedExample with Exclamation Mark
feat!: redesign authentication systemBoth trigger a MAJOR version bump.
Scope
The scope is optional and specifies what part of the codebase is affected:
feat(auth): add login endpointCommon scopes might be: auth, api, cli, core, etc.
Examples
Feature Example
feat(auth): add OAuth2 support
Implement OAuth2 authentication with GitHub and Google providers.
Closes #123Result: Minor version bump
Bug Fix Example
fix(api): handle null pointer exception
The API was throwing a null pointer exception when processing
empty request bodies.Result: Patch version bump
Breaking Change Example
feat(api)!: change response format from XML to JSON
The API response format has changed from XML to JSON.
All clients must update their parsers.
BREAKING CHANGE: Response format is now JSON instead of XMLResult: Major version bump
Documentation Example
docs: update README with installation instructionsResult: Patch version bump (by default - configurable, see below)
Best Practices
✅ Do's
- Use lowercase for type and scope
- Be descriptive and concise
- Include issue references when applicable
- Use imperative mood ("add feature" not "added feature")
- Keep the subject line under 50 characters
❌ Don'ts
- Use vague descriptions like "update stuff"
- Mix multiple unrelated changes in one commit
- Use all caps for types
- Include irrelevant information
Examples of Good Commits
feat: add user authentication module
fix(database): handle connection timeout
docs(contributing): add development setup guide
refactor(core): extract validation logic to separate module
feat(cli)!: change command structure
BREAKING CHANGE: Command syntax has changed from 'npx @versu/cli run' to 'npx @versu/cli'Versu Integration
Versu reads your commit history and:
- Identifies commit types (feat, fix, etc.)
- Detects breaking changes (BREAKING CHANGE footer or
!) - Calculates version bumps based on the types found
- Generates changelogs with commit messages organized by type
Configuration
You can customize how Versu interprets commit types and their impacts on versioning in your versu.config.js.
From defining which types trigger which version bumps to specifying how dependency updates should be handled, you have full control over the versioning strategy.
The example below keeps the defaults for code changes but disables bumps for non-code types (docs, test, chore, style, ci, build):
export default {
versioning: {
breakingChange: {
stable: "major",
prerelease: "premajor",
},
unknownCommitType: {
stable: "patch",
prerelease: "prepatch",
},
commitTypes: {
feat: {
stable: "minor",
prerelease: "preminor",
},
fix: {
stable: "patch",
prerelease: "prepatch",
},
perf: {
stable: "patch",
prerelease: "prepatch",
},
refactor: {
stable: "patch",
prerelease: "prepatch",
},
docs: {
stable: "none",
prerelease: "none",
},
test: {
stable: "none",
prerelease: "none",
},
chore: {
stable: "none",
prerelease: "none",
},
style: {
stable: "none",
prerelease: "none",
},
ci: {
stable: "none",
prerelease: "none",
},
build: {
stable: "none",
prerelease: "none",
},
},
cascadeRules: {
stable: {
major: "major",
minor: "minor",
patch: "patch",
},
prerelease: {
premajor: "premajor",
preminor: "preminor",
prepatch: "prepatch",
prerelease: "prerelease",
},
},
},
}Further Reading
Ready to use Conventional Commits in your project? Check out the Quick Start guide!
