Get "PHP 8 in a Nuthshell" (Now with PHP 8.4)
Amit Merchant

Amit Merchant

A blog on PHP, JavaScript, and more

Managing Git Hooks using Whisky in PHP

Git hooks are scripts that run automatically every time a particular event occurs in a Git repository. They let you customize Git’s internal behavior and trigger customizable actions at key points in the development life cycle.

For instance, if you want to run a linter every time you commit a change, you can use Git hooks to do that. Or if you want to run a test suite before you push your changes to the remote repository, you can use Git hooks to do that as well.

The traditional way of managing Git hooks is to create a file with the name of the hook inside the .git/hooks directory of your Git repository.

For instance, if you want to run a linter every time you commit a change, you can create a file called pre-commit inside the .git/hooks directory and add the following code to it.

#!/bin/sh

echo "Running linter before commit!"

The problem with this approach is that you can’t version control these hooks. So, if you want to share these hooks with your team, you have to manually copy these hooks to each of your team members’ machines. This is where this PHP package called Whisky comes in.

What is Whisky?

Whisky is a framework-agnostic PHP package that lets you manage Git hooks in a version-controlled way. It lets you define Git hooks in a JSON file and then it automatically creates the hooks for you in the .git/hooks directory of your Git repository.

Installation

You can install the package as a dev dependency in a Composer-based project using the following command.

composer require --dev projektgopher/whisky
./vendor/bin/whisky install

The only prerequisite for this package is that the project should be running on PHP 8.1 or higher.

Defining Git Hooks

Once installed, Whisky will create a whisky.json file in the root of your project. This file is used to define the Git hooks.

Here’s how it will look like.

{
  "disabled": [],
  "hooks": {
    "pre-commit": [
      "./vendor/bin/pint --dirty"
    ],
    "pre-push": [
      "composer test"
    ]
  }
}

As you can tell, the configuration is pretty straightforward. All the Git hooks are defined inside the hooks key. The keys in the hooks object are the name of the Git hooks and the value is an array of commands that you want to run when the hook is triggered.

In this example, we’re running Laravel Pint before every commit and running the test suite before every push. So, it will fix the code style issues before every commit. Also, it will run the test suite before every push.

Adding or removing any hooks (not individual commands) to your whisky.json file should be followed by ./vendor/bin/whisky update to ensure that these changes are reflected in your .git/hooks directory.

Disabling Git Hooks

If for some reason, you want to disable a Git hook, you can do that by adding the name of the hook inside the disabled key.

{
  "disabled": [
    "pre-commit"
  ],
  "hooks": {
    "pre-commit": [
      "./vendor/bin/pint --dirty"
    ],
    "pre-push": [
      "composer test"
    ]
  }
}

In this example, we’re disabling the pre-commit hook. So, it won’t run before every commit.

Skipping Git Hooks

If you want to skip a Git hook for a particular commit, you can do that by adding a --no-verify flag to the commit command.

git commit -m "My commit message" --no-verify

Or you can use the following command before running a Git command which will skip all the Git hooks once.

./vendor/bin/whisky skip-once

Under the hood

If you check the content of the hook file created by Whisky under the .git/hooks directory, you’ll see something like this.

# .git/hooks/pre-commit

#!/bin/sh
eval "$(/project-dir/vendor/bin/whisky get-run-cmd pre-commit)"

As you can tell, Whisky creates its own shell script that runs the commands defined in the pre-commit hook defined in the whisky.json file.

Conclusion

And that’s essentially the crux of what Whisky does. It’s a pretty handy tool if you want to manage Git hooks in a version-controlled way. You can learn more about this package on its repository.

Learn the fundamentals of PHP 8 (including 8.1, 8.2, 8.3, and 8.4), the latest version of PHP, and how to use it today with my new book PHP 8 in a Nutshell. It's a no-fluff and easy-to-digest guide to the latest features and nitty-gritty details of PHP 8. So, if you're looking for a quick and easy way to PHP 8, this is the book for you.

Like this article?

Buy me a coffee

👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.

Comments?