Skip to content

Git Commit Messages

This document outlines the required standards and conventions for writing Git commit messages within our project. It serves as a primary reference for all contributors to ensure our version control history remains clear and consistent.

Why Commit Messages Matter

Good commit messages are essential for maintaining a healthy codebase. They serve as a historical record of what changed, why it changed, and how it impacts the project. Well-written commits help teammates understand your work, make code reviews more efficient, enable easier debugging when issues arise, and create a clear audit trail for future developers.

Think of commit messages as documentation that lives alongside your code-they're often the first place someone will look when trying to understand why a particular change was made.

Our Commit Message Format

We follow the Conventional Commits specification, which provides a standardized structure:

<type>(<optional scope>): <description>

[optional body]

[optional footer]

Commit Types Reference

The Conventional Commits specification define the following commit prefixes:

  • feat: A new feature for users or a new capability in the code. This signals that you've added something new to the code base. These changes typically result in a minor version bump in semantic versioning.
  • Example: feat(auth): add login functionality
  • fix: A bug fix that corrects unwanted behavior. Use this when you've resolved an issue or error. These changes typically result in a patch version bump.
  • Example: fix(parser): handle edge case
  • docs: Documentation changes only, such as updating README files, adding comments, or revising API documentation. No code functionality changes.
  • Example: docs(readme): update installation instructions
  • style: Code formatting changes that don't affect functionality-fixing indentation, adding missing semicolons, removing whitespace, or applying linting rules.
  • Example: style: fix indentation of user model
  • refactor: Code restructuring that neither adds features nor fixes bugs. This might include renaming variables for clarity, reorganizing functions, or improving code structure without changing behavior.
  • Example: refactor: extract validation logic into service
  • test: Adding new tests or updating existing test cases. Use this when working exclusively on test files.
  • Example: test: add unit tests for new API endpoint
  • chore: Routine maintenance tasks like updating dependencies, modifying build configurations, or other housekeeping that doesn't modify source or test files.
  • Example: chore: update dependencies to latest stable
  • build: Changes to the build system or external dependencies-updating package.json, modifying webpack config, or adjusting build scripts.
  • Example: build: update webpack configuration
  • ci: Changes to continuous integration configuration files or scripts, such as GitHub Actions, Jenkins, or deployment pipelines.
  • Example: ci: add E2E test job
  • perf: Performance improvements that make code run faster or use fewer resources without changing functionality.
  • Example: perf: optimize image loading speed
  • revert: Reverting a previous commit. Include information about which commit is being reverted and why.
  • Example: revert: "feat: experimental feature"

Adding Scope and Breaking Changes

Scope (optional) provides additional context about which part of the codebase changed: feat(api): add user endpoint or fix(parser): handle edge case.

Breaking Changes are indicated with an exclamation mark before the colon: feat!: redesign authentication system. You can also include a BREAKING CHANGE: footer in your commit message to explain the impact.

Quick Tips

  • Keep the description line under 50-72 characters when possible
  • Use the imperative mood: "add feature" not "added feature"
  • The description should complete the sentence: "This commit will..."
  • Use the optional body to explain why you made the change, not just what changed
  • Reference issue numbers in footers when relevant: Refs: #123

Following these conventions makes our project history scannable, enables automated changelog generation, and helps everyone on the team understand changes at a glance.

Examples

Simple style

style: remove unused imports flagged by linter

Test with scope

test(auth): add unit tests for login validation

Refactor with body

refactor: rename getUserData to fetchUserProfile

New name better reflects that this function makes an async network request rather than just returning cached data

Fix with breaking change

fix(database)!: change user ID from integer to UUID

Switched from auto-incrementing integers to UUIDs for better distributed system support and security.

BREAKING CHANGE: user IDs are now strings instead of numbers

Migration: scripts/migrate_user_ids.sql

Refs: #321