Git hooks in 5 min


Working together as a team and maintaining a clean codebase is becoming increasingly important. Therefore most companies create and use certain rulesets which have to be followed by everyone in the team.

To avoid unnecessary code review time spent to check simple rules we have agreed on, we can leave the work to detect issues and even fix them to software.

It is no surprise that tools like eslint for linting and prettier for formatting are at a weekly download count of whacking 45 million downloads per week (numbers at the time of writing this post, taken from npmjs-prettier and npmjs-eslint).

the problem

While many people (yup, me as well) include them in their IDE, there are also people that don't. One way to ensure a formatted and linted code is to tell them to make sure that they run something like

./node_modules/bin/prettier --write .

for formatting and

./node_modules/.bin/eslint . -c .eslintrc.js --ext .js,.ts,.vue

for linting.

Since we are all humans and make countless mistakes each day, people could forget this before pushing their code. Which would end up in unnecessary bad code or wasted developer time in the code reviews...

Git hooks to the rescue

To fix this issue, we use git hooks (which are just simple shell scripts) which will run these commands/tools on certain git actions (commit/push/pre-push/etc..).

NOTE: You can run anything you want inside your git hooks. This is in no way limited to some javascript or typescript tooling. And also not to linting and formatting. These are just practical, typical use cases.

We will set up our git repo with hooks now. Our goal is to:

  • Run prettier before every commit
  • Run eslint before every push.
  • Stop the current action when we receive an error inside our hooks.
  • To determine when the git hook will be run, it simply has to be named like the git action.
  • Want to run something before a commit? Create the shellscript pre-commit.
  • Before a push..? Exactly, pre-push.

NOTE: In the following code $? is used to determine the return code of the last executed command. For us this will be prettier and eslint respectively.

pre-commit File 'pre-commit'. Runs prettier before the commit will be executed.

These have to be stored inside the .git/hooks directory in your project root. After doing this your hooks folder should look like this:

git hooks folder How the git hooks folder looks after creating both files. The X.sample are example files for hooks. To enable them remote the postfix '.sample'.

Lets imagine we did create this piece of code:

initial code with linting and formatting errors This code contains linting and formatting errors.

And then we want to include it into our code base. We run

git add .

then try commiting with

git commit -m "create awesome index.js file"

git commit hook in action State of the file after comitting. We see that it was automaticly formatted for us.

So far so good. We auto formatted the code by simply commiting it. Lets try to push the existing code into our remote repository.

git push

git pre push hook error Push was stopped because eslint did find errors in our codebase.

Lets fix these errors, create a new commit and try pushing again. This is our resulting file now:

final result

Okay. Time to push the code.

git push

git push successfull Yaaay, the code got accepted. Eslint did not find any errors and the push was successful!

And thats it, I hope you enjoyed this post. I always suggest to just jump in and try around with this by yourself! Have fun!

Want to read more?
Automerge Zustand React Native Drama
The tragedy of using react native async-storage with automerge and zustand
Built with ๐Ÿงก using RNW and Nextjs