Skip to content

Instantly share code, notes, and snippets.

@qoomon
Last active June 12, 2026 19:59
Show Gist options
  • Select an option

  • Save qoomon/5dfcdf8eec66a051ecd85625518cfd13 to your computer and use it in GitHub Desktop.

Select an option

Save qoomon/5dfcdf8eec66a051ecd85625518cfd13 to your computer and use it in GitHub Desktop.
Conventional Commits Cheatsheet

Conventional Commit Messages starline

See how a minor change to your commit message style can make a difference.

git commit -m"<type>(<optional scope>): <description>" \
  -m"<optional body>" \
  -m"<optional footer>"

Note

This cheatsheet is opinionated, however it does not violate the specification of conventional commits

Tip

Take a look at git-conventional-commits a CLI util to ensure these conventions, determine version and generate changelogs.

Commit Message Formats

General Commit

<type>(<optional scope>): <description>
empty line as separator
<optional body>
empty line as separator
<optional footer>

Initial Commit

chore: init

Merge Commit

Merge branch '<branch name>'

Follows default git merge message

Revert Commit

Revert "<reverted commit subject line>"

Follows default git revert message

Types

  • Changes relevant to the API or UI:
    • feat Commits that add, adjust or remove a feature to/of/from the API or UI
    • fix Commits that fix an API or UI bug of a preceded feat commit
  • refactor Commits that rewrite or restructure code without altering API or UI behavior
    • perf Commits are special type of refactor commits that specifically improve performance
  • style Commits that address code style (e.g., white-space, formatting, missing semi-colons) and do not affect application behavior
  • test Commits that add missing tests or correct existing ones
  • docs Commits that exclusively affect documentation
  • build Commits that affect build-related components such as build tools, dependencies, project version, ...
  • ops Commits that affect operational aspects like infrastructure (IaC), deployment scripts, CI/CD pipelines, backups, monitoring, or recovery procedures, ...
  • chore Commits that represent tasks like initial commit, modifying .gitignore, ...

Scopes

The scope provides additional contextual information.

  • The scope is an optional part
  • Allowed scopes vary and are typically defined by the specific project
  • Do not use issue identifiers as scopes

Breaking Changes Indicator

  • A commit that introduce breaking changes must be indicated by an ! before the : in the subject line e.g. feat(api)!: remove status endpoint
  • Breaking changes should be described in the commit footer section, if the commit description isn't sufficiently informative

Description

The description contains a concise description of the change.

  • The description is a mandatory part
  • Use the imperative, present tense: "change" not "changed" nor "changes"
    • Think of This commit will... or This commit should...
  • Do not capitalize the first letter
  • Do not end the description with a period (.)
  • In case of breaking changes also see breaking changes indicator

Body

The body should include the motivation for the change and contrast this with previous behavior.

  • The body is an optional part
  • Use the imperative, present tense: "change" not "changed" nor "changes"

Footer

