Setting Up Git Commit Email Notifications

A method to send email notification to a list of email addresses by the remote git server after every push from the client will be introduced in this post. An example notification email after a commit is shown in the figure below. The subject contains a prefix, the repository name, the branch name and the last commit message. The body of the email contains a summary of the changes and the commit log.


How does it work

After the client pushing to the git server, several actions are triggered. These actions are done by hooks. Hooks are scripts placed in the GIT_DIR/hooks directory. Here, GIT_DIR is the directory of the git repository on the git server. One of the trigger action is post-receive,  so we can put a executable script with name post-receive under GIT_DIR/hooks. For every push by clients, post-receive will be executed to send email notification.

Now lets go to the detail of how to set up the email notification.

Get the post-receive script

My script that sends email like the example described above can be downloaded from: git post-receive script.

Or view the source code: git post-receive script

This script uses mailx to send email by default which uses the local message transfer agent service (like sendmail) to send email. You need to enable the message transfer agent to send out emails on your git server. You can also choose to use smtp to send out email, just find the line

# cat $email_tmp_file | mailx -S smtp="smtp://" -s "$emailsubject" -r $senderemail $recipients

near to the bottom of the script, uncomment it out, comment out the next line which calls mailx, and change the smtp server to yours. The script will use smtp server to send email. If you like to use Gmail’s smtp, please refer to Sending Email from mailx Command in Linux Using Gmail’s SMTP.

This script is changed from Andy Parkins’s one which is in git’s distribution. On fedora 12, the original script can be found under /usr/share/git-core/contrib/hooks.

Put the post-receive script into hooks directory

After getting the post-receive script, you need to copy it to or make a soft link (which I do since there usually many repositories) in the GIT_DIR/hooks/ directory on the git server.

Please note that this script should be executable. You may need to add executable mod bits to post-receive by

chmod a+x hooks/post-receive

when you are in GIT_DIR.

If you use soft links, setting the original post-receive file once is sufficient.

Change the repository description

The repository name in the email subject is the first line of $GIT_DIR/description. Change the first line of the description file to you project’s name.

Change the config file

The sender’s email address, the mail list and the subject prefix is defined in GIT_DIR/config file. I like to edit this config file by hand which is as easy as using git config command.

Add these line to the config file:

   mailinglist = ""
   senderemail = ""

The email addressed in mailing list is separated by space.

The default subject prefix is [GIT]. You can change it to any string you like by adding hooks.emailprefix in the config file.

Now the email notification mechanism has been set up. You can change the script if more functions are needed. If you think your new version is great and would like to share it, send me a pull request.

Previous comments:

Dhivya S
– What exactly will be the senderemail ? I want whoever committed,
to be ‘sender’ of the email

Eric Zhiqiang Ma
That will be a nice feature. But I got no time to implement it at
current. There are some cases that should be took care of. For
1. The push contains multiple commits possibly by merging another
braunch from the others. Whoses email to use?
2. The committer may have no email set and a email address like
user@localhost will be provided. This may possibly lead the email
to be rejected by some email providers.
If you or someone else would lile to add the new feature, do send me a
pull request or a patch.

Eric Zhiqiang Ma
Updated script on Mar. 7, 2014: use mailx to send email by default which
uses the local message transfer agent service (like sendmail) to
send email. Just downloading the script and enable the message
transfer agent and it should work.

Sumer Joshi
I am using Gitlab with the post-receive script. However, whenever I
try to commit code, I’m getting this error message:
*** hooks.mailinglist is not set so no email will be sent
*** for refs/heads/master update
master -> master
error: unable to create directory for
error: Cannot lock the ref
I already set the hooks.mailinglist query in the config file of the
project. I was not sure how to go about fixing this issue.

Eric Zhiqiang Ma
I am not familiar wiht Gitlab. But please check whether Gitlab will
use the config file for configuration. It will be strange if it
does not.

finnaly someone get this work with that excelent code.
I’ve downloaded your script but I don’t know how to configure it.
I’m using Gitlab 6.4 and the Hooks path is on gitlab-shell/hooks.
Where do I can put the mailling address configs???
Have you tested it
with gitlab???
for my poor english

Zhiqiang (Eric) Ma
Hi Rafeta, this script is for the vanilla git instead of gitlab. You
may need to integrated it into the gitlab systems if you need. For
vanilla git, it is under the .config. But this may be different for
the gitlab.

