Git Smart: Streamlining Your Workflow with the prepare-commit-msg Hook
Tags: git, jira
Published: 2023-02-26 04:00:23

## Overview

If you want to learn how to improve and automate your commit messages, you're in the right place!

- [Motivation](#motivation)
- [Setting up the prepare-commit-msg hook](#setting-up-the-git-hook)
- [Configure the hook globally](#configure-the-hook-globally)
- [Configure existing repositories](#configure-existing-repositories)

## Motivation

Most companies use an issue and project tracking software, such as JIRA, for software development. JIRA has integrations for many online VCSs. If you name your branches appropriately, then JIRA can automatically link to branches and pull requests created on many different code hosting platforms (GitHub, GitLab, Bitbucket, etc.)

When several developers are working in parallel, merging branches becomes commonplace. It can be very helpful to prefix your commits with the ticket number. For instance, assume you're working on ticket `JIRA-1234` and want to commit a change, you might want to do something like this:

```sh
git commit -m "JIRA-1234: add part of my awesome feature"
```

In theory, every commit could (and probably should) have this reference back to a ticket. If and when a someone needs more context around a commit, it provide the link to further documentation. However, since this is a manual process it can lead to a lack of uniformity and consistency.

But fear not! Git's got your back with its `prepare-commit-msg` hook.

## Setting up the git hook

Here's a painless one-liner to install the hook into an existing repository. Open a terminal, navigate to your repository, then run the following command:

```sh
curl  https://gist.githubusercontent.com/chaz8080/36b539ca29a29de11334e57a9dd3b61d/raw/4f6dc9232346b7d866bcfc0fbcdd43b6fb638073/install-hook.sh | sh
```

Here's what it's doing:

{% gist https://gist.github.com/chaz8080/36b539ca29a29de11334e57a9dd3b61d file=install-hook.sh %}

It should add a `prepare-commit-msg` file to your repo's `.git/hooks` folder, and make it executable. 

{% gist https://gist.github.com/chaz8080/36b539ca29a29de11334e57a9dd3b61d file=prepare-commit-msg %}

Assuming that you're on a branch named after the JIRA ticket, e.g. `JIRA-1234_my_awesome_feature`, then you can simply commit your message as you normally would, without any ticket info:

```sh
git commit -m "add another part of my awesome feature"
```

And the desired prefix will automatically be added. Running `git log`, you should see something like:

```sh
commit 8014201b6f223ca800c574bac093e53641c1bae9 (HEAD -> JIRA-1234_my_awesome_feature)
Author: John Smith <john.smith@gmail.com>
Date:   Sat Feb 25 21:05:22 2023 -0500

    JIRA-1234: add another part of my awesome feature
```

## Configure the hook globally

Instead installing the hook in every new repo cloned, let's configure global templates and configure the global [init.templatedir](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-inittemplateDir). 

Assuming that you do not already have templates set up, run the following command:

```sh
curl  https://gist.githubusercontent.com/chaz8080/36b539ca29a29de11334e57a9dd3b61d/raw/d1768296cbd15d59149097b8f8840ac107399567/configure-git-template.sh | sh
```

Again, a peek under the hood:

{% gist https://gist.github.com/chaz8080/36b539ca29a29de11334e57a9dd3b61d file=configure-git-template.sh %}

This configures the global git template directory and installs the previous hook.

This will configure a new directory `~/.git-template`. Anytime that you initialize or clone a new repository, these templates will be copied over.

## Configure existing repositories

Now that you know how to create a one off hook for a single repo, and how to make sure that all new repos get the same config, you might want a script to also add the `prepare-commit-msg` hook to all of your existing repos.

In terminal, and at the directory for which you store all of your repositories, simply run:

```sh
curl https://gist.githubusercontent.com/chaz8080/36b539ca29a29de11334e57a9dd3b61d/raw/d1768296cbd15d59149097b8f8840ac107399567/install-to-all-repos.sh | sh
```

For posterity, it simply searches all subdirectories for any git repositories and copies the `prepare-commit-msg` that was [previously configured](#configure-the-hook-globally) in your global git template:

{% gist https://gist.github.com/chaz8080/36b539ca29a29de11334e57a9dd3b61d file=install-to-all-repos.sh %}

## Conclusion

In conclusion, using the `prepare-commit-msg` hook is a simple and effective way to improve the organization and readability of your Git commits, particularly in a collaborative development environment. By automatically prepending JIRA ticket numbers to commit messages, you can make it easier to track changes and tie them back to specific tickets or issues.

Setting up the `prepare-commit-msg` hook globally across your organization is easy and can be done with just a few simple steps. By following the instructions outlined in this article, you can ensure that all of your Git repositories have the hook installed and ready to use.

I hope that this article has been helpful in guiding you through the process of setting up the `prepare-commit-msg` hook and that you can start using it to improve your Git workflow today. Happy coding!