Skip to content

Instantly share code, notes, and snippets.

@qoomon
Last active July 14, 2024 12:16
Show Gist options
  • Save qoomon/5dfcdf8eec66a051ecd85625518cfd13 to your computer and use it in GitHub Desktop.
Save qoomon/5dfcdf8eec66a051ecd85625518cfd13 to your computer and use it in GitHub Desktop.
Conventional Commits Cheatsheet

Conventional Commit Messages

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

Tip

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

Commit Message Formats

Default

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

Merge Commit

Merge branch '<branch name>'

Follows default git merge message

Revert Commit

Revert "<reverted commit subject line>"

Follows default git revert message

Inital Commit

chore: init

Types

  • API relevant changes
    • feat Commits, that adds or remove a new feature
    • fix Commits, that fixes a bug
  • refactor Commits, that rewrite/restructure your code, however does not change any API behaviour
    • perf Commits are special refactor commits, that improve performance
  • style Commits, that do not affect the meaning (white-space, formatting, missing semi-colons, etc)
  • test Commits, that add missing tests or correcting existing tests
  • docs Commits, that affect documentation only
  • build Commits, that affect build components like build tool, ci pipeline, dependencies, project version, ...
  • ops Commits, that affect operational components like infrastructure, deployment, backup, recovery, ...
  • chore Miscellaneous commits e.g. modifying .gitignore

Scopes

The scope provides additional contextual information.

  • Is an optional part of the format
  • Allowed Scopes depends on the specific project
  • Don't use issue identifiers as scopes

Breaking Changes Indicator

Breaking changes should be indicated by an ! before the : in the subject line e.g. feat(api)!: remove status endpoint

  • Is an optional part of the format

Description

The description contains a concise description of the change.

  • Is a mandatory part of the format
  • Use the imperative, present tense: "change" not "changed" nor "changes"
    • Think of This commit will... or This commit should...
  • Don't capitalize the first letter
  • No dot (.) at the end

Body

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

  • Is an optional part of the format
  • Use the imperative, present tense: "change" not "changed" nor "changes"
  • This is the place to mention issue identifiers and their relations

Footer

The footer should contain any information about Breaking Changes and is also the place to reference Issues that this commit refers to.

  • Is an optional part of the format
  • optionally reference an issue by its id.
  • Breaking Changes should start with the word BREAKING CHANGES: followed by space or two newlines. The rest of the commit message is then used for this.

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 CHANGES: ticket enpoints no longer supports list all entites.
    
  • fix(api): handle empty message in request body
    
  • fix(api): fix wrong calculation of request body checksum
    
  • fix: add missing parameter to service call
    
    The error occurred because of <reasons>.
    
  • perf: decrease memory footprint for determine uniqe 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 messges 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


@superco01
Copy link

hi @qoomon i made an update here to add revert
kindly give your thoughts on this

@qoomon
Copy link
Author

qoomon commented Oct 6, 2023

@superco01 thx, I've added it as well

@ttytm
Copy link

ttytm commented Oct 9, 2023

If using conventional commit prefixes or not, for those who get stuck with Added, Adding, Adds / fixed fixing fixes and equivalents instead of add / fix in the commit body, think of it this way:

  • Either taking an imperative tone, commanding it to do something: Add ...

  • Or, "this commit should fix ..." / "this PR [aims/wants] to fix ..."

Both ways are semantically more correct versions that come closer to what is actually happening - as commits often should do something, but sometimes don't do what they state or want to do.

So thinking about it as This commit should... would also be more correct than This commit will.... Greetings from the nitpicky asshole in my cortex.

@qoomon
Copy link
Author

qoomon commented Oct 9, 2023

👍

@upmorpheus
Copy link

It is very great!
If you are a senior software engineer, you will use that commits like that.

@bloggerklik
Copy link

Here are some confusions 🤔

  1. What should be the conventional commit type when I install or update a new package?
  2. I am developing a mobile app. For example, which type should I use when I upgrade versionCode or versionName to release new version?
  3. Which type should I use when I remove a feature I added?

Thanks.

@qoomon
Copy link
Author

qoomon commented Nov 10, 2023

Hi @bloggerklik, I would use following conversation

1# use build: update dependencies or build: update dependency xxxxx, unless this will change the API of your artifact then it would be a feat: ... commit

#2 use build(release): bump version to x.x.x

#3 use feat!: remove ...., if you change the API it is always a feat: no matter if you add or remove one

@ttytm
Copy link

ttytm commented Nov 10, 2023

What should be the conventional commit type when I install or update a new package?