which version of mailx are you using? I installed bsd-mailx on my
Ubuntu but it doesn’t have the -S option to specify the smtp

Zhiqiang Ma
Please find a discussion on the mailx client on Ubuntu

Paul Theodoropoulos
I’ve been tasked with implementing this on our local gitlab server
(v3.0.3). I’ve gone the the various configuration steps listed
above, and was just about to put the script into the git hooks dir –
but then I found that post-receive is currently a link
post-receive -> /home/git/.gitolite/hooks/common/post-receive. And that is a script
that part of the whole gitlab setup, containing the following:

#!/usr/bin/env bash
# This file was placed here by GitLab. It makes sure that your pushed commits
# will be processed properly.
read oldrev newrev ref
# For every branch or tag that was pushed, create a Resque job in redis.
“$pwd” | sed s/.git$//`
env -i redis-cli rpush
> /dev/null 2>&1

So, I guess my question would be, can I just *append* this post-receive
script to the bottom of that existing post-receive script? Or am I
on the wrong track here….

Zhiqiang Ma
Hi Paul,
At the first glance, it should not work after simply appending the
script to the bottom of your existing one.
For example,
Both scripts have:

read oldrev…

after one script reads the input from the STDIN, the other script will
fail to get it.
But after some minor changes, it should work.
For the example above, you may just keep (or save) these variables and
change the 2nd script to use these variables instead of read them
from the STDIN.
Beside of this, you may change other minor aspects as also.

Paul Theodoropoulos
Thank you Zhiqiang-Ma, I appreciate the quick response!

I am trying to configure smtp like that:

$email_tmp_file | mailx -v -s “$emailsubject” -s
smtp-use-starttls -s ssl-verify=ignore -S smtp-auth=login -s
smtp=smtp:// -s from=mail@domain -s
smtp-auth-user=mail@domain -s smtp-auth-password=QWERTY -s
ssl-verify=ignore -r $senderemail $recipients

But it doesn’t work at all. Where is my mistake?

Zhiqiang Ma
What output of the command do you get?

I’ve a remote bare repo at a windows client and when git tries to run the
script it says “mailx” command not found.
Help please!

Zhiqiang Ma
This means that ‘mailx’ is not installed on the system. If you are
using Fedora, try run ‘yum install mailx’ as root. On other
distros, please try to install the package the provides mailx.

liuzhong my
dear ma:
last week i installed
turnkey-gitlab-12.0-squeeze-x86.iso in my pc,this git system include
some useful tools ,such as gitlab ,webmin.and so on .and the git
server was well configured ,i could add and commit my code to the
server,now i want to automaly send emails to the users in my team ,i
read your article for long time ,but i can not do it ,please help
me, my thank you

Zhiqiang Ma
Hi liuzhong,
I am sorry that I am not familiar with turnkey-gitlab. But if you can
provide more details, I may help you to discuss / find possible
solutions. You are always welcome to ask questions in the forum
( ).

OK ,the turnkeylinux-gitlab include gitolite gitlab ,i downloaded the
iso and burn it to a cd ,it is easy to install,avoid use command
mode install a lot of packages and soft if my pc’s os is ubantu
or fedroa. it simple to use.but I donot know $GIT_DIR/description
mean , i can not find it in my pc..
and can you tell me your
mail in order to send same pic to you ?
at last please fogive
my Chinglish. hehe

Zhiqiang Ma
I see. GIT_DIR is the directory of the git repository on the git
server. This is a unclear part of this tutorial. I have updated
it. GIT_DIR/description is the file named description in the git
repository directory.
I prefer to discuss the question related to the posts here or in
the forum. But if you want to contact me by email, please find it

i am sorry ,mybe i have a mistake .i haved install a turnkeylinux
on my pc somedays ago,and i found it was a debian system a few
minutes ago! so i might set the post-recive files in a wrong
place!not in the responsity/project/hooks/ ,your script ” on
debian the hook is stored in # /usr/share/doc/git-core/contrib/hooks/post-receive-email:” ,and i will try another time. i will be carefull!

Zhiqiang Ma
This script should be okay with most Linux distros including Debian.
The script here is actually a modified version of the script
from the git-core or similar package. You can download the
script here into the hooks/ or save it to somewhere and share
the script by many repositories by soft links.

Is it possible to display the changes made
+ some text

some text
I tried adding the following to the config under [hooks]

git show
-C %s; echo

