1. Introduction

When committing information in Git Commit is properly written, it can improve readability and project maintenance efficiency. This article introduces the message specification and the submission detection tool.

2. Reference: Angular Team Commit Specification

Detailed submission information can let people know which aspects of the original project will be modified by this submission. Whether it’s fixing bugs, adding components or modules, modifying code styles, or refactoring. Message also tells you which part of the document or module to change.

But what is the best way to write this message? Refer to the Angular team’s Git-commit guidelines. Here is the team’s specification format for Message:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
Copy the code

Each submission contains a header, body, and footer. The header includes type, Scope, and Subject.

If the current commit is a rollback of the previous commit, the header must start with revert: and the body must specify: This reverts commit. hash refers to the SHA value generated by Git after each commit. The SHA value for each commit can be viewed from the Git log:

1.header

In the header, type and Subject are required and scope is optional. The three parts of the head are described in detail below:

(1) type

A mandatory field that specifies the type of modification to be made in this submission. It must be any of the following:

  • Feat: A new feature
  • It’s A bug fix.
  • Docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) Usually style changes, such as whitespace, formatting, semicolons, etc.)
  • Refactor: A code change that neither fixes A bug nor adds A feature
  • Perf: A code Change that Improves Performance
  • Test: Adding missing or correcting existing tests
  • chore: Changes to the build process or auxiliary tools and libraries such as documentation generation

(2) the scope

An optional field that indicates the location of the change in this commit. Usually in project name/module name format. If there are more than one change in a commit, you can officially use * to default. Personally, however, I prefer to make a single change per submission, which makes reading the submission information more detailed.

(3) the subject

A mandatory field that briefly describes the changes made in this commit. And it needs to meet the format:

  • If described in English, English words can only be in the present simple or imperative
  • The first letter cannot be capitalized
  • Not to.As the end

2.body

Optional, the body is used to describe the changes made in this submission in more detail than the subject mentioned above. This needs to include the motivation for this change and the improvements compared to the previous change.

3.footer

Optional items mainly include:

  • break changes: Any breaking changes that are incompatible with the previous version, such as version upgrades, data field changes, interface parameter changes, etc. If breaking change exists, it is necessary toBREAKING CHANGE:Write clear changes after the beginning is followed by a space or two new lines.
  • Affect Issues: Indicates whether the modification is for certain issues.

3. Submit the information preformatting tool

(1) commitizen

An officially recommended tool for writing qualified commit information in place of the Git commit directive. For details, see Commitizen. I have not used this tool because VSCode commits with buttons. If you use Commitizen in your project, you will need to use git cz instead of Git commit. It will change the whole operation process, and it will not be able to promote in the team.

(2) Commit Message Editor

Here I choose a tool in VSCode to generate formatted submission information Commit Message Editor, the operation can be seen in the following figure:

(1) Common operation

(2) When submitting information in Angular format

4. Submit the information check tool

1. Install

npm install -D @commitlint/config-conventional @commitlint/cli husky

Husky: a Git hooks tool.

Commitlint: a tool that detects the commit message format

2. The configuration

(1). Huskyrc

First configure the husky aspect by creating a new file named.huskyrc (or.huskyrc.json) in the root directory and writing the following:

//.huskyrc
{
  "hooks": {
    "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
  }
}
Copy the code

Commitlint -e HUSKY_GIT_PARAMS is executed before git performs commit and merge. Commitlint detects the commit information.

** Git hooks have many periodic functions, see githooks for more. Some people ask why not use “pre-commit” and “pre-commit- MSG “.

We can check out the explanation of “pre-commit” in the githooks website just attached:

This hook is invoked by git-commit[1], and can be bypassed with the –no-verify option. It takes no parameters, and is invoked before obtaining the proposed commit log message and making a commit. Exiting with a non-zero status from this script causes the git commit command to abort before creating a commit.

“Pre-commit” is triggered before the commit log message has been obtained. Therefore, the submission information cannot be detected.

Look at the following explanation of “pre-commit-msg” :

This hook is invoked by git-commit[1] right after preparing the default log message, and before the editor is started.

Compare the following interpretation of “commit-msg” :

This hook is invoked by git-commit[1] and git-merge[1], and can be bypassed with the --no-verifyoption. It takes a single parameter, the name of the file that holds the proposed commit log message. Exiting with a non-zero status causes the command to abort.

“Pre-commit” and “pre-commit- MSG “are both triggered by git commit and git merge. So we choose the “commit- MSG “periodic function.

(2) commitlint. Config. Js

Next, configure the commitLint parameters and write the following:

//commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'scope-case': [0]
  }
}
Copy the code

[Root@commitlint/config-Conventional] [root@commitlint/config-Conventional] [root@commitlint/config-Conventional]

