DEV Community

Tanishq Singla
Tanishq Singla

Posted on

Write your own pre-commit hooks

Overview

If you've never written a git hooks don't worry. Writing git hooks is far more easier than you think it is. In this blog I'll be sharing a basic idea how pre-commit hooks are made by creating a simple pre-commit hook that runs a formatting and linting check on our project.

Creating the project

The example in this blog is a simple hello world application using node.js and express but you don't have to learn anything about them as the main focus is to run the scripts and not to create a web-server.
You can find the project in this repo - pre-commit-example.

Project overview

The project contains our hello world application and the logic for it is defined in server.js and then there are some config files for eslint and prettier.

server.js

const express = require('express')

const app = express()

app.get("/", (_, res) => {
  res.send("Hello world");
})

app.listen(3000, () => console.log("server is running on http://127.0.0.1:3000"))
Enter fullscreen mode Exit fullscreen mode

eslint and prettier
As for eslint and prettier, I am using prettier plugins with eslint, you can find more details for it in this blog - You might not need a separate config for eslint and prettier

{ "env": { "commonjs": true,
    "es2021": true,
    "node": true
  },
  "extends": ["eslint:recommended", "plugin:prettier/recommended"],
  "plugins": ["prettier"],
  "parserOptions": {
    "ecmaVersion": "latest"
  },
  "rules": {
    "prettier/prettier": [
      "error",
      {
        "semi": true,
        "useTab": true
      }

    ],
    "indent": ["error", "tab"],
    "semi": ["error", "always"],
    "quotes": ["error", "double"]
  }
}
Enter fullscreen mode Exit fullscreen mode

If you take a look at our config and server.js file, you will realize that when we will run our linter it is going throw errors.

scripts
I've added scripts to run our eslint in the package.json file

"scripts": {
  "lint": "eslint .",
  "lint:fix": " eslint --fix ."
}
Enter fullscreen mode Exit fullscreen mode

Writing our pre-commit

Let's write our pre-commit hook. The general idea of writing our pre-commit hook (in this case) is to avoid code with linting errors to get commited, this will streamline our development cycle as developers often forget small things in the code which might get alarmed in our lint stage.

To write a pre-commit hook all we need to do is a create a bash script file named pre-commit in the hooks folder under .git folder.

#!/bin/sh

npm run lint

SUCCESS=$?

[ $SUCCESS -ne 0 ] && exit 1
exit 0
Enter fullscreen mode Exit fullscreen mode

That's it! Yes, this is our pre commit hook that checks if our code is formatted or not. Let's look at what we're doing here.

npm run lint
This is the command we defined in our package.json, this commands run the eslint command and displays the error.

SUCCESS=$?
Here we're assigning a variable named SUCCESS and assigning it to the status code of the last command that ran i.e npm run lint. Commands that run successfully return 0 as their value and those who don't returns a non-zero value.

[ $SUCCESS -ne 0] && exit 1
This is our conditional statement that checks if the SUCCESS value is not 0, if it is not 0 then it exits with code 1 which is a non-zero value implying our program exited with an error.

exit 0
If our conditional statement returned false, we exit the program with 0 meaning success.

One last step

Now that we've created our script we need to make it an executable so that the git can execute this file before we hit commit. To do that we provide the file with execute access. Run this command in your terminal to do that

chmod +x .git/hooks/pre-commit
Enter fullscreen mode Exit fullscreen mode

Now when you'll try to commit the changes it won't let you do that, as we have linting errors in our code.

Limitations of this approach

As simple as this approach looks there is one limitation with this approach, the hooks are not versioned by git and hence not stored in the repo.
There are work arounds to this mentioned in this stackoverflow post. But this relies on Git v2.9 or older.
You can also create a simple script that copies the contents of your git hooks.

Other solutions

You can follow Git Hooks docs, this doc contains some amazing project that can supercharge your development cycle with git hooks.
You can also use pre-commit a very famous package for setup like this. You can refer this tweet of mine.

Top comments (1)

Collapse
 
tuanxt profile image
tuanxt • Edited

Thank you, i will save your post and reading affter