Git pre-hook: Setup pre-commit hook for NPM project example
Tags: git, npm, react, tutorial
Published: 2021-09-17 23:49:47

## Introduction 

There are various Git pre-hooks that are quite helpful for several essential tasks we want to execute before git commit or push or rebase etc. Basically, there are various use cases, like running linting before you commit the code or running unit tests before commit or push.

> Note: Whenever a Git repository is initialized, Git creates sample hooks inside `.git/hooks` directory under the project directory. E.g. `.git/hooks/pre-commit.sample`. Remember this is hidden directory.

## Getting Started 

Below are the steps on how to configure pre-commit Git pre-hook for an NPM project.

### 1. Create a pre-hook script

Let's create a `pre-commit` file inside a new `scripts` directory. Use case is to execute the unit tests before code commit.

> Note: The file name needs to be strictly as `pre-commit`, because we’re going to Git pre-hook mechanism.

```SHELL
#!/bin/sh

echo "*****Running unit tests******"

stash_commit="$(git stash create)"
git reset —-hard

npm test -- --watchAll=false

status=$?

if [[ -n "${stash_commit}" ]]
then git stash apply "${stash_commit}"
fi

exit $status
```
Above command stash the working directory changes before running the unit tests, and unstash back. This makes sure, we're running the tests only in the clean working directory. (as this is been configured for pre-commit, changes must have been staged, make sense?😀)

### 2. Create NPM script 

Next up, create an NPM script in the `package.json` file to install the `pre-commit script`. Why do we need it? because, we want this to run on all developers' machine, not just on our machine, we all love consistency and wants to put the constraint.

```JSON

"scripts": {
    "prestart": "cp scripts/pre-commit .git/hooks/ && chmod +x .git/hooks/pre-commit && echo 'hook copied'",
.
.
.
  }

```
> Here the `pre-commit` file is created inside project root directory i.e. `scripts`

The above NPM script first copy the already created `pre-commit` file under project’s Git hook directory and set the executable permission, finally just print the message. As we have configured it to run as a part of prestart script, it will run whenever someone starts the application and assuming that developer who is making changes will run the `npm start` at least once and I hope I'm right😉.

Once pre-commit script is copied to `.git/hooks/` directory, we're all set. We can verify its content as below:

```SHELL
cat .git/hooks/pre-commit
```

Now, next time whenever someone will run `git commit`, it will first run the `npm test -- --watchAll=false`.

E.g.
```SHELL
ak@--mac git-pre-commit-with-npm % git commit -am "update"

-- Output

*****Running unit tests******

> git-pre-commit-with-npm@0.1.0 test /users/ak/git-pre-commit-with-npm
> react-scripts test "--watchAll=false"

 PASS  src/App.test.js
  ✓ renders learn react link (29 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.964 s, estimated 1 s
Ran all test suites.
[main 0b432f0] update
 1 file changed, 4 insertions(+)
```
## Final Notes
- The way `npm test` is configured, in the same way, any other tasks can be executed. And of course for other tasks stash and unstash won't be compulsory.
- Similarly other pre-hooks can be configured. Here are a few more examples, [Pre-hooks Examples](https://dev.to/akdevcraft/git-pre-hooks-examples-1g3i).

## Sample Code

Here is the [GitHub repo](https://github.com/an1meshk/git-pre-commit-with-npm) with an example.

## My other Blogs:

- [Micro-frontend Decision Framework](https://dev.to/akdevcraft/micro-frontend-decision-framework-26hf)
- [How to Reduce Page Loading Time - Part 1](https://dev.to/akdevcraft/how-to-reduce-page-loading-time-part-1-2go1)
- [Barrel - Best Way to Import Files in Modern JavaScript Apps](https://dev.to/akdevcraft/barrel-best-way-to-import-files-in-modern-javascript-apps-3592)
- [Avoid Spring RestTemplate Default Implementation to Prevent Performance Impact](https://dev.to/akdevcraft/never-use-spring-resttemplate-default-implementation-2ghj)
- [How to use external font with web component](https://dev.to/akdevcraft/use-font-in-web-component-51a4)
- [Setup pre-hook for Gradle project](https://dev.to/akdevcraft/git-pre-hook-pre-commit-with-gradle-task-134m)
- [Team Agreement in Software Engineering](https://dev.to/akdevcraft/software-engineering-sample-team-agreement-2275)

_If you have reached here, then I did a satisfactory effort to keep you reading. Please be kind to leave any comments or ask for any corrections. **Happy Coding!**_