Skillfully using gitHooks to check the code before submission

Posted by redtux on Thu, 09 Dec 2021 18:19:19 +0100

Thanks for bigAken's contribution

Every repository that uses git for version management has a directory git/hooks, including scripts of Hooks in each stage of commit. These Hooks can perform pre or post operations when git operates commit, push, merge, etc. for example, pre commit can perform code verification before git commit. ESLint is used to verify the code, and prettier is used for formatting. The common Hooks supported by git are shown in the following table. For more information, please check the official website Hooks:

Git Hook

Call timing

Call timing

pre-commit

Before git commit execution

You can bypass it with git commit -- no verify

commit-msg

Before git commit execution

You can bypass it with git commit -- no verify

pre-merge-commit

Before git merge execution

You can bypass it with git merge -- no verify

pre-push

Before git push execution

This article first practices how to write the git hooks of pre commit, and then introduces the use of husky, lint staged and commitlint

In the GIT project There are many hooks examples under git/hooks, as follows

These git hooks are At the end of sample, if you want to enable a hooks, you can remove it End of sample

practice

npm init -y initializes a project, then git init, and then NPM install eslint -- save dev

newly build. gitignore file

node_modules

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

*-lock.json
*.lock

newly build. eslintrc, configure eslint

{
 "rules": {
  // Semicolons are required
  "semi": ["error", "always"],
  // Force consistent backticks, double quotes, or single quotes
  "quotes": ["error", "double"]
 }
}

Create a new src directory, and then create an index JS, do not use shortcut keys to format

console.log('object')

Create a new folder from the root directory customGitHooks then git config 'core hooksPath' . customGitHooks is mainly used to set the storage directory of gitHooks, because the default storage directory of gitHooks is git/hooks, create a new pre commit, and write as follows

#!/bin/sh

echo 'start check your code,please wait...'
# git diff gets the changed content. You can configure the condition through the parameter -- diff filter
npx eslint $(git diff --cached --name-only --diff-filter=ACM -- '*.js')
# Variable $? --- > Execution status result of the previous command
if [ $? != '0' ];then
  echo "ending and failed,please check your code;"
 exit 1
else
  echo "check pass"
fi

At this time, execute git add, git commit -m 'test' will find no successful commit and report an error, as shown in the following figure

If you put index JS code is modified as follows:

console.log('object')

Execute git add, git commit -m 'test' will find that the eslint code has passed the check and can be submitted normally. The above practice can well explain how to check the code before commit, but there is a disadvantage that others pull your code to execute git config 'core hooksPath' . Customgithooks works; The following describes the use of husky, lint staged, and committed lint

. git folders are not tracked and uploaded to the remote warehouse

Husky

github in order to solve the problem git configuration cannot submit to the remote warehouse. Husky comes out. After you install npm i, husky only needs to automatically execute husky install

Install npm install husky -D

npm install husky -D

use

Edit Package JSON adds the value of prepare in the script as husky install

  "scripts": {
    "prepare":"husky install"
  },

Then execute npm run prepare. What did you do

Source code index TS, we see that executing husky install is actually creating Husky directory, copy/ husky.sh file to this directory, and one is configured gitignore, set the core Hookspath (set the. Husky directory to git hooks directory)

Add a hook

Yes Create pre commit under husky directory

#!/bin/sh

echo 'start check your code,please wait...'
# git diff gets the changed content. You can configure the condition through the parameter -- diff filter
npx eslint $(git diff --cached --name-only --diff-filter=ACM -- '*.js')
# Variable $? --- > Execution status result of the previous command
if [ $? != '0' ];then
  echo "ending and failed,please check your code;"
 exit 1
else
  echo "check pass"
fi

index.js file contents are as follows

console.log('object')

Then execute git add, git commit -m 'test' found that the code has been intercepted and not submitted because of index JS code does not conform to the specification

The remaining problem is what to do if git hooks can't be written. Here's lint staged

lint-staged

Function of configuration example: bash command operation on Git temporary storage code file, etc

npm i lint-staged -D

Create a new directory under the root directory lintstagedrc file

{
  "*.js": "eslint"
}

