Git Hooks Users Guide

This document provides a quick reference towards using AdaCore's "Git Hooks", which are the scripts used to manage our git repositories, when new commits get pushed. These scripts are typically responsible for pre-commit checks, and email notifications.

The source for these hooks can be found at: https://github.com/adacore/git-hooks

Enabling the hooks

The hooks have been designed to work with both bare and non-bare repositories. But typical usage will be with bare repositories.

o enable the hooks, an administrator needs to replace the "hooks" directory in your git repository by a link to the /hooks directory from a git-hooks checkout, and configure them as outlined below.

Minimum Configuration

The following config options must be set for all repositories. Updates of any kind will be rejected with an appropriate error message until minimum configuration is satisfied.

See below for a description of these config options.

Configuration

Configuration File location

The hooks configuration is loaded from a file named project.config in branch refs/meta/config. This file follows the same format as the various git "config" files (Eg. $HOME/.gitconfig).

To update your repository's configuration, you will need to do the following:

Updating the Configuration File

To update your repository's configuration, you will need to do the following

  $ git fetch origin refs/meta/config
  $ git checkout FETCH_HEAD

  $ git config -f project.config --add hooks.from-domain adacore.com
  $ git config -f project.config --add hooks.mailinglist ide-ci@adacore.com

  [hooks]
      from-domain = adacore.com
      mailinglist = ide-ci@adacore.com

  $ git commit -a -m "Notify ide-ci@adacore.com of changes"
  $ git push origin HEAD:refs/meta/config

General Information about Configuration Options

Some of the configuration options supported by git-hooks are lists (Eg: a list of references). For such options, the value of that configuration option can be specified with either:

    no-emails = refs/heads/fsf-.*, refs/heads/thirdparty

    no-emails = refs/heads/fsf-.*
    no-emails = refs/heads/thirdparty

Configuration Options for General Use

The following config options are available for general use:

    frozen-ref = refs/heads/gdb-7.4
    frozen-ref = refs/heads/gdb-7.5

    ignore-refs = refs/heads/ignore-.*
    ignore-refs = refs/heads/internal/

    no-emails = /refs/heads/fsf-.*
    no-emails = /refs/heads/thirdparty

    no-precommit-check = /refs/heads/fsf-.*
    no-precommit-check = /refs/heads/thirdparty

    no-rh-style-checks = /refs/heads/fsf-.*
    no-rh-style-checks = /refs/heads/thirdparty

    reject-merge-commits = refs/heads/master
    reject-merge-commits = refs/heads/gdb-.*

Configuration Options for Debugging

The following config options are recognized, but are only meant to be used for debugging/testing purposes. They should not be used during normal operations.

Pre-commit Checks

"Revert" commits

In order to avoid unnecessary complications while reverting a commit that is causing problems, all pre-commit checks (revision log, style checks) are deactivated for commits created by "git revert".

Since there is no reliable feature that we can use to identify these commits, the git-hooks rely on a heuristic instead, and look for a pattern in the commit's revision log that gets automatically inserted by the "git revert" command. In particular, at the moment, we look for the following pattern:

Pre-commit Checks on the Revision History

The hooks verify that the revision histories of all new commits being pushed comply with the rules defined below. This step is skipped for any commit whose revision history contains the 'no-rh-check' sequence.

Rules enforced on the revision logs:

YES:
      | The subject of my commit - no other explanation required.

YES:
      | The subject of my commit
      |
      | This is what this commit does.

NO:
      | The subject of my commit
      | This is what this commit does, but an empty line is missing
      | between the subject and this description.

Filename Collisions Pre-commit Check

On Operating Systems such as Darwin or Windows, where the File System is typically case-insensitive, having two files whose name only differ in the casing (Eg: "hello.txt" and "Hello.txt", or "dir/hello.txt" vs "DIR/hello.txt") can cause a lot of confusion. To avoid this, the hooks will reject any commit where such name collision occurs.

This check is disabled on the branches matching the hooks.no-precommit-check config value, or if a valid $HOME/.no_cvs_check file is found (see below).