but this hasn’t done anything

Zhiqiang Ma
You may consider modifying the generate_update_branch_email() function
in the script.
For example: modifying the ‘git diff-tree –stat –summary
–find-copies-harder $oldrev..$newrev’ line with the one you want.

Steven Dobbelaere
I installed the script but when I execute it in the terminal I get
this error: “GIT_DIR not set”
Any idea on how I can set my GIT_DIR variable
I suspect I have to do it here:

# — Config
# Set GIT_DIR either from the working directory, or from the environment
# variable.
GIT_DIR=$(git rev-parse
–git-dir 2>/dev/null)
if [ -z "$GIT_DIR" ];
echo >&2 “fatal: post-receive: GIT_DIR not
exit 1

Zhiqiang Ma
Hi Steven,
This script should be run by the git server automatically. Just save a
copy in hooks/post-receive in the git directory on the server side.
It will be invoked automatically by git when you push to the

Akzhan Feel
free to use colored diffs with

Can somebody explain how to run this script from command line ?

Zhiqiang Ma
This script is designed to be automatically invoked by git rather than
for run from command line.
You may consider adapting it for command line use if you like. The
source code can be downloaded in the link in the post.

Sam change
sh to bash.
remove -r option
works fine then

Zhiqiang Ma
Hi Rainer,
You can find out the lines that have the msg_count and comment them out
to bypass these warnings (there are only several lines). It seems
the bash on your computer doesn’t support the ((msg_count+=1))
Nice to know that you find the script useful ;)

Rainer aaah,
thanks for the quick !
i managed to find the -S option and took it out. had to also remove -r
and now i’m happily sending mails, thanks!
still have ugly output, though, something is wrong around the msg_count
objects: 5, done.
Delta compression using up to 2 threads.
3 (delta 2), reused 0 (delta 0)
hooks/post-receive: 706:
msg_count+=1: not found
[: 706: ==: unexpected
hooks/post-receive: 706: msg_count+=1: not found
706: ==: unexpected operator
hooks/post-receive: 706:
msg_count+=1: not found
[: 706: ==: unexpected
hooks/post-receive: 706: msg_count+=1: not found
706: ==: unexpected operator
hooks/post-receive: 706:
msg_count+=1: not found
[: 706: ==: unexpected
hooks/post-receive: 706: msg_count+=1: not found
706: ==: unexpected operator
cat: /tmp/git-email-subject-10682:
No such file or directory

but things work! thanks!

Zhiqiang Ma
@Rainer It seems that you are using a distribution with old (not too old)
software. In RHEL/CentOS 5, the mailx version are very old and it
doesn’t support -S option. You can try to put these parameters
into the ~/.mailrc file.

Hi, cool script thanks!
Doesn’t work for me though, failing with the following issue:
git stuff
hooks/post-receive: 706: msg_count+=1: not
[: 706: ==: unexpected operator
hooks/post-receive: 706:
msg_count+=1: not found
[: 706: ==: unexpected
hooks/post-receive: 706: msg_count+=1: not found
706: ==: unexpected operator
hooks/post-receive: 706:
msg_count+=1: not found
[: 706: ==: unexpected
hooks/post-receive: 706: msg_count+=1: not found
706: ==: unexpected operator
hooks/post-receive: 706:
msg_count+=1: not found
[: 706: ==: unexpected operator
/tmp/git-email-subject-10489: No such file or directory
invalid option — ‘S’
usage: mailx [-eIinv] [-a header] [-b
bcc-addr] [-c cc-addr] [-s subject] to-addr …
sendmail-options …]
mailx [-eIiNnv] -f [name]
[-eIiNnv] [-u user]
I hate bash, can’t read it, sorry. otherwise i’d go hunting for
this bug myself!

About Eric Zhiqiang Ma

Eric Zhiqiang Ma is interested in system software for cloud computing, virtualization of large-scale distributed systems and etc. Also find Eric on Facebook, Twitter, LinkedIn and Google+. The views or opinions expressed here are solely Eric's own and do not necessarily represent those of any third parties.


  1. Hi,

    My post-receive-email scrip does not have the line to uncomment.
    # cat $email_tmp_file | mailx -S smtp=”smtp://” -s “$emailsubject” -r $senderemail $recipients
    I recently installed GIT on Ubuntu. Can you please update you tutorial for the lastest version of GIT?


Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Click to subscribe to Posts by Email if you have not.