Modify the pre commit under husky directory as follows

. "$(dirname "$0")/_/husky.sh"
npm run lint

package.json add script

"scripts": {
  "lint": "lint-staged"
}

index.js is as follows

console.log('object')
console.log('object')

Execute git add, git commit -m 'test', it can be found that eslint is called to check the code. If the check fails, exit the commit

To sum up, the code detection specification has been, and now the submission specification also needs to be standardized;

commitlint

github

Verify the information submitted by commit

npm install --save-dev @commitlint/config-conventional @commitlint/cli

Use new commitlint config. js

module.exports = {
 extends: ['@commitlint/config-conventional'],
 rules: {
  'type-enum': [2, 'always', ['build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'style', 'test', 'revert', 'chore']],
  'type-case': [0],
  'type-empty': [0],
  'scope-empty': [0],
  'scope-case': [0],
  'subject-full-stop': [0, 'never'],
  'subject-case': [0, 'never'],
  'header-max-length': [0, 'always', 72]
 }
}

Configure git hooks and execute the following command

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'

The commit message is generally divided into three parts: Header, Body and Footer

header
<type>(<scope>): <subject>
// One blank line
<body>
// One blank line
<footer>
Among them, Header Is required, Body and Footer Can be omitted

The next commit must conform to the following format

Notice the space after the colon

git commit -m <type>[optional scope]: <description>

Common type categories

  • build: the main purpose is to modify the submission of the project construction system (such as glup, webpack, rollup configuration, etc.)
  • ci: the main purpose is to modify the submission of project continuous integration process (such as Travis, Jenkins, gitlab, ci, Circle, etc.)
  • docs: document update
  • feat: what's new
  • Fix: bug fix
  • perf: Performance Optimization
  • Refactor: refactor code (no new features, no bug fixes)
  • style: code modification that does not affect program logic (modify white space characters, complete missing semicolons, etc.)
  • Test: add test cases or update existing tests
  • revert: rolls back an earlier commit
  • chore: other types (daily affairs) that do not belong to the above types

optional scope: an optional modification scope. It is used to identify which module in the code is mainly involved in this submission.

description: describe the main contents of this submission in one sentence, so as to be concise and comprehensive.

At this point, perform a test

git add .
git commit -m 'test'

Because the commit submitted is nonstandard, the failure during submission is shown in the following figure

If you modify the commit, it will be submitted successfully because it complies with the commit specification

git add .
git commit -m 'feat: test'

But the problem comes again. You have to enter it every time you commit, which is a little inconvenient; And it may be wrong. Let's introduce commitizen

commitizen

cz-commitlint

Generate a qualified commit message

There is no global installation for the local installation. Of course, you can use the global installation. For the global installation, you can use git, CZ, CZ commitlint to get through the commitizen and commitlint configurations

npm install --save-dev @commitlint/cz-commitlint commitizen

then

npx commitizen init cz-conventional-changelog --save-dev --save-exact

package.json add script

{
 "scripts": {
  "commit": "git-cz"
 },
 "config": {
  "commitizen": {
   "path": "@commitlint/cz-commitlint"
  }
 }
}

Create a new commitlint config. js

module.exports = {
 extends: ['@commitlint/config-conventional']
}

Then execute

git add .
npm run commit

If it is found in Chinese, the prompt is shown in the figure below

Modify commitlint. Again config. js

module.exports = {
 extends: ['@commitlint/config-conventional'],
 prompt: {
  questions: {
   type: {
    description: 'Select the type you want to submit:',
    enum: {
     feat: {
      description: 'new function',
      title: 'Features',
      emoji: '✨'
     },
     fix: {
      description: 'Repair related bug',
      title: 'Bug Fixes',
      emoji: '🐛'
     },
     docs: {
      description: 'Document changes',
      title: 'Documentation',
      emoji: '📚'
     }
    }
   }
  }
 }
}

Then execute

git add .
npm run commit

You can see that it has become Chinese. Please refer to the official website for details

Next, submit the information and execute npm run commit to submit according to the specification; If you do not use commit lint, you can also customize many configurations by using CZ customizable in commit