NAME

Git::Hooks::CheckCommit - Git::Hooks plugin to enforce commit policies

VERSION

version 4.0.0

SYNOPSIS

As a Git::Hooks plugin you don't use this Perl module directly. Instead, you may configure it in a Git configuration file like this:

[githooks]

  # Enable the plugin
  plugin = CheckCommit

  # These users are exempt from all checks
  admin = joe molly

  # The @mergers group is used below
  groups = mergers = larry sally

[githooks "checkcommit"]

  # Reject commits if the author or committer name contains any characters
  # other then lowercase letters.
  name = !^[a-z]+$

  # Reject commits if the author or committer email does not belong to the
  # @cpqd.com.br domain.
  email = @cpqd\.com\.br$

  # Enable several integrity checks on the author and committer emails using
  # the Email::Valid Perl module.
  email-valid = true

  # Only users in the @mergers group can push merge commits.
  merger = @mergers

  # Rejects pushes with more than two commits in a single branch, in order to
  # avoid careless pushes.
  push-limit = 2

  # Reject commits unless they are signed with a GPG key
  # and the signature is good (does not need to be trusted).
  signature = good

DESCRIPTION

This Git::Hooks plugin hooks itself to the hooks below to enforce commit policies.

  • pre-commit, pre-applypatch

    This hook is invoked before a commit is made to check the author and committer identities.

  • post-commit, post-applypatch

    This hook is invoked after a commit is made to check its signature. Note that the commit is checked after it has been made and any errors must be fixed with a git-commit --amend command afterwards.

  • update

    This hook is invoked multiple times in the remote repository during git push, once per branch being updated, to check if all commits being pushed comply.

  • pre-receive

    This hook is invoked once in the remote repository during git push, to check if all commits being pushed comply.

  • ref-update

    This hook is invoked when a direct push request is received by Gerrit Code Review, to check if all commits being pushed comply.

  • commit-received

    This hook is invoked when a push request is received by Gerrit Code Review to create a change for review, to check if all commits being pushed comply.

  • submit

    This hook is invoked when a change is submitted in Gerrit Code Review, to check if all commits being pushed comply.

  • patchset-created

    This hook is invoked when a push request is received by Gerrit Code Review for a virtual branch (refs/for/*), to check if all commits being pushed comply.

Projects using Git, probably more than projects using any other version control system, have a tradition of establishing policies on several aspects of commits, such as those relating to author and committer identities and commit signatures.

To enable this plugin you should add it to the githooks.plugin configuration option:

[githooks]
  plugin = CheckCommit

NAME

Git::Hooks::CheckCommit - Git::Hooks plugin to enforce commit policies

CONFIGURATION

The plugin is configured by the following git options under the githooks.checkcommit subsection.

It can be disabled for specific references via the githooks.ref and githooks.noref options about which you can read in the Git::Hooks documentation.

name [!]REGEXP

This multi-valued option impose restrictions on the valid author and committer names using regular expressions.

The names must match at least one of the "positive" regular expressions (the ones not prefixed by "!") and they must not match any one of the negative regular expressions (the ones prefixed by "!").

This check is performed by the pre-commit local hook.

This allows you, for example, to require that author and committer names have at least a first and a last name, separated by spaces:

[githooks "checklog"]
  name = .\\s+.

email [!]REGEXP

This multi-valued option impose restrictions on the valid author and committer emails using regular expressions.

The emails must match at least one of the "positive" regular expressions (the ones not prefixed by "!") and they must not match any one of the negative regular expressions (the ones prefixed by "!").

This check is performed by the pre-commit local hook.

email-valid BOOL

This option uses the Email::Valid module' address method to validate author and committer email addresses.

These checks are performed by the pre-commit local hook.

Note that the Email::Valid module isn't required to install Git::Hooks. If it's not found or if there's an error in the construction of the Email::Valid object the check fails with a suitable message.

The Email::Valid constructor (new) accepts some parameters. You can pass the Boolean parameters to change their default values by means of the following sub-options. For more information, please consult the Email::Valid documentation.

githooks.checkcommit.email-valid.mxcheck BOOL

Specifies whether addresses should be checked for a valid DNS entry. The default is false.

githooks.checkcommit.email-valid.tldcheck BOOL

Specifies whether addresses should be checked for valid top level domains. The default is false.

githooks.checkcommit.email-valid.fqdn BOOL

Species whether addresses must contain a fully qualified domain name (FQDN). The default is true.

githooks.checkcommit.email-valid.allow_ip BOOL

Specifies whether a "domain literal" is acceptable as the domain part. That means addresses like: rjbs@[1.2.3.4]. The default is true.

canonical MAILMAP

This option requires the use of canonical names and emails for authors and committers, as configured in a MAILMAP file and checked by the git-check-mailmap command. Please, read that command's documentation to know how to configure a mailmap file for name and email canonicalization.

This check is only able to detect known non-canonical names and emails that are converted to their canonical forms by the git-check-mailmap command. This means that if an unknown email is used it won't be considered an error.

Note that the git-check-mailmap command is available since Git 1.8.4. Older versions of Git don't have it and Git::Hooks will complain accordingly.

Note that you should not have Git configured to use a default mailmap file, either by placing one named .mailmap at the top level of the repository or by setting the configuration options mailmap.file and mailmap.blob. That's because if Git is configured to use a mailmap it will convert non-canonical to canonical names and emails before passing them to the hooks. This will invoke git-check-mailmap using the -c option to temporarily configure it to use the MAILMAP file.

These checks are performed by the pre-commit local hook.

signature {nocheck|optional|good|trusted}

This option allows one to check commit signatures according to these values:

  • nocheck

    By default, or if this value is specified, no check is performed. This value is useful to disable checks in a repository when they are enabled globally.

  • optional

    This value does not require commits to be signed but if they are their signatures must be valid (i.e. good or untrusted, but not bad).

  • good

    This value requires that all commits be signed with good signatures.

  • trusted

    This value requires that all commits be signed with good and trusted signatures.

This check is performed by the post-commit local hook.

merger WHO

This multi-valued option restricts who can push commit merges to the repository. WHO may be specified as a username, a groupname, or a regex, like the githooks.admin option (see "CONFIGURATION" in Git::Hooks) so that only users matching WHO may push merge commits.

push-limit INT

This limits the number of commits that may be pushed at once on top of any reference. Set it to 1 to force developers to squash their commits before pushing them. Or set it to a low number (such as 3) to deny long chains of commits to be pushed, which are usually made by Git newbies who don't know yet how to amend commits. ;-)

check-code CODESPEC

If the above checks aren't enough you can use this option to define a custom code to check your commits. The code may be specified directly as the option's value or you may specify it indirectly via the filename of a script. If the option's value starts with "file:", the remaining is treated as the script filename, which is executed by a do command. Otherwise, the option's value is executed directly by an eval. Either way, the code must end with the definition of a routine, which will be called once for each commit with the following arguments:

Since the codes may take much time to run, the plugin checks if the githooks.timeout option has been violated after each code runs.

  • GIT

    The Git repository object used to grok information about the commit.

  • COMMIT

    This is a hash representing a commit, as returned by the Git::Repository::Plugin::GitHooks::get_commits method.

  • REF

    The name of the reference being changed, for the update and the pre-receive hooks. For the pre-commit hook this argument is undef.

The subroutine should return a Boolean value indicating success. Any errors should be produced by invoking the Git::Repository::Plugin::GitHooks::error method.

If the subroutine returns undef it's considered to have succeeded.

If it raises an exception (e.g., by invoking die) it's considered to have failed and a proper message is produced to the user.

REFERENCES

AUTHOR

Gustavo L. de M. Chaves <gnustavo@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2024 by CPQD <www.cpqd.com.br>.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.