Hooks

Besides the actual git hooks CaptainHook supports hooks that do not exist in git like post-change. Those hooks are called virtual hooks. Virtual hooks are hooks that get triggered by multiple git hooks. The post-change hook for example gets triggered by post-checkout, post-rewrite and post-merge. You can utilize virtual hooks to not have to copy paste hook configurations.

pre-commit

This hook will run before git executes a commit. Failing during this commit aborts the current commit. You can run unit tests, style checker or linter during this hook to make sure nobody commits 'broken' code.

"pre-commit": {
  "enabled": true,
  "actions": [
    {
      "action": "vendor/bin/phpunit"
    }
  ]
}

prepare-commit-msg

This hook will run before git executes a commit. Failing during this commit aborts the current commit. Here you get access to the provided git commit message to change it. This hook will not be skipped with --no-verify so you should not use it for validation.

This can be used if you want to include details into your commit messages that you can gather automatically.

"prepare-commit-msg": {
  "enabled": true,
  "actions": [
    {
      "action": "\\MyName\\GitHook\\PrepareCommitMessage",
      "options": []
    }
  ]
}

Custom Implementation

<?php
namespace MyName\GitHook;

use CaptainHook\App\Config\Action;
use CaptainHook\App\Console\IO;
use CaptainHook\App\Hook\Action as HookAction;
use SebastianFeldmann\Git\CommitMessage;
use SebastianFeldmann\Git\Repository as Repo;

class PrepareCommitMessage implements HookAction
{
    /**
     * Execute the action.
     *
     * @param  \CaptainHook\App\Config           $config
     * @param  \CaptainHook\App\Console\IO       $io
     * @param  \SebastianFeldmann\Git\Repository $repository
     * @param  \CaptainHook\App\Config\Action    $action
       @return void
     * @throws \Exception
     */
    public function execute(Config $config, IO $io, Repo $repository, Action $action) : void
    {
        $message         = $repository->getCommitMsg();
        $text            = 'This will be your commit message';
        $preparedMessage = new CommitMessage($text, $oldMessage->getCommentCharacter());
        $repository->setCommitMsg($preparedMessage);
    }
}

commit-msg

This hook will run before git executes a commit. Failing during this commit aborts the current commit. Here you get access to the provided git commit message to validate it.

"commit-msg": {
  "enabled": true,
  "actions": [
    {
      "action": "\\MyName\\GitHook\\NoEmptyCommitMessages",
      "options": []
    }
  ]
}

Custom Implementation

<?php
namespace MyName\GitHook;

use CaptainHook\App\Config\Action;
use CaptainHook\App\Console\IO;
use CaptainHook\App\Hook\Action as HookAction;
use SebastianFeldmann\Git\Repository as Repo;

class NoEmptyCommitMessages implements HookAction
{
    /**
     * Execute the action.
     *
     * @param  \CaptainHook\App\Config           $config
     * @param  \CaptainHook\App\Console\IO       $io
     * @param  \SebastianFeldmann\Git\Repository $repository
     * @param  \CaptainHook\App\Config\Action    $action
       @return void
     * @throws \Exception
     */
    public function execute(Config $config, IO $io, Repo $repository, Action $action) : void
    {
        $message = $repository->getCommitMsg();
        if (empty($message->getContent())) {
            throw new \Exception('Empty commit message is not allowed');
        }
    }
}

pre-push

This hook will run before git executes a push. Failing during this hook aborts the current push. You can run unit tests, style checker or linter during this hook to make sure nobody pushes 'broken' code.

"pre-push": {
  "enabled": true,
  "actions": [
    {
      "action": "vendor/bin/phpunit"
    }
  ]
}

post-commit

This hook will run after a successful commit. Failing during this hook has no effect on the commit.

"post-commit": {
  "enabled": true,
  "actions": [
    {
      "action": "do/some/post-commit-action"
    }
  ]
}

post-checkout

This hook will run after a successful checkout. Failing during this hook has no effect on the checkout.

"post-checkout": {
  "enabled": true,
  "actions": [
    {
      "action": "do/some/post-checkout-action"
    }
  ]
}

post-merge

This hook will run after a successful merge. Failing during this hook has no effect on the merge.

"post-merge": {
  "enabled": true,
  "actions": [
    {
      "action": "do/some/post-merge-action"
    }
  ]
}

post-rewrite

This hook will run after a successful rebase or amend. Failing during this hook has no effect on the git command.

"post-rewrite": {
  "enabled": true,
  "actions": [
    {
      "action": "do/some/post-rewrite-action"
    }
  ]
}

Virtual hooks

virtual hook name gets triggered by
post-change post-checkout, post-merge, post-rewrite