Pre-commit Checks on the Differences Introduced by the Commit

This is the usual "style check" performed by the style_checker program.

Note that the program verifies the entire contents of the files being modified, not just the modified parts.

Controlling the Pre-commit Checks

/!\ Despite the use of very similar names, note the fairly important difference in scope between the hooks.no-precommit-checks config option, and the no-precommit-check git attribute! (see below)

By default, the pre-commit checks are turned on for all commits of all branches. The following controls are available to tailor the hooks' behavior regarding this check:

Email Notifications

In general, developers are notified via email whenever a change is pushed to the repository. This section describes the policy used to determine which emails are being sent.

The Summary Email

The purpose of this email is to give a quick overview of what has changed.

Composition

The Summary Email is composed of two sections:

  1. A short description of what has changed. For instance, if a tag was created, it will explain what kind of tag was created, what the associated revision log was, and what commit it points to.
  2. Optionally, a list of commits which have been lost and/or added.

Sending Policy

The general policy is to send the Summary Email for all updates in order to inform its developers about the change. However, there are a number of situations where the email would bring little information to the Commit Emails already sent out:

Filing Policy

Normally, this email is not used for filing purposes (ie, a copy is not even sent to file-ci@), as we are more interested in filing the individual commits than the summary.

However, it is interesting to file those emails in the following cases:

In those cases, the revision log attached to those tags may contain a TN, which means this event deserves filing.

In either case, a Diff: marker is always added before the section summarizing the list of commits that were lost and/or added, making sure that this part of the email never gets filed, as the commits themselves are already getting filed.

The Commit Emails

Composition

The subject of that email is the commit's subject and its contents is roughly what the git show command would display.

Sending Policy

The Commit Email is always sent, unless the commit is found to exist in a branch matching the hooks.no-emails configuration.

Filing Policy

This email is always bcc'd to file-ci@. Note that this list must not appear in any explicit To:/Cc: header, as we want to prevent any replies from being sent there.

Using a script in hooks.mailinglist

For projects that share the same git repository but want separate email addresses for email notifications, it is possible to use a script in place of an email address in the hooks.mailinglist config. Script entries are indentified by the fact that the entry is an absolute filename, and that this filename points to a file on the server which an executable.

{i} Note that the "term" script is used loosely here as, although we expect most users of that feature to indeed use a script, a compiled program would work just as well.

Script Calling Convention

This script is called by the hooks as follow:

The hooks expects the script to return the list of email addresses on standard output, one email address per line.

By convention, we expect the scripts to return all email addresses when the given list of files being changed is empty. This is useful for "cover" emails that the hooks want to send to everyone.

Script Email Expansion Policy for Commit Emails

For commit emails, the hooks will call the mailinglist script with the list of files being changed by the commit, and let the script decide who should be notified based on that list of files.

Script Email Expansion Policy for Git Note Update Emails

Git Note Update emails are similar to Commit Emails, and therefore the distribution list will be computed based on the list of files being changed. The only difference is that the list of files is going to be the list of files in the commit being annotated, not the note's commit.

Script Email Expansion Policy for "Cover" Emails

The expansion policy for cover emails is currently very simple: Send to everyone.

Rationale:

Retiring Old Branches

The recommended method for retiring a branch which is no longer useful is to add a hooks.frozen-ref in the project's project.config file which lists the branch's reference name. Eg:

    [hooks]
        frozen-ref = refs/heads/gdb-7.5

Alternatively, the following (legacy) method is also available:

By using the naming suggested for the tag, the hooks will ensure that the branch never gets accidently recreated. This would otherwise happen if a developer did not know that the branch was deleted, still had that branch locally in his repository, and tried to push his change as usual.

The use of the retired/ namespace for those tags also helps standardizing the location where those tags are created.

And the use of a tag allows everyone to determine the latest state of that branch prior to its retirement.

None: GitHooksUsersGuide (last edited 2017-12-13 13:32:25 by brobecke)

All content (C) 2008 Free Software Foundation. For terms of use, redistribution, and modification, please see the WikiLicense page.