Skip to main content

Send notification emails for git pushes

Project description

git-multimail
=============

git-multimail is a tool for sending notification emails on pushes to a
git repository. It includes a Python module called git_multimail.py,
which can either be used as a hook script directly or can be imported
as a Python module into another script.

git-multimail is derived from the old
contrib/hooks/post-receive-email, and is mostly compatible with that
script. See README.migrate-from-post-receive-email for details about
the differences and for how to migrate from post-receive-email to
git-multimail.

git-multimail, like the rest of the git project, is licensed under
GPLv2 (see the COPYING file for details).


By default, for each push received by the repository, git-multimail:

1. Outputs one email summarizing each reference that was changed.
These "reference change" emails describe the nature of the change
(e.g., was the reference created, deleted, fast-forwarded, etc.)
and include one-line summaries of the commits that were added to
the reference.

2. Outputs one email for each new commit that was introduced by the
reference change. These "commit" emails include a list of the
files changed by the commit, followed by the diffs to text files.
The commit emails are threaded to the corresponding reference
change email via "In-Reply-To". This style (similar to the "git
format-patch" style used on the git mailing list) makes it easy
to scan through the emails, jump to patches that need further
attention, and write comments about specific emails. Commits are
handled in reverse topological order (i.e., parents shown before
children). For example,

[git] branch master updated
+ [git] 01/08: doc: fix xref link from api docs to manual pages
+ [git] 02/08: api-credentials.txt: show the big picture first
+ [git] 03/08: api-credentials.txt: mention credential.helper explicitly
+ [git] 04/08: api-credentials.txt: add "see also" section
+ [git] 05/08: t3510 (cherry-pick-sequence): add missing '&&'
+ [git] 06/08: Merge branch 'rr/maint-t3510-cascade-fix'
+ [git] 07/08: Merge branch 'mm/api-credentials-doc'
+ [git] 08/08: Git 1.7.11-rc2

Each commit appears in exactly one commit email, the first time that
it is pushed to the repository. If a commit is later merged into
another branch, then a one-line summary of the commit is included in
the reference change email (as usual), but no additional commit email
is generated.

By default, reference change emails have their "Reply-To" field set to
the person who pushed the change, and commit emails have their
"Reply-To" field set to the author of the commit.


Invocation
----------

git_multimail.py is designed to be used as a "post-receive" hook in a
git repository (see githooks(5)). Link or copy it to
$GIT_DIR/hooks/post-receive within the repository for which email
notifications are desired. Usually it should be installed on the
central repository for a project, to which all commits are eventually
pushed.

For use on pre-v1.5.1 git servers, git_multimail.py can also work as
an "update" hook, taking its arguments on the command line. To use
this script in this manner, link or copy it to $GIT_DIR/hooks/update.
Please note that the script is not completely reliable in this mode
[1].

Alternatively, git_multimail.py can be imported as a Python module
into your own Python post-receive script. This method is a bit more
work, but allows the behavior of the hook to be customized using
arbitrary Python code. For example, you can use a custom environment
(perhaps inheriting from GenericEnvironment or GitoliteEnvironment) to

* change how the user who did the push is determined

* read users' email addresses from an LDAP server or from a database

* decide which users should be notified about which commits based on
the contents of the commits (e.g., for users who want to be notified
only about changes affecting particular files or subdirectories)

Or you can change how emails are sent by writing your own mailer
class. The "post-receive" script in this directory demonstrates how
to use git_multimail.py as a Python module. (If you make interesting
changes of this type, please consider sharing them with the
community.)


Configuration
-------------

By default, git-multimail mostly takes its configuration from the
following "git config" settings:

multimailhook.environment

This describes the general environment of the repository.
Currently supported values:

"generic" -- the username of the pusher is read from $USER and the
repository name is derived from the repository's path.

"gitolite" -- the username of the pusher is read from $GL_USER and
the repository name from $GL_REPO.

It is possible to define a new environment by implementing a class
that inherits from Environment, then adding it to
KNOWN_ENVIRONMENTS.

The environment value can be overridden on the command line using
the --environment option. If it is not specified on the command
line or by multimailhook.environment, then it defaults to
"gitolite" if the environment contains variables $GL_USER and
$GL_REPO; otherwise "generic".

multimailhook.reponame

A short name of this git repository, to be used in various places
in the notification email text. Default is to derive this value
from the repository path, or to use $GL_REPO for gitolite
repositories.

multimailhook.mailinglist

The list of email addresses to which notification emails should be
sent, as RFC 2822 email addresses separated by commas. This
configuration option can be multivalued. Leave it unset or set it
to the empty string to not send emails by default. The next few
settings can be used to configure specific address lists for
specific types of notification email.

multimailhook.refchangelist

The list of email addresses to which summary emails about
reference changes should be sent, as RFC 2822 email addresses
separated by commas. This configuration option can be
multivalued. Defaults to the value in multimailhook.mailinglist.
Set this value to the empty string to prevent reference change
emails from being sent.

multimailhook.announcelist

The list of email addresses to which emails about new annotated
tags should be sent, as RFC 2822 email addresses separated by
commas. Defaults to the value in multimailhook.refchangelist or
multimailhook.mailinglist. Set this value to the empty string to
prevent annotated tag announcement emails from being sent.

multimailhook.commitlist

The list of email addresses to which emails about individual new
commits should be sent, as RFC 2822 email addresses separated by
commas. This configuration option can be multivalued. Defaults
to the value in multimailhook.mailinglist. Set this value to the
empty string to prevent notification emails about individual
commits from being sent.

multimailhook.announceshortlog

If this option is set to true, then emails about changes to
annotated tags include a shortlog of changes since the previous
tag. This can be useful if the annotated tags represent releases;
then the shortlog will be a kind of rough summary of what has
happened since the last release. But if your tagging policy is
not so straightforward, then the shortlog might be confusing
rather than useful. Default is false.

multimailhook.envelopesender

If set then pass this value to sendmail via the -f option to set
the envelope sender address.

multimailhook.administrator

The name and/or email address of the administrator of the git
repository; used in FOOTER_TEMPLATE. Default is
multimailhook.envelopesender.

multimailhook.emailprefix

All emails have this string prepended to their subjects, to aid
email filtering (though using the X-Git-* email headers, if
possible, is probably more robust). Default is the short name of
the repository in square brackets; e.g., "[myrepo]".

multimailhook.emailmaxlines

The maximum number of lines that should be included in the
generated email body. If not specified, there is no limit. Lines
beyond the limit are suppressed and counted, and a final line is
added indicating the number of suppressed lines.

multimailhook.emailmaxlinelength

The maximum length of a line in the email body. Lines longer than
this limit are truncated to this length with a trailing " [...]"
added to indicate the missing text. The default is 500, because
(a) diffs with longer lines are probably from binary files, for
which a diff is useless, and (b) even if a text file has such long
lines, the diffs are probably unreadable anyway. To disable line
truncation, set this option to 0.

multimailhook.emailstrictutf8

If this boolean option is set to "true", then the main part of the
email body is forced to be valid UTF-8. Any characters that are
not valid UTF-8 are converted to the Unicode replacement
character, U+FFFD. The default is "true".

multimailhook.diffopts

Alternate options for the git diff-tree invocation that summarizes
changes in ReferenceChange emails. Default is "--stat --summary
--find-copies-harder". Add -p to those options to include a
unified diff of changes in addition to the usual summary output.

multimailhook.emaildomain

Domain name appended to the username of the person doing the push
to convert it into an email address (via "%s@%s" % (username,
emaildomain)). More complicated schemes can be implemented by
overriding Environment.username_to_email().


Email filtering
---------------

All emails include extra headers to enable fine tuned filtering and
give information for debugging. All emails include the headers
"X-Git-Repo", "X-Git-Refname", and "X-Git-Reftype". ReferenceChange
emails also include headers "X-Git-Oldrev" and "X-Git-Newrev";
Revision emails also include header "X-Git-Rev".


Customizing email contents
--------------------------

git-multimail mostly generates emails by expanding templates. The
templates can be customized. To avoid the need to edit
git_multimail.py directly, the preferred way to change the templates
is to write a separate Python script that imports git_multimail.py as
a module, then replace the templates in place. See the provided
post-receive script for an example of how this is done.


Customizing git-multimail for your environment
----------------------------------------------

git-multimail has a concept called an "Environment" that describes the
local environment in which git is running. It has built-in support
for two kinds of environments:

* GenericEnvironment: a stand-alone git repository.

* GitoliteEnvironment: a git repository that is managed by gitolite
[2]. For such repositories, the identity of the pusher is read from
environment variable $GL_USER, and the name of the repository is
read from $GL_REPO (if it is not overridden by
multimailhook.reponame).

By default, git-multimail assumes GitoliteEnvironment if $GL_USER and
$GL_REPO are set, and otherwise assumes GenericEnvironment.
Alternatively, you can choose one of these two environments explicitly
by setting a "multimailhook.environment" config setting (which can
have the value "generic" or "gitolite") or by passing an --environment
option to the script.

You can override the Environment class using arbitrary Python code to
customize the script to idiosyncrasies your own environment. To do
so, you need to import git_multimail.py as a Python module, as in the
example post-receive script, and set the "environment" variable to an
instance of your environment class. Your environment class should
usually inherit from one of the provided Environment classes.


Footnotes
---------

[1] Because of the way information is passed to update hooks, the
script's method of determining whether a commit has already been
seen does not work when it is used as an "update" script. In
particular, no notification email will be generated for a new
commit that is added to multiple references in the same push.

[2] https://github.com/sitaramc/gitolite

Project details


Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page