Do you have a set of routines you do before you commit and publish code? These routines could be linting, formatting, testing and building the code. Imagine if there was a way to automate all of this for your whole team? The solution is to use Git hooks.
Working with Git Hooks
Git hooks enable us to hook into Git events and add code to be executed at events such as:
Git hooks are set up in the .git folder in a Git project. These are written as bash scripts. Unless you lack social skills and wear square glasses you wouldn’t like to write bash scripts (joke).
Husky enables you to specify Node scripts to execute on the different hooks. This can be used eg. to run npm scripts and will make it very easy to hook your Node scripts into the Git events.
Husky can be installed with:
npm i --save-dev husky
Or for YARN users:
yarn add husky -D
Husky can be configured in package.json with a property called husky and supports the Git hooks.
You can also create a .huskyrc file for the husky config (recommended).
From here you specify regular NPM scripts that will be executed on the specific Git events.
My recommended setup with Git hooks for Angular apps
After having used Git hooks for a while I have developed a couple of preferences for scripts I would like to run before I commit code. My husky config looks like this:
The commit message hook is triggered before pre-commit. It is used to evaluate the commit message using
commitlint configuration is:
When using this, make sure you install:
npm i -D commitlint
And config conventional:
npm i -D @commitlint/config-conventional
Pre-commit is used for linting and formating the code before it is committed. This ensures that you avoid seeing extra commits such as:
chore: fixed lint
Pre-commit hooks should be fast, as they are running on a developer’s machine that otherwise will be idle.
My recommended approach for fast pre-commit hooks is to do:
- Prettier formatting of all supported files
- TSLint linting of Typescript
- stylelint linting of css/scss files
All of this is triggered through the lint-staged command.
My recommended lint-staged configuration looks like this:
Lint-staged is applying the given commends for every staged file (appending them to each command) that matches the glob expressions.
Lint-staged is installed with:
npm i -D lint-staged
The first part, is formating Typescript files, JSON, markdown SCSS and HTML with
The second part is linting Typescript files with
TSLint and fixing errors.
The last part is linting and fixing style with
For my recommended Prettier and TSLint configuration check this post.
Git hooks vs. running scripts on the CI
You might be wondering, what should run as Git hooks vs. on the CI. I have a clear take on this:
If it is related to the styling and formating on the code, use Git commit hooks. Otherwise let the CI handle it (test, build, SonarCube etc.)
You might be wondering, what about the post-commit hooks? My recommendation is to (normally) let the CI handle that, eg. e2e tests, tests and build, if you are not short on CI resources.
Git hooks should always be fast and they make the Git versioning cleaner by cleaning up before the commits are happening and are building automatic enforcement of good code practices into the workflow.
In this post, we saw how Git hooks can ease the development process as you are automatically running trivial commit-msg and pre-commit scripts. Also, I gave a recommendation of how to set up Git hooks for Angular apps that I have found very beneficial myself.
Thanks for reading. Remember to follow me on Twitter and leave a comment.
I’m Christian, a freelance software developer helping people with Angular development. If you like my posts, make sure to follow me on Twitter.
Also published on Medium.