Hello, I’m Ludens, named after the island Studio mascot, Ludens.

preface

There have been a number of articles about Git in the nuggets series recently, so LET me write down some of the problems and solutions I’ve encountered.

I met a problem in the development before. After pulling the latest code from the warehouse, the local operation reported a syntax error, and some members pushed the wrong code, which triggered a thinking on the code submission process within the team. And finally decided to use Husky, the Husky, in the program.

So before we introduce the husky, first we need to know about Githooks.

Githooks

What is Githooks

The original description of Githooks is

Hooks are programs you can place in a Hooks directory to trigger actions at certain points in Git’s execution That don’t have the executable bit set are ignored.

Hooks are programs that you can place in the hook directory to trigger actions at some point in git execution. Hooks without an executable bit set are ignored. – Bing translation

Like Vue’s lifecycle hooks, Git lets users add and execute custom functions at certain points in its lifecycle.

Where are Githooks kept

Githooks is saved by default in the.git/hooks folder of your project, and when you open it you will see samples for many hooks

Let’s open up Simple and see what it looks like inside

As you can see, the Githooks file is actually a shell script that you can modify to implement custom functionality.

If Githooks are stored in the.git/hooks folder, how do you versioncontrol custom hooks? Git also provides a config for the Hooks folder. Core. hooksPath can be set to redirect the Hooks folder to your own directory.

What can Githooks solve

Back to the actual issues in the project

  • Problem: There is a syntax error in the remote repository code
  • Reason: some members did not check carefully and mistakenly uploaded the code with grammatical errors
  • Solution: InBefore you commitCheck the code in the staging area for syntax errors

If you only rely on the current member to check the code added to the staging area for errors, it is not reliable and ineffective. So we can use the hook of pre-commit, which can execute our custom statement before git commit. Prevent the COMMIT behavior if an error occurs or a non-zero state is returned.

Git operations, such as commit and push, provide hooks before or after an operation. If you are interested, you can check Githooks to understand.

Husky

Now that we know about Githooks, Husky is ready.

What is the Husky

In a nutshell, it makes creating or modifying Githooks easier.

So let’s take a look at how the source code is implemented

  • At initialization, the project is checked to see if it hosts code through Git
if (spawnSync('git', ['rev-parse']).status ! == 0) { l('not a Git repository, skipping hooks installation') return }Copy the code
  • Once the check passes, a.husky folder is created to hold the Githooks and Husky configurations
// create.husky/_ mkdirSync(join(dir, '_'), {recursive: WriteFileSync (join(dir, '.gitignore'), Sh copyFileSync(fileURLToPath(new URL('./husky.sh', import.meta.url))), join(dir, '_/husky.sh'), )Copy the code
  • Then pass core.hookspath to make the project’s Githooks path point to the newly created.husky folder, and the husky initialization process is roughly complete
    const { error } = spawnSync('git', ['config', 'core.hooksPath', dir])
    if (error) {
       throw error
    }
Copy the code
  • After initialization, create the file using the add command or add statements to the end of the file
    if (existsSync(file)) {
        appendFileSync(file, `${cmd}\n`)
        l(`updated ${file}`)
    } else {
        set(file, cmd)
    }
Copy the code

The editing function of the add command only supports adding statements to the end of a file. To modify the previous statements, you need to open the file

How to use Husky

To better demonstrate this functionality, let’s make a small Demo

  • We first initialize a small project with NPM, and then we installeslint,lint-stagedandhusky
    npm install --save-dev eslint lint-staged husky
Copy the code
  • After esLint is initialized, let’s initialize husky
    npx husky install
Copy the code
  • That’s when we see the.husky folder, addlintstagedrc.jsUsed to configure the corresponding lint for the staging file
 // .husky/lintstagedrc.js
    module.exports = {
      '*.js': ['eslint'],
    };

Copy the code
  • Create a pre-commit hook to check the files in the staging area
    npx husky add .husky/pre-commit "npx lint-staged -c .husky/lintstagedrc.js"
Copy the code
  • Add js to project with intentional syntax error
    const testA = {
    console.log(testA);
Copy the code
  • If an error is detected, an error message will be returned and the commit behavior will be prevented

  • After fixing the syntax errors, we can successfully pass the detection and commit, thus achieving our goal

Note that inWindowsOn, if it is throughGit BashTo do Git operations, the Githook statement containsYarnIn this case, you need to add common.sh to. Husky

// .husky/common.sh
    command_exists () {
      command -v "$1" >/dev/null 2>&1
    }
    # Workaround for Windows 10, Git Bash and Yarn
    if command_exists winpty && test -t 1; then
      exec < /dev/tty
    fi
Copy the code

Add it to the Hook file that uses Yarn

// .husky/(hook文件)
    #!/bin/sh
    . "$(dirname "$0")/_/husky.sh"
    . "$(dirname "$0")/common.sh"

    yarn ...
Copy the code

The difference between Yorkie and Husky

If you are familiar with the Vue CLI, you may know that the Vue CLI comes with Git Hook functionality. The Yorkie for this implementation is yyx Fork’s old version of Husky and modified, but the two are not very different in nature and greatly simplify the process of creating and adding new statements in Githooks.

Since Git added core.hookspath, a config that allows you to customize Githooks paths, Husky has changed.

  • The new version of Husky starts using this config to change the path of hooks to/huskyTo better manage the Githooks that belong to the project.
  • Older versions of Husky were maintained based on the Githooks field in package.json.git/hooksThe Hooks, equivalent to the project’s customization of Githooks, exist in two places.git/hooksandpackage.json, which may cause the two to be out of sync. The same is true for Yorkie.

So when core.hooksPath was added, Husky abandoned the.git/hooks approach.

The resources

  • GitHub-Husky
  • Husky
  • Githooks
  • Why husky has dropped conventional JS config

Afterword.

Through this experience, I have learned more about Git and also reflected my lack of engineering knowledge. I still need to learn more in this area. In the future, I can use Husky with a series of Lint tools (such as CommitLint and Stylelint) to better standardize the code submission process.

It is the first time to write and share technical experience of the article, there are shortcomings or mistakes, please forgive and put forward mistakes or valuable suggestions, but also very grateful to Po ge this article “wrote more than 200 articles, I summed up the writing experience”, when I write this article gave me a lot of help.