The footer should contain issue references and informations about Breaking Changes

  • The footer is an optional part, except if the commit introduce breaking changes
  • Optionally reference issue identifiers (e.g., Closes #123, Fixes JIRA-456)
  • Breaking Changes must start with the word BREAKING CHANGE:
    • For a single line description just add a space after BREAKING CHANGE:
    • For a multi line description add two new lines after BREAKING CHANGE:

Versioning

  • If your next release contains commit with...
    • Breaking Changes incremented the major version
    • API relevant changes (feat or fix) incremented the minor version
  • Else increment the patch version

Examples

  • feat: add email notifications on new direct messages
    
  • feat(shopping cart): add the amazing button
    
  • feat!: remove ticket list endpoint
    
    refers to JIRA-1337
    
    BREAKING CHANGE: ticket endpoints no longer supports list all entities.
    
  • fix(shopping-cart): prevent order an empty shopping cart
    
  • fix(api): fix wrong calculation of request body checksum
    
  • fix: add missing parameter to service call
    
    The error occurred due to <reasons>.
    
  • perf: decrease memory footprint for determine unique visitors by using HyperLogLog
    
  • build: update dependencies
    
  • build(release): bump version to 1.0.0
    
  • refactor: implement fibonacci number calculation as recursion
    
  • style: remove empty line
    

Git Hook Scripts to ensure commit message header format

Click to expand

commit-msg Hook (local)

pre-receive Hook (server side)

  • create following file in your repository folder .git/hooks/pre-receive
    #!/usr/bin/env bash
    
    # Pre-receive hook that will block commits with messages that do not follow regex rule
    
    commit_msg_type_regex='feat|fix|refactor|style|test|docs|build'
    commit_msg_scope_regex='.{1,20}'
    commit_msg_description_regex='.{1,100}'
    commit_msg_regex="^(${commit_msg_type_regex})(\(${commit_msg_scope_regex}\))?: (${commit_msg_description_regex})\$"
    merge_msg_regex="^Merge branch '.+'\$"
    
    zero_commit="0000000000000000000000000000000000000000"
    
    # Do not traverse over commits that are already in the repository
    excludeExisting="--not --all"
    
    error=""
    while read oldrev newrev refname; do
      # branch or tag get deleted
      if [ "$newrev" = "$zero_commit" ]; then
        continue
      fi
    
      # Check for new branch or tag
      if [ "$oldrev" = "$zero_commit" ]; then
        rev_span=`git rev-list $newrev $excludeExisting`
      else
        rev_span=`git rev-list $oldrev..$newrev $excludeExisting`
      fi
    
      for commit in $rev_span; do
        commit_msg_header=$(git show -s --format=%s $commit)
        if ! [[ "$commit_msg_header" =~ (${commit_msg_regex})|(${merge_msg_regex}) ]]; then
          echo "$commit" >&2
          echo "ERROR: Invalid commit message format" >&2
          echo "$commit_msg_header" >&2
          error="true"
        fi
      done
    done
    
    if [ -n "$error" ]; then
      exit 1
    fi
  • ⚠ make .git/hooks/pre-receive executable (unix: chmod +x '.git/hooks/pre-receive')

References


@goyalyashpal

goyalyashpal commented Feb 27, 2025

Copy link
Copy Markdown

thanks a lot for sharing detailed thoughts.

  • i agree with you on not splitting refac further.

  • as for the enh, there are several times when there is no API. like in:

    • creating some static website (like profile readmes, or blogs, etc), or
    • producing some PDF document (like book, manual, etc). or
    • package metadatas / configs (like scoop for windows, pkg files for arch, or nixpkgs / flakes for nixos)

    in all these cases, enhance helps a lot.

  • i appreciate standards, but in this case, i like to stick to 52 character limit in the commit title more, and even if you ignore the readability improvements, those 3 characters really make or break things at times.

  • thanks a lot for detailing on ci too. i haven't had much experience with build tools, will keep in mind in future.

@qoomon

qoomon commented Feb 27, 2025

Copy link
Copy Markdown
Author

as for the enh, there are several times when there is no API. like in:
creating some static website (like profile readmes, or blogs, etc), or

readme would be docs, a new blog post would be a new feat if you add static content to your repo

producing some PDF document (like book, manual, etc). or

most likely docs commit as well

package metadatas / configs (like scoop for windows, pkg files for arch, or nixpkgs / flakes for nixos)

these would be ops commits

@goyalyashpal

goyalyashpal commented Feb 27, 2025

Copy link
Copy Markdown

most likely docs commit as well

not if the whole repo is dedicated to docs lol 😆

yes, readme comes under docs for normal repos. but in case of profile repos, the readme is the main show itself.

@qoomon

qoomon commented Feb 27, 2025

Copy link
Copy Markdown
Author

but in case of profile repos, the readme is the main show itself.

then its a feat commit. it depends on what is your interface of your application (API/UI)

@barraIhsan

Copy link
Copy Markdown

What do you guys think about adding/modifying a comments to clarify the code fall into?
Is it docs or style

@qoomon

qoomon commented Mar 9, 2025

Copy link
Copy Markdown
Author

@barraIhsan what's not clear about the current comments

docs Commits, that affect documentation only
style Commits, that do not affect the meaning (white-space, formatting, missing semi-colons, etc)

Do you have suggestions to improve the comments?

@barraIhsan

barraIhsan commented Mar 9, 2025

Copy link
Copy Markdown

no, I meant I was asking if I edited a comments in my codebase, what commit type it should fall into?
For example

+ // This function will add two numbers
fn add(x: i32, y: i32) {
  x+y
}

Currently I think that docs: add missing comments on function suits well, but whats your opinion about it?

Oh also, isn't it supposed to be BREAKING CHANGE: without s?

@barraIhsan

Copy link
Copy Markdown

and, when we're removing something like remove pages, remove unused functions, replace a plugin with another one.
We use feat for that right? I've been using chore this whole time. I interpret it as the wildcard type.

@qoomon

qoomon commented Mar 9, 2025

Copy link
Copy Markdown
Author

@barraIhsan

Currently I think that docs: add missing comments on function suits well, but whats your opinion about it?

I would chose docs as well for these changes.

@qoomon

qoomon commented Mar 9, 2025

Copy link
Copy Markdown
Author

@barraIhsan

Oh also, isn't it supposed to be BREAKING CHANGE: without s?

yes you are right I'll fix that or add singular wording as well i think both singular and plural should be valid

@barraIhsan

Copy link
Copy Markdown

@barraIhsan

Currently I think that docs: add missing comments on function suits well, but whats your opinion about it?

I would chose docs as well for these changes.

ahh okay then. Thanks for clarifying that out. I've been using it all wrong this whole time

@qoomon

qoomon commented Mar 9, 2025

Copy link
Copy Markdown
Author

@barraIhsan

and, when we're removing something like remove pages,

if that results in an change for the user it should be a feat otherwise it's probably refactor

remove unused functions,

probably it's a refactor commit, unless it changes the api of your project e.g. you project is an library and the function was exposed to lib users then it would be feat

replace a plugin with another one.

probably it's a refactor commit, unless it also change the the ui or api of your project

I've been using chore this whole time. I interpret it as the wildcard type.

chore should definitely not be used as a wildcard type or fallback type

@barraIhsan

Copy link
Copy Markdown

ahh okay! Thanks for the clarification!

@muzaffaar

Copy link
Copy Markdown

Amazing!

@qoomon

qoomon commented Apr 10, 2025

Copy link
Copy Markdown
Author

🙏thanks :-)

