Skip to content

Instantly share code, notes, and snippets.

@milksense
Created February 17, 2026 21:44
Show Gist options
  • Select an option

  • Save milksense/2c7c1f06ff5194e577ee3a76b9e2bc79 to your computer and use it in GitHub Desktop.

Select an option

Save milksense/2c7c1f06ff5194e577ee3a76b9e2bc79 to your computer and use it in GitHub Desktop.
Conventional Commits Guide

Conventional Commits Guide

Located at

.git/hooks/commit-msg

Introduction

Conventional commits provide a consistent way to structure commit messages, which helps with automation, release notes generation, and understanding the history of a project. The format adheres to the following structure:

<type>(<scope>): <message>

Or, if the commit introduces a breaking change:

<type>(<scope>)!: <message>

For more details, see the official documentation: https://www.conventionalcommits.org

πŸ”₯ Quick Example

feat(api): add user registration endpoint
fix(auth): handle expired token edge case
refactor(core)!: remove deprecated session manager

BREAKING CHANGE: Session manager has been removed. Replace it with the new auth lifecycle.

πŸ’‘ With Emojis (optional style)

Some teams like to use emojis as part of the commit message to make it easier to visually distinguish commit types. Emojis can be used in the message, but the commit type still follows the standard (e.g., fix:, feat:). Here's how it can be applied:

feat(auth): ✨ implement OAuth2 login
fix(ui): πŸ› resolve flickering issue in dark mode
refactor(core)!: ♻️ simplify session logic

BREAKING CHANGE: Session handling is now stateless and requires new configuration.

Commit Types

feat

A new feature has been added.

Example:

feat(auth): add user login functionality

With Emoji:

feat(auth): ✨ add user login functionality

fix

A bug has been fixed.

Example:

fix(ui): correct button alignment on mobile

With Emoji:

fix(ui): πŸ› correct button alignment on mobile

docs

Changes related to documentation only.

Example:

docs: update README with new setup instructions

With Emoji:

docs: πŸ“š update README with new setup instructions

style

Changes that do not affect the meaning of the code (e.g., formatting, missing semicolons).

Example:

style(ui): update button padding and font size

With Emoji:

style(ui): πŸ’… update button padding and font size

refactor

Refactoring code (i.e., no new features, no bug fixes, but changes to the structure of the code).

Example:

refactor(auth): restructure authentication middleware

With Emoji:

refactor(auth): ♻️ restructure authentication middleware

perf

Changes that improve performance.

Example:

perf(api): optimize database query for user search

With Emoji:

perf(api): ⚑ optimize database query for user search

test

Adding or updating tests.

Example:

test(auth): add unit tests for login functionality

With Emoji:

test(auth): πŸ§ͺ add unit tests for login functionality

chore

Other changes that don't modify application behavior (e.g., build, tooling).

Example:

chore: update dependencies

With Emoji:

chore: πŸ”§ update dependencies

build

Changes that affect the build system or external dependencies (e.g., packaging, deployment).

Example:

build: configure webpack for production

With Emoji:

build: πŸ› οΈ configure webpack for production

ci

Changes related to continuous integration.

Example:

ci: add CircleCI configuration for automated testing

With Emoji:

ci: 🎑 add CircleCI configuration for automated testing

Breaking Changes

If your commit introduces a breaking change, use a ! immediately after the type or scope, and optionally include a BREAKING CHANGE: footer to explain it.

Example:

feat(auth)!: change token format to JWT v2

BREAKING CHANGE: Token format is now incompatible with previous versions. Clients must update to handle the new format.

This makes it easy for tools like semantic-release to detect breaking changes and bump major versions automatically.

Conclusion

By using Conventional Commits, you ensure a clean, organized commit history that can be easily understood by other developers and enable automation like changelog generation and semantic versioning.

Learn more at: https://www.conventionalcommits.org

#!/usr/bin/env bash
# Path to the commit message file (provided by Git).
COMMIT_MSG_FILE=$1
# Ignore automatic commit messages containing ' into ' or 'Merge'.
if grep --quiet --extended-regexp " into |^Merge " "$COMMIT_MSG_FILE"; then
exit 0
fi
COMMIT_MSG=$(head -n 1 "$COMMIT_MSG_FILE" | tr -d '\r')
CONVENTIONAL_COMMIT_REGEX='^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\([a-zA-Z0-9_.-]+\))?(!)?:[[:space:]].*$'
# Check if the commit message matches the regex.
if ! [[ $COMMIT_MSG =~ $CONVENTIONAL_COMMIT_REGEX ]]; then
echo "ERROR: Commit message does not follow Conventional Commits format."
echo "Your header was: $COMMIT_MSG"
echo
echo "The commit message should be structured as follows:"
echo "<type>(<optional scope>): <description>"
echo "[optional body]"
echo "[optional footer(s)]"
echo
echo "Valid types are:"
echo " feat: A new feature."
echo " fix: A bug fix."
echo " docs: Documentation changes."
echo " style: Code style changes (formatting, missing semicolons, etc.)."
echo " refactor: Code refactoring (neither fixes a bug nor adds a feature)."
echo " test: Adding or updating tests."
echo " chore: Routine tasks like updating dependencies or build tools."
echo " build: Changes affecting the build system or external dependencies."
echo " ci: Changes to CI configuration files or scripts."
echo " perf: Performance improvements."
echo " revert: Reverting a previous commit."
echo
echo "Examples:"
echo " feat(auth): add login functionality"
echo " fix(api)!: resolve timeout issue"
echo " docs(readme): update installation instructions"
echo
exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment