Upgrade to a Git Pro Automatcially
Use Git Hooks
You probably suck at git. On top of that, you probably have a lot of other things you’re worrying about. It’s ok, we all have that problem.
But git is not just a tool to bonk new developers with weird corners. It’s not just a tool to make you interact with your coworkers during pull requests. It’s also a development tool.
I’m talking about git hooks; they’re one of the often overlooked features of git. I’m also trying to help you avoid Medium, but I’m sure you could find something there if you wanted to.
The main point I’ll try and get across here is that git hooks are automations. They’re great because they do chores for you, and if you’re not using them or have never heard of them, it’s time to up your game.
How Do I Become a Pro Now?
Ok, so say you have linting, like npm run lint
. Do this in ./.git/hooks/pre-commit
#!/usr/bin/env sh
npm run lint
easy, you’re a pro.
What the Heck is a Hook?
Hooks are side-effects. So CLEAN code can get thrown out the window (if you still have a copy that is).
Ok, well I also wanted to get on the dirty code bandwagon.
Hooks are sanctioned side effects; they’re extension points that you’d expect other programs and scripts to take advantage of. Webhooks are a good example in the, erm, web, but git has had these for quite a while now. The full documentation is here, but the basic idea is simple. At specific points of the source control lifecycle we want to run code, that’s what makes us a pro.
The snippet I placed above runs npm run lint
before you commit. In *Nix tradition if that program throws a 1
back at us, then the commit is blocked. If your linter is set up like mine then even if you have some dirty looking code it’ll get cleaned up and updated before you write the commit message.
So what other hooks should you use?
pre-commit
path: /.git/hooks/pre-commit
I already touched on this one, but it’s worth going into some detail. Add stuff that needs to be in always, even if this code isn’t shipping. For my Typescript projects, that’s things like tsc
, lint
, and prettier
. If you have something that checks for keys, then run that (don’t commit keys to the repo!). For a document repo, maybe you run a spellcheck. For a python project, maybe black3
etc.
Pre-Commit is one of the best hooks to work with, because it’s before any changes go even to local. So if you’ve messed up your files to the point that the linter won’t stop crying, no one else has to see, and you can’t accidentally push that to remote.
There’s even an escape hatch that lets us get out of this, so if we need to do a WIP commit you can still push whatever you need
# heck with hooks, SEND IT!
git commit --no-verify
prepare-commit-msg
path: /.git/hooks/pre-commit
The default message doesn’t live here (that’s a git template) but if you did want to use a script to mess with that, then this would be the place.
# Please enter the commit message fro your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# time to write a great commit
This shouldn’t be confused with the commit-msg hook. That hook takes your already completed commit message and messes with it. Usually you’ll want to only use that if your commit message have to have some formatting or something. Most modern git clients don’t care so much, but back in the day (pre 2005?) that hook was probably very useful. The docs have an example of how to use that hook.
pre-push
path: /.git/hooks/pre-push
Ok, now we’re really getting into it, making well-formatted commtis is fine and all but what about sharing your actual work with people? In the past I’ve done this without checking all of the boxes (unit tests, integration tests if I have them) and ooops, we broke prod after my merge.
So before you push, mayyybe you want to test what you wrote?
I use pre-push for that,
post-receive
path: /.git/hooks/post-recieve
So far, the hooks I’ve been talking about relate directly to pushing up code, but what if you have a remote that wants to pull code down and then update itself?
well this is a pretty good place to start. I’ll be honest, I’ve never used something like this but if you do have git remotes on production servers that you can actually push code to then this is a pretty elegant solution. Please don’t take that as an endorsement to use this on a mission-critical system, there are definitely dangers to pushing to prod
How do I use Git Hooks in JS?
Consider Husky for your next JS project, getting started from them:
npm install husky -D
Or, even initialize a project with Husky:
npx husky-init && npm install
Husky is the way to go: not only does it allow you to manage Git Hooks in a repository (with auto-install), it’s got good support.
Next thing is to create the hook; if you didn’t already upgrade your git practice [above]({{ < relfref “#pro-now” > }}), you can do it here:
npx add .husky/pre-commit "npm run lint"
git add .husky/pre-commit
and now you’re a pro, with a husky: 🐶
The thing that makes me really excited about this is that when you pull the repo onto your other machines, you get the automations you just spent working on automatically.
The Book on Hooks
To Wrap it up, let’s look at more info; I want to give you an on ramp to expand your own understanding. I found this while scouring for this post. It’s got a lot of great information beyond the git SCM docs, and it’s written pretty well and has even more links and references to more people talking about this.
Go forth, Git Pro!