Skip to content

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:

text
<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Types

The standard types and their default version impacts are:

TypeMeaningDefault Version Impact
featA new featureMinor bump
fixA bug fixPatch bump
docsDocumentation onlyPatch bump
styleChanges that don't affect code meaning (whitespace, formatting)Patch bump
refactorCode change that doesn't fix a bug or add a featurePatch bump
perfCode change that improves performancePatch bump
testAdding or updating testsPatch bump
choreChanges to build process, dependencies, etc.Patch bump
ciChanges to CI configurationPatch bump
buildChanges that affect the build systemPatch 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.

text
feat: send email notification to user

BREAKING CHANGE: The email notification API has changed

Example with Exclamation Mark

text
feat!: redesign authentication system

Both trigger a MAJOR version bump.

Scope

The scope is optional and specifies what part of the codebase is affected:

text
feat(auth): add login endpoint

Common scopes might be: auth, api, cli, core, etc.

Examples

Feature Example

text
feat(auth): add OAuth2 support

Implement OAuth2 authentication with GitHub and Google providers.
Closes #123

Result: Minor version bump

Bug Fix Example

text
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

text
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 XML

Result: Major version bump

Documentation Example

text
docs: update README with installation instructions

Result: 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

text
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:

  1. Identifies commit types (feat, fix, etc.)
  2. Detects breaking changes (BREAKING CHANGE footer or !)
  3. Calculates version bumps based on the types found
  4. 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):

javascript
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!

Released under the MIT License.