When we’re working on a collaborative team, from time to time a developer has to add a new package to a branch which is then merged into master. Someone might be unaware of it and just pull master and run the app only to have it crash due to the missing package. Let’s see how we can use Git hooks to detect changes to a package.json
or a yarn.lock
and display a message prompting the user to install the missing dependencies.
- What are Git hooks?
- Running Git hooks with Husky
- Adding a post merge Git hook to check lock file changes
- Testing the lock file change check
- Detecting a lock file change in VS Code
What are Git hooks?
Git hooks are fired when some Git event occurs such as a new commit, pushing commits to an online branch, pull commits, checkout a branch or merge a branch. These processes end with 0 when they end correctly or some other value when they end incorrectly.
If the process hooked ends with 0, the Git action proceeds. Otherwise, the Git action is blocked. For example, if you configure a pre-commit Git hook to lint your code, Git will run this when you do a git commit
. If the lint fails, the commit won’t go through.
Git hooks are something integrated into Git and the list of hooks is very extensive. For example, you have pre-push, post-commit, post-checkout, post-merge, and many other Git hooks.
Run Git hooks with Husky
To run some tasks when the Git hooks are fired we can use the Husky package for Node.js. Husky allows us to specify in a package.json
file which scripts to run when a Git hooks is fired. Install the Husky package with NPM:
npm i -D husky
or Yarn:
yarn add -D husky
Now you need to initialize Husky for Git hooks. If you use NPM:
npx husky install
and if you use Yarn
yarn husky install
and that’s it, you’ve now installed and configured Husky to run Git hooks. It’s finally time to define a hook!
Add a post merge Git hook to check lock file changes
We want to run some code to alert us if the package-lock.json
or yarn.lock
files have changed. This happens usually when we pull master
and these files have changed. We can setup a hook to run when we merge a branch.
To specify our Git hooks to Husky we define them in the package.json
file. Add this as a top level key:
"husky": {
"hooks": {
"post-merge": "./githooks/post-merge-hook.sh"
}
}
What this says, is that after a branch is merged, we’ll run this script. We now have to create it. Create a folder, add a file to it and set it to be executable:
mkdir githooks && cd githooks && touch post-merge-hook.sh && chmod +x post-merge-hook.sh
If you don’t set it to be executable, you’ll run into an error “Permission denied” when Husky attempts to run this Git hook. Now edit the file with Vim or your favorite editor and paste this in it:
#!/bin/sh
changedFiles="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
runOnChange() {
echo "$changedFiles" | grep -q "$1" && echo -e "$2"
}
runOnChange package-lock.json "\033[35m*******************************************************************************\n* \033[33mpackage-lock.json\033[35m has changed. Run\033[33m npm install\033[35m to update your dependencies. *\n*******************************************************************************"
exit 0
This will print a message in purple with the words package-lock.json
and npm install
in orange. This scripts checks if package-lock.json
was updated and if you want to test for yarn.lock
instead you’ll simply have to replace the file name.
Test the lock file change check
Testing this is not too complex. You basically just need to create a new branch, install some package so the package-lock.json
is modified, commit it, and switch to the previous branch. All that can be done with this command:
git checkout -b testbranch && npm i -D lint-staged && git add . && git commit -m "test" && git checkout -
Now you need to merge it onto this branch
git merge testbranch
This will trigger the post-merge hook and will run our script. You’ll then see this message in the command line because the package-lock.json
has been modified during the merge:
Detecting a lock file change in VS Code
This was only one use. Git hooks can be used in many ways, for example, to run the popular package Prettier before you commit something to format your code.
There are alternatives for this particular cas, of checking whether package-lock.json
was updated. For example for VS Code there’s a nifty package Refresh NPM Packages that will prompt you to update your packages if it detects a modification. It will run regardless of whether you’ve setup Git hooks or not. Another nice thing is that it will work when you switch branches, even without merging one of them into the other.
However, the advantage of what we’ve implemented here is that it will run in the command line and it doesn’t depend on a particular code editor. If you’re working for example on an open source project you might want to setup what’s described here so there’s a common ground for all the developers involved regardless of their setup.