@mehrsamoradi

mehrsamoradi commented Apr 22, 2025

Copy link
Copy Markdown

Is it appropriate to use chore when we're only updating the version of a dependency?

@qoomon

qoomon commented Apr 22, 2025

Copy link
Copy Markdown
Author

@malihehmoradi IMHO it should be build or even build(deps): ... because build indicates changes in the build process that includes changes to dependencies

@qoomon

qoomon commented Apr 24, 2025

Copy link
Copy Markdown
Author

@flip12322 💚

@hacker-hackman

hacker-hackman commented May 8, 2025

Copy link
Copy Markdown

What type should be used when we've updated our app's repository to incorporate changes from the upstream repository on which our app is based?

I've named the commit like this:
chore: sync codebase with upstream repository changes

@qoomon

qoomon commented May 8, 2025

Copy link
Copy Markdown
Author

@hacker-hackman thats a tricky one. If its a merge just keep it a merge commit. If it is a commit without history, then it depends what the changes are, in other words could be any commit type. chore is probably not a good fit because it gives the impression of an safe commit without the risk of breaking changes or new features.

@qoomon

qoomon commented May 8, 2025

Copy link
Copy Markdown
Author

@hacker-hackman I probably would go for feat or introduce a new type like upstream

@hacker-hackman

Copy link
Copy Markdown

In this specific case, it was indeed a low-risk sync with the upstream repository, containing only formatting and type checking changes. Thanks for the insight!

@GabenGar

Copy link
Copy Markdown

Just go for chore when dealing with merges/sync. Or create a separate sync type.

@qoomon

qoomon commented May 13, 2025

Copy link
Copy Markdown
Author

@GabenGar again I would highly recommend to NOT use chore for syncs from repository external sources. It should reflect what has been synched especially if you sync feat or fix commits. If you do a regular merge, within the sam repo and history chore would be okay, however I would stick with the default merge message.

@AlphaHasher

Copy link
Copy Markdown

Typo in heading: Inital Commit

@qoomon

qoomon commented May 19, 2025

Copy link
Copy Markdown
Author

@AlphaHasher thx, it's fixed.

@tamXinchao

Copy link
Copy Markdown

thanks for this. It really what i need now

@yasithgwd

Copy link
Copy Markdown

really helpful thanks !!!

@qoomon

qoomon commented May 30, 2025

Copy link
Copy Markdown
Author

❤️

@nafg

nafg commented Jun 12, 2025

Copy link
Copy Markdown

@qoomon now it says ops twice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment