How to automate your work using Git’s add-on scripts?
Do you know you can automate a part of the work that you do every time during your development?
This includes running lint, test cases, etc. before committing and pushing the code. Git provides an excellent option to achieve this.
That’s called Git Hooks
Git Hooks, being an advanced topic do you know why I call it as Dark part of Git?
Because, being a powerful feature it was not widely adopted by many software development teams (including me, but I follow an alternative. Read further to know what is it & why I’m using that).
Let’s try to explore the below items in this blog
- What is Git Hooks?
- Why most development teams are not adopting Hooks in their development process?
What is Git Hooks?
Git Hooks is a feature of git that allows to run custom scripts on the occurrence of certain events at the git lifecycle. Some of the events include before-commit, after-commit, before-push, etc.
Why do we need Git Hooks?
Hooks is the tool that makes it much easier for developers to adhere to certain guidelines. These guidelines include running lint before committing, running test cases before pushing the code, etc. Git Hooks can be configured to make the action fail (by returning a non-zero exit code) if something was broken or not good (test case/lint failure).
Where can I find the Hooks configured on my repo?
Git Hooks comes pre-installed with the git repository. Whenever you initialize a git repo (
git init ) or clone a repo from any remote server (
git clone ). You can find all the hooks inside
.git/hooks directory from the root repo.
Every hook will be configured as a file. By default, git creates 12 sample hooks file listed below. The files that end with
.sample are example hook files generated by git.
Okay. That’s fine. I hope your next question will be,
What are all the available hooks which I can use?
Client Side Hooks
Server Side Hooks
This is not the entire list of all available Git hooks. These are the sample hook files that will be available by default on all git repositories. Head over to Git's official documentation to have a look at all supported hooks.
How to configure a hook?
Let’s take a look at a couple of examples of using it
prepare-commit-msg hook is run before the commit message editor is fired up but after the default message is created. It lets you edit the default message before the commit author sees it. This hook is generally used to template the commit message.
The parameters of this hook are,
- Path to the file that holds the commit message
- Type of commit
- Commit SHA-1, if this is an amended commit.
For example, I used to prepend my name in all the commits I made. We follow this across our organization.
As mentioned earlier, we need to remove
.sample from the file name. Find the code below to template your name while committing
We need to make the script executable. So, running
chmod +x on the file
Let’s try to commit our change,
The Nano text editor (system default) opens up immediately after I ran
git commit . From the below screenshot, you can see my name is already written to the commit message file (COMMIT_EDITMSG) and I just need to add the commit message.
That’s it. We have successfully setup
Let’s have a quick look at another simple example with a failure scenario.
The action will be failed if the hook(except a few) returns non-zero values.
pre-push hook fail by returning a non-zero value
I’ve 35 commits in my repo (haven’t pushed from the beginning of my blogging series). So, I’m not making any new commits and going to push the existing commits.
pre-push hook to pass by returning zero
Let’s try to push the commits again and verify if it works.
Hooray!!!! Our commits are pushed to the remote repo.
The only concern is the error message which we received when exiting with a non-zero value was not so user-friendly. It did not say that it has failed due to an error thrown from
error: failed to push some refs to 'firstname.lastname@example.org:arungogosoon/Git-Project.git'
Let’s jump into the next section of our blog
Why most development teams are not adopting Hooks in their development process?
There are many reasons to answer this question. However, I’m outlining a few of the most common causes.
- Hooks are local to any given Git repository and are not synced with the remote repository. This means, if you try to clone again, you’ll not see your hooks there. So, it’ll be challenging to manage them across the development team. But, we can overcome this with 2 workarounds.
1. Git allows us to move the hooks folder outside of
.gitfolder. We can create a symlink (shortcut) from
.git/hooksfolder to the folder where we moved the hooks files. With this approach, we can track the changes in the hooks file and it’ll be synced with the entire team.
2. By using some kind of alternative packages like
npmpackage which can be added in
huskyhelps us to configure commands to be executed on git hooks in the project configuration file. i.e.,
- Though we find workarounds to sync the hooks file, the developer can easily skip the hooks validation by adding
--no-verifywith every git command. With this in mind, it’s best to think of Git hooks as a convenient developer tool rather than a strictly enforced development policy. Unless a server-side verification is set up, these cannot be verified.
- While git hooks are a compelling guardrail to help enforce quality, like any guardrail, they also come with some downsides including slowing down well-disciplined developers, and withholding opportunities for less-disciplined developers to gain that discipline. When a hook is configured to run test cases on every commit, it reduces developer productivity due to the long-running test cases. This happens especially with the compiling & transpiling languages (Eg. Java, Typescript, etc. ). Rather than focusing effort on guardrails to prevent developers from doing the “wrong thing”, focus on building discipline so that developers will learn to do the “right thing”.
Q & A
I have limited experience of using
git hooks with my team.
But, I have an interesting question raised by Kumar from my team.
He asked, “I’m bad at shell scripting, but good at scripting in Python. Is there a way, I can run this hook in python?”
Even I don’t when he asks this question. But, we did a quick search immediately and found that it’s possible.
Just by replacing
#!/bin/sh with the python interpreter location (
#!/usr/bin/env python ) will work. We even tested this and this works fine.
Hope you enjoyed reading this article. Give a clap 👏 if you like this article. Subscribe to our newsletter to receive more such insightful articles that get delivered straight to your inbox.