Code Commit Guidelines using Conventional Commits

Let’s explore pre-commit a more structured way to commit history and how to make it easier for people to contribute to your projects

code commit guidelines android
Photo by Yancy Min on Unsplash


In order to keep commits aligned across all repositories, we should use the conventional commits specification.

The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools for example Github Actions on top of it. 

Conventional Commit makes it easier for people to contribute to your projects, by allowing them to explore a more structured commit history. 

Commit

Each code commit should have some basic details about the commit and the ticket description. It will be easier to track the ticket from commit. It will be easier for team members to understand and follow the pattern if each team member is following the same way. 

Pull Request 

Each PR should contain ticket details and the title of the PR. It should also contain the type of ticket so team members can check if it was a feature/enhancement or bug fix. 

In general, the commit message should be structured as the following pattern:
<type>[optional scope]: [REFERENCE-1234]
<description>
[optional body]
[optional footer(s)]


Real-world examples can look like this:

chore: [PRJ1-123] run tests on jenkins ci
fix(server): [PRJ2-1234] send cors headers
send CORS headers by reflecting the origin header in the request
feat(blog): [PRJ2-1234] add comment section


Examples

Commit message with scope, description, and breaking change footer:

// without scope
feat: allow provided config object to extend other configs

BREAKING CHANGE: `extends` key in config file is now used for extending other config files

// with scope
feat(lang): add Polish language


Commit message with multi-paragraph body and multiple footers:

fix: prevent racing of requests

Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.

Remove timeouts which were used to mitigate the racing issue but are
obsolete now.

Reviewed-by: Z
Refs: #123


One recommendation is to use the revert type and a footer that references the commit SHAs that are being reverted:

revert: let us never again speak of the noodle incident

Refs: 676104e, a215868


Commit Types

Use the following as a guideline as to what types you could use for your commits.

Type Category Release Explanation
BREAKING Major
feat Features Minor A new feature
fix Bug Fixes Patch A bug fix
docs Documentation Patch Documentation only changes
style Styles Patch Changes that do not affect the meaning of the code (whitespace, formatting, missing semi-colons, etc.)
refactor Code Refactoring Patch A code change that neither fixes a bug nor adds a feature
perf Performance Improvements Patch A code change that improves performance
test Tests Patch Adding missing tests or correcting existing tests
build Builds Patch Changes that affect the build system or external dependencies (example scopes: npm, make, etc.)
ci Continuous Integrations Patch Changes to our CI configuration files and scripts (example scopes: BitBucket, CircleCI)
chore Chores Patch Other changes that don't modify source or test files
revert Reverts Patch Revert a previous commit


Real-world examples can look like this:

Code Commit Format Sample Android


How to setup up pre-commit for your project

To get commit linting going follow the below steps.

1. Install the pre-commit package using Brew:
    brew install pre-commit
    
    //check version after installatio complete 
    pre-commit --version

    2. Run the following command in your project directory:
      pre-commit install -t commit-msg -t pre-commit -t pre-push - allow-missing-config
      

      3. Add pre-commit plugins to your project. Create the config file .pre-commit-config.yaml in your project directory:
        default_stages: [commit, push]
        repos:
          - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
            rev: v2.1.0
            hooks:
              - id: commitlint
                stages: [commit-msg]
                additional_dependencies:
                  - "@commitlint/config-conventional"
                  - conventional-changelog-conventionalcommits
        
          - repo: https://github.com/pre-commit/pre-commit-hooks
            rev: v2.4.0
            hooks:
              - id: check-json
              - id: check-merge-conflict
              - id: detect-private-key
              - id: no-commit-to-branch
        
          - repo: https://github.com/jguttman94/pre-commit-gradle
            rev: v0.3.0
            hooks:
              - id: gradle-spotless
                args: ['-w', --wrapper]
        

        4. Add lint to your project. Create the config file commitlint.config.js in your project directory:
          module.exports = {
              extends: ["@commitlint/config-conventional"],
              // Validate for issue/ticket numbers
              parserPreset: {
                  parserOpts: {
                      // these are samples, add possible prefixes based on your project requirement
                      issuePrefixes: ['ANDR-', 'TEST-','DSC-', 'ABC-', 'CO-'] 
                  }
              },
              rules: {
                  "body-leading-blank": [ 1, "always" ],
                  "footer-leading-blank": [ 1, "always" ],
                  "header-max-length": [ 2, "always", 72 ],
                  "scope-case": [ 2, "always", "lower-case" ],
                  "subject-case": [
                      2,
                      "never",
                      [ "sentence-case", "start-case", "pascal-case", "upper-case" ]
                  ],
                  "subject-empty": [ 2, "never" ],
                  "subject-full-stop": [ 2, "never", "." ],
                  "type-case": [ 2, "always", "lower-case" ],
                  "type-empty": [ 2, "never" ],
                  "type-enum": [
                      2,
                      "always",
                      [
                          "build",
                          "chore",
                          "ci",
                          "docs",
                          "feat",
                          "feature",
                          "fix",
                          "perf",
                          "refactor",
                          "revert",
                          "style",
                          "test"
                      ]
                  ]
              }
          };
          

          5. Commit the added files to your repository

            The output should look like this:

            > git commit -m 'fix: [TOL-6911] test lint'
            [INFO] Initializing environment for https://github.com/alessandrojcm
            /commitlint-pre-commit-hook:@commitlint/config-conventional,
            conventional-changelog-conventionalcommits.
            Fix End of
            Files.........................................................Passed
            Check JSON...........................................(no files to check)
            Skipped
            Check for merge
            conflicts................................................Passed
            Detect Private
            Key.......................................................Passed
            Don't commit to
            branch...................................................Passed
            [INFO] Installing environment for https://github.com/alessandrojcm
            /commitlint-pre-commit-hook.
            [INFO] Once installed this environment will be reused.
            [INFO] This may take a few minutes...
            commitlint..............................................................
            .Passed
            - hook id: commitlint
            - duration: 0.43s
            [branchify-devops-changes fde84e2] fix: [TOL-6911] test lint
             1 file changed, 3 insertions(+), 3 deletions(-)
            

            Done, you now have a commit message linting in place.


            Moreover, since we have a detection of unexpected secrets, you would need to set up the first baseline:

            1. Install a detect-secrets tool (it is as easy as pip install detect-secrets).
            2. Run detect-secrets scan > .secrets.baseline in your project directory.
            3. Commit the added files to your repository.

            Done, you now have a baseline for detecting unexpected changes related to secrets.

            Try the following command to validate:
            git commit --allow-empty -m ""
            

            Let’s take a step to move to clean commit, Just the way we are moving to clean code ;)


            Resources


            I also write on Medium. Please check my profile and other articles.

            Code Commit Guidelines using Conventional Commits | by Pragnesh Ghoda | Medium


            Thanks for reading this article. Hope you would have liked it!. Please share and subscribe to my blog to support.

            Pragnesh Ghoda

            A forward-thinking developer offering more than 8 years of experience building, integrating, and supporting android applications for mobile and tablet devices on the Android platform. Talks about #kotlin and #android

            1 Comments

            Please let us know about any concerns or query.

            Previous Post Next Post

            Contact Form