There are many types of detection rules. The most commonly used one is Conventional Commits. This rule is derived from the Angular Team Commit Specification described above. Commitlint More rules: Shared Configuration.

** Extension: ** There are two similar rules in the above url rules:

  • @commitlint/config-angular
  • @commitlint/config-conventional

‘@commitlint/config-angular’ satisfies almost all of the header, body, and footer rules described in point 2 of this article. Then I added the rule that type and scope in the header must be lowercase.

While ‘@commitlint/config-angular’ inherits all rules from ‘@commitlint/config-angular’, there are some minor constraints, such as:

  • Header Contains a maximum of 100 characters
  • Each line of body and footer has a maximum length of 100 characters. Note that this is per line.

After adding the above two configurations, git will check the rules before committing each time. If the rules are not met, git will break. For example:

The information I submitted is ci(.huskyrc): test, because the scope has capital letters, so the submission is closed.

5. The preparation of the rules

As with esLint rules, rules defined in Rules have the highest priority. When some of the detection rules in @commitLint/config-Conventional do not apply to your project, you can rewrite them using rules. As follows:

"rules": {
  "header-max-length": [0, "always", 72],
}
Copy the code

Each rule defined in rules consists of the name header-max-length and the configuration array [0, “always”, 72].

There are three elements in the configuration array, which are:

  • Level: one of the values of 0,1,2. 0 means to invalidate this rule; 1 indicates warning, does not affect the compilation run; 2 indicates an error message that prevents the compilation from running. The above example indicates that this rule does not work.
  • Applicable: in order toalwaysandneverOne of the values.neverIt stands for reverse rule, which equals! Invert.
  • Value: Specifies the value applicable to the rule. The above example representsheaderThe maximum number of words can only be 72.

For my own project, because SCOPE is used to write the modified folder name, there will be a case of uppercase, so I use rules to modify here as follows:

rules: {
    'scope-case': [0]
}
Copy the code

No longer validates scope’s case rule. If I submit again as ci(.huskyrc): test, no error will be reported.

6. Extension: Add type

For a real development scenario, the Types defined in the Angular Team Commit Specification may not satisfy the types of changes that the developer is dealing with. As with my own project development, some changes are made to adjust component CSS styles due to UI changes. Therefore, the team negotiated and added a type called UI type.

The changes are as follows:

//commitlint.config.js module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'scope-case': [0], 'type-enum': [ 2, 'always', [ 'build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test', 'UI' // New type for CSS changes]]}}Copy the code

Add a test for type-enum in rules, and add UI as the new type in the third parameter value list in addition to the original type.

For VSCode’s plug-in Commit Message Editor, add the following paragraph in setting.json:

"commit-message-editor.tokens": [
        {
            "label": "Type",
            "name": "type",
            "type": "enum",
            "options": [
                {
                    "label": "---",
                    "value": ""
                },
                {
                    "label": "build",
                    "description": "Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)"
                },
                {
                    "label": "chore",
                    "description": "Updating grunt tasks etc; no production code change"
                },
                {
                    "label": "ci",
                    "description": "Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)"
                },
                {
                    "label": "docs",
                    "description": "Documentation only changes"
                },
                {
                    "label": "feat",
                    "description": "A new feature"
                },
                {
                    "label": "fix",
                    "description": "A bug fix"
                },
                {
                    "label": "perf",
                    "description": "A code change that improves performance"
                },
                {
                    "label": "refactor",
                    "description": "A code change that neither fixes a bug nor adds a feature"
                },
                {
                    "label": "revert"
                },
                {
                    "label": "style",
                    "description": "Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)"
                },
                {
                    "label": "test",
                    "description": "Adding missing tests or correcting existing tests"
                },
                {
                    "label": "ui",
                    "description": "Modify css"
                }
            ],
            "description": "Type of changes"
        },
        {
            "label": "Scope",
            "name": "scope",
            "description": "A scope may be provided to a commit’s type, to provide additional contextual information and is contained within parenthesis, e.g., <code>feat(parser): add ability to parse arrays</code>.",
            "type": "text",
            "multiline": false,
            "prefix": "(",
            "suffix": ")"
        },
        {
            "label": "Short description",
            "name": "description",
            "description": "Short description in the subject line.",
            "type": "text",
            "multiline": false
        },
        {
            "label": "Body",
            "name": "body",
            "description": "Optional body",
            "type": "text",
            "multiline": true
        },
        {
            "label": "Breaking change",
            "name": "breaking_change",
            "type": "boolean",
            "value": "BREAKING CHANGE: ",
            "default": false
        },
        {
            "label": "Footer",
            "name": "footer",
            "description": "Optional footer",
            "type": "text",
            "multiline": true
        }
    ]
Copy the code

This is the code in the red box:

At this point, use the Commit Message Editor to select a type named UI, as shown below: