A former coworker and I had a system for letting each other know about dependency changes in shared codebases. We wrote npm install
on a post-it note and would stick it to the other person’s monitor. Once the post-it note eventually lost its stickiness, we just screwed up and threw it at each other. By the end of the project, the universal sign for ‘update your dependencies’ was to throw a random object across the room.
The only downside of this otherwise perfect system is that it doesn’t scale well, especially on distributed teams. A much better solution is to use git hooks.
Git hooks execute a command when git performs an action. They are useful for doing things like running a linter before you commit (pre-commit
) or running a build script when a server receives a push (post-receive
).
We want to check whether package-lock.json
has changed when we run git pull
, so we can use the post-merge
hook (git pull
being equivalent to git fetch
+ git merge
). If the lockfile has changed, we can echo
a notification to the user that they should run npm install
to bring their node_modules
directory up to date.
Create a git hook file
In your repo, create a file called post-merge
in .git/hooks
:
touch .git/hooks/post-merge
In that file we’re going to define a function that checks whether a file has changed between commits, and run that function with package-lock.json
as the argument:
function changed {
git diff --name-only HEAD@{1} HEAD | grep "^$1" > /dev/null 2>&1
}
if changed 'package-lock.json'; then
echo "📦 package-lock.json changed. Run npm install to bring your dependencies up to date."
fi
You could add notifications for other file changes in here, like Gemfile.lock
or Podfile.lock
.
Credit to 8bitDesigner for this approach.
Test the hook
Try out the hook by rewinding to a commit where you know package-lock.json
has changed, let’s say 20 commits ago, then running git pull
to fast-forward back to now:
git reset --hard HEAD~20 && git pull
If package-lock.json changed between now and then, you will see the notification.
Use husky to share your hook with others
Changes in the .git
directory are not version controlled, so we need to move our hook to somewhere that is. We then need to provide a way for other developers to easily install the hook for themselves. Thankfully husky exists to do exactly that.
Create a directory called .githooks
and move your hook there:
mkdir .githooks && mv .git/hooks/post-merge .githooks
Now we can set up husky. The npm post-install script for husky checks package.json
for any declared hooks and automatically installs them in .git/hooks
.
In package.json
add:
"husky": {
"hooks": {
"post-merge": "./.githooks/post-merge"
}
}
Then install husky:
npm install --save-dev husky
Next time someone runs npm install
with your changes, the hook will be installed in their local .git
directory.