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
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:
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
pre-commit install -t commit-msg -t pre-commit -t pre-push - allow-missing-config
.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]
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" ] ] } };
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:
-
Install a detect-secrets tool (it is as easy as
pip install detect-secrets
). -
Run
detect-secrets scan > .secrets.baseline
in your project directory. - 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
- IntelliJ plugins that support conventional commit
- https://plugins.jetbrains.com/plugin/13389-conventional-commit
- https://plugins.jetbrains.com/plugin/13477-git-commit-message-helper
I also write on Medium. Please check my profile and other articles.
Very helpful. Thanks for sharing
ReplyDelete