Upgrade to a Git Pro Automatcially

Tags: git, development, js

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

docs

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

docs

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

docs

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

docs

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!