| 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 Git project's 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). |
| |
| Please note: although, as a convenience, git-multimail may be |
| distributed along with the main Git project, development of |
| git-multimail takes place in its own, separate project. See section |
| "Getting involved" below for more information. |
| |
| |
| By default, for each push received by the repository, git-multimail: |
| |
| 1. Outputs one email summarizing each reference that was changed. |
| These "reference change" (called "refchange" below) emails describe |
| the nature of the change (e.g., was the reference created, deleted, |
| fast-forwarded, etc.) and include a one-line summary of each commit |
| that was 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 of files |
| modified by the commit. 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 |
| commits. 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. |
| |
| 3. Output one "announce" mail for each new annotated tag, including |
| information about the tag and optionally a shortlog describing the |
| changes since the previous tag. Such emails might be useful if you |
| use annotated tags to mark releases of your project. |
| |
| |
| Requirements |
| ------------ |
| |
| * Python 2.x, version 2.4 or later. No non-standard Python modules |
| are required. git-multimail does *not* currently work with Python |
| 3.x. |
| |
| The example scripts invoke Python using the following shebang line |
| (following PEP 394 [1]): |
| |
| #! /usr/bin/env python2 |
| |
| If your system's Python2 interpreter is not in your PATH or is not |
| called "python2", you can change the lines accordingly. Or you can |
| invoke the Python interpreter explicitly, for example via a tiny |
| shell script like |
| |
| #! /bin/sh |
| /usr/local/bin/python /path/to/git_multimail.py "$@" |
| |
| * The "git" command must be in your PATH. git-multimail is known to |
| work with Git versions back to 1.7.1. (Earlier versions have not |
| been tested; if you do so, please report your results.) |
| |
| * To send emails using the default configuration, a standard sendmail |
| program must be located at '/usr/sbin/sendmail' or |
| '/usr/lib/sendmail' and must be configured correctly to send emails. |
| If this is not the case, set multimailhook.sendmailCommand, or see |
| the multimailhook.mailer configuration variable below for how to |
| configure git-multimail to send emails via an SMTP server. |
| |
| |
| 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 |
| [2]. |
| |
| 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. |
| |
| If neither of these environments is suitable for your setup, then |
| you can implement a Python class that inherits from Environment |
| and instantiate it via a script that looks like the example |
| post-receive script. |
| |
| The environment value can be specified 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. The default is to use $GL_REPO |
| for gitolite repositories, or otherwise to derive this value from |
| the repository path name. |
| |
| 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. The default is the value in |
| multimailhook.mailingList. Set this value to the empty string to |
| prevent reference change emails from being sent even if |
| multimailhook.mailingList is set. |
| |
| 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. This configuration option can be multivalued. The |
| default is the value in multimailhook.refchangeList or |
| multimailhook.mailingList. Set this value to the empty string to |
| prevent annotated tag announcement emails from being sent even if |
| one of the other values is set. |
| |
| 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. The |
| default is the value in multimailhook.mailingList. Set this value |
| to the empty string to prevent notification emails about |
| individual commits from being sent even if |
| multimailhook.mailingList is set. |
| |
| 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.refchangeShowLog |
| |
| If this option is set to true, then summary emails about reference |
| changes will include a detailed log of the added commits in |
| addition to the one line summary. The log is generated by running |
| "git log" with the options specified in multimailhook.logOpts. |
| Default is false. |
| |
| multimailhook.mailer |
| |
| This option changes the way emails are sent. Accepted values are: |
| |
| - sendmail (the default): use the command /usr/sbin/sendmail or |
| /usr/lib/sendmail (or sendmailCommand, if configured). This |
| mode can be further customized via the following options: |
| |
| multimailhook.sendmailCommand |
| |
| The command used by mailer "sendmail" to send emails. Shell |
| quoting is allowed in the value of this setting, but remember that |
| Git requires double-quotes to be escaped; e.g., |
| |
| git config multimailhook.sendmailcommand '/usr/sbin/sendmail -oi -t -F \"Git Repo\"' |
| |
| Default is '/usr/sbin/sendmail -oi -t' or |
| '/usr/lib/sendmail -oi -t' (depending on which file is |
| present and executable). |
| |
| multimailhook.envelopeSender |
| |
| If set then pass this value to sendmail via the -f option to set |
| the envelope sender address. |
| |
| - smtp: use Python's smtplib. This is useful when the sendmail |
| command is not available on the system. This mode can be |
| further customized via the following options: |
| |
| multimailhook.smtpServer |
| |
| The name of the SMTP server to connect to. The value can |
| also include a colon and a port number; e.g., |
| "mail.example.com:25". Default is 'localhost' using port |
| 25. |
| |
| multimailhook.envelopeSender |
| |
| The sender address to be passed to the SMTP server. If |
| unset, then the value of multimailhook.from is used. |
| |
| multimailhook.from |
| |
| If set then use this value in the From: field of generated emails. |
| If unset, then use the repository's user configuration (user.name |
| and user.email). If user.email is also unset, then use |
| multimailhook.envelopeSender. |
| |
| multimailhook.administrator |
| |
| The name and/or email address of the administrator of the Git |
| repository; used in FOOTER_TEMPLATE. Default is |
| multimailhook.envelopesender if it is set; otherwise a generic |
| string is used. |
| |
| multimailhook.emailPrefix |
| |
| All emails have this string prepended to their subjects, to aid |
| email filtering (though filtering based on the X-Git-* email |
| headers 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 body of |
| a generated email. 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.maxCommitEmails |
| |
| The maximum number of commit emails to send for a given change. |
| When the number of patches is larger that this value, only the |
| summary refchange email is sent. This can avoid accidental |
| mailbombing, for example on an initial push. To disable commit |
| emails limit, set this option to 0. The default is 500. |
| |
| 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 |
| |
| Options passed to "git diff-tree" when generating the summary |
| information for 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. Shell quoting is allowed; see multimailhook.logOpts for |
| details. |
| |
| multimailhook.logOpts |
| |
| Options passed to "git log" to generate additional info for |
| reference change emails (used only if refchangeShowLog is set). |
| For example, adding --graph will show the graph of revisions, -p |
| will show the complete diff, etc. The default is empty. |
| |
| Shell quoting is allowed; for example, a log format that contains |
| spaces can be specified using something like: |
| |
| git config multimailhook.logopts '--pretty=format:"%h %aN <%aE>%n%s%n%n%b%n"' |
| |
| If you want to set this by editing your configuration file |
| directly, remember that Git requires double-quotes to be escaped |
| (see git-config(1) for more information): |
| |
| [multimailhook] |
| logopts = --pretty=format:\"%h %aN <%aE>%n%s%n%n%b%n\" |
| |
| multimailhook.commitLogOpts |
| |
| Options passed to "git log" to generate additional info for |
| revision change emails. For example, adding --ignore-all-spaces |
| will suppress whitespace changes. The default options are "-C |
| --stat -p --cc". Shell quoting is allowed; see |
| multimailhook.logOpts for details. |
| |
| 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 and overriding its get_pusher_email() |
| method. |
| |
| multimailhook.replyTo |
| multimailhook.replyToCommit |
| multimailhook.replyToRefchange |
| |
| Addresses to use in the Reply-To: field for commit emails |
| (replyToCommit) and refchange emails (replyToRefchange). |
| multimailhook.replyTo is used as default when replyToCommit or |
| replyToRefchange is not set. The value for these variables can be |
| either: |
| |
| - An email address, which will be used directly. |
| |
| - The value "pusher", in which case the pusher's address (if |
| available) will be used. This is the default for refchange |
| emails. |
| |
| - The value "author" (meaningful only for replyToCommit), in which |
| case the commit author's address will be used. This is the |
| default for commit emails. |
| |
| - The value "none", in which case the Reply-To: field will be |
| omitted. |
| |
| |
| Email filtering aids |
| -------------------- |
| |
| All emails include extra headers to enable fine tuned filtering and |
| give information for debugging. All emails include the headers |
| "X-Git-Host", "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 replaces 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 is mostly customized via an "environment" that describes |
| the local environment in which Git is running. Two types of |
| environment are built in: |
| |
| * GenericEnvironment: a stand-alone Git repository. |
| |
| * GitoliteEnvironment: a Git repository that is managed by gitolite |
| [3]. 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. |
| |
| If you need to customize the script in ways that are not supported by |
| the existing environments, you can define your own environment class |
| class using arbitrary Python code. To do so, you need to import |
| git_multimail.py as a Python module, as demonstrated by the example |
| post-receive script. Then implement your environment class; it should |
| usually inherit from one of the existing Environment classes and |
| possibly one or more of the EnvironmentMixin classes. Then set the |
| "environment" variable to an instance of your own environment class |
| and pass it to run_as_post_receive_hook(). |
| |
| The standard environment classes, GenericEnvironment and |
| GitoliteEnvironment, are in fact themselves put together out of a |
| number of mixin classes, each of which handles one aspect of the |
| customization. For the finest control over your configuration, you |
| can specify exactly which mixin classes your own environment class |
| should inherit from, and override individual methods (or even add your |
| own mixin classes) to implement entirely new behaviors. If you |
| implement any mixins that might be useful to other people, please |
| consider sharing them with the community! |
| |
| |
| Getting involved |
| ---------------- |
| |
| git-multimail is an open-source project, built by volunteers. We |
| would welcome your help! |
| |
| The current maintainer is Michael Haggerty <mhagger@alum.mit.edu>. |
| |
| General discussion of git-multimail takes place on the main Git |
| mailing list, |
| |
| git@vger.kernel.org |
| |
| Please CC emails regarding git-multimail to me so that I don't |
| overlook them. |
| |
| The git-multimail project itself is currently hosted on GitHub: |
| |
| https://github.com/mhagger/git-multimail |
| |
| We use the GitHub issue tracker to keep track of bugs and feature |
| requests, and GitHub pull requests to exchange patches (though, if you |
| prefer, you can send patches via the Git mailing list with cc to me). |
| Please sign off your patches as per the Git project practice. |
| |
| Please note that although a copy of git-multimail will probably be |
| distributed in the "contrib" section of the main Git project, |
| development takes place in the separate git-multimail repository on |
| GitHub! (Whenever enough changes to git-multimail have accumulated, a |
| new code-drop of git-multimail will be submitted for inclusion in the |
| Git project.) |
| |
| |
| Footnotes |
| --------- |
| |
| [1] http://www.python.org/dev/peps/pep-0394/ |
| |
| [2] 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. |
| |
| [3] https://github.com/sitaramc/gitolite |