build or chore: is fitting

I am developing a mobile app. For example, which type should I use when I upgrade versionCode or versionName to release new version?

chore: fits here as well. E.g. https://github.com/clap-rs/clap/commits/master.

Which type should I use when I remove a feature I added?

depends on the reason why it is removed. Could be any of the prefixes.

@bloggerklik
Copy link

bloggerklik commented Nov 10, 2023

@qoomon @ttytm Thank you for your answers. The distinction between build and chore seems unclear and confusing. I'm searching for sources, but they are unclear and inconsistent. That's why I'm not considering using chore at all, as the Angular documentation says. What is your opinion?

@ttytm
Copy link

ttytm commented Nov 10, 2023

Since you already mentioned adapting the commit messages to your needs: I think it really depends on the project. The angular style prefixes fit well for the angular project and are fairly universal.

But e.g., at https://github.com/vlang/v/ we use module scoped prefixes. Which work better here than the Angular style prefixes to organize things.

So there is no need to take a narrow-minded view. Sometimes using no pre-fixes is also what is fitting and good enough https://github.com/webui-dev/go-webui/commits/main

Just keep things uniform.

@qoomon
Copy link
Author

qoomon commented Nov 11, 2023

@bloggerklik I use chore for everything that does not fit in any of the other conventional types

@bloggerklik
Copy link

@qoomon Last question😅 We need to use docs for comment lines, right? Thanks.

@qoomon
Copy link
Author

qoomon commented Nov 11, 2023

@wezzcoetzee
Copy link

Thank you so much this is awesome

@alisenola
Copy link

Awesome!

@monish-khatri
Copy link

Helpful 😄

@123atif
Copy link

123atif commented Feb 5, 2024

Helpful

@andre-alck
Copy link

Should the first commit of the project be considered as 'build'?

@qoomon
Copy link
Author

qoomon commented Feb 12, 2024

The first commit is tricky, I think build is probably the best choice, however I'd tend to always use just init as the very first commit. Ill add this recommendation to this gist.

@Borodkov
Copy link

can you help me with server side script?
on my home Gitlab @ ubuntu 20.04 LTS create pre-commit hook in repository but got error on push from client:
pre-receive: 32: Syntax error: "(" unexpected (expecting "then")

Next, when comment lines 32 and 37 (if condition)
if ! [[ "$commit_msg_header" =~.....
...
fi
got 3 echo of my commit hash, "ERROR: Invalid commit message format", commit msg body

how rewrite if condition in line 32?

@qoomon
Copy link
Author

qoomon commented Feb 16, 2024

@Borodkov my bad. You need to change the first line of the script from #!/usr/bin/env sh to #!/usr/bin/env bash

@Borodkov
Copy link

how simple!
thanks @qoomon for fast answer

helpful gist

@Borodkov
Copy link

Borodkov commented Feb 16, 2024

can you help with some modifications of regexp for gitlab isuues links patterns (#1, #2, .... #999)?

  • #1 feat: add cool feature

what wrong with this one?:
^(#\d{1,3} )(feat|fix|refactor|style|test|docs|build): .+$

@qoomon
Copy link
Author

qoomon commented Feb 17, 2024

@Borodkov you can not use \d in bash regex use [[:digit:]] instead
e.g. (^(#[[:digit:]]{1,3} )(feat|fix|refactor|style|test|docs|build): .+$)

@dannyk0104
Copy link

Nice posting!
I have a question. What whould you put for changes for framework configuration files?
For springboot application (not sure you are familiar with springboot tho),
it has a application.yaml file that keeps some configurations like below.

spring:
  application:
    name: my-app
  profiles:
    active: local
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: http://mydb.com...

If I make a change in this configuration file, what would you put for the type? refactor?(since it is part of source code..?)

@qoomon
Copy link
Author

qoomon commented May 30, 2024

@dannyk0104 it depends

  • it is probably not a feat or fix commit, because you don't change the api
  • I would probably go for refactor, because you made a change to a source code file (I count application config files as source code as well)

@JohnnyWalkerDigital
Copy link

Finally! A clear, simple and concise explanation of the Conventional Commits format! So much better than the documentation on the actual website!

@qoomon
Copy link
Author

qoomon commented Jun 1, 2024

@JohnnyWalkerDigital thanks a lot.

@sarvsav
Copy link

sarvsav commented Jul 2, 2024

Thank you for sharing this. It is super helpful. 🙏

@qoomon
Copy link
Author

qoomon commented Jul 2, 2024

@sarvsav glad you like it :-)

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