NOTE: See 2 updates below.
A couple of weeks ago I switched jobs. We use Git for version control at my new workplace (I was using SVN at work up until now). I also have a few public repositories of my own on GitHub (and some private ones as well). We’re using a pretty advanced Continuous Integration and Deployment system developed in-house called Lifecycle, and on my first week – while still getting to know the entire system and code-base – I committed a change that broke the build. (Actually the change that broke the build wasn’t written by me, but by someone else who sent me a Git patch to continue his work, but let’s not play the blame game.)
It isn’t uncommon for commits to break the build, and when that happens the faulted developer gets notified of the problem by email and usually quickly fixes it. The problem was that I wasn’t notified of the error. A few hours later a colleague told me there was a problem with the commit and that he fixed it. While researching why I didn’t get the email notification, I discovered that the commit was signed with my personal email address instead of my work one, the build system didn’t expect that email address and thus didn’t notify me.
This is a very long introduction to the problem I discovered I had – the need to work with different email addresses for different Git repositories.
When first settings up Git on my machine I ran (like everyone does):
This resulted in the following in my global
Obviously the global user configuration wasn’t going to help me with my situation – I need to use different emails for the different environments. If I changed the email to my work one, I’ll commit to GitHub with that email address (and I don’t want that). Also, removing the email field completely from the global
.gitconfig file and committing would result in the following:
That is, my email would be saved as
orr@Orrs-MacBook-Pro.local and I’d have the above warning on every commit. Fortunately, Git allows you to add configuration for individual repositories. This would solve the problem – I’ll manually add the correct email to each repository locally:
But – and this is the main point of this post – this would require me to do it for every inited (new) or cloned repository. Every time. And cloning repositories is something I do on a daily basis, many times a day. Not only do we have dozens of repositories, I sometimes clone repos I already have locally just to try something and then discard it. I was worried that I would forget to set my email explicitly every time, and again won’t be notified of errors related to failing builds.
The solutions I found to this problem: using Git hooks. First I created a private hooks folder (which is also saved to my personal dot files repo):
~/.git/templates/hooks. Next, I made Git use that as the
templatedir by adding the following to
Lastly, I created a
pre-commit hook by saving the following to
And so now, whenever a new repository is created by running
$ git init or
$ git clone, the
pre-commit file is added to it’s local
.git/hooks folder. Then, when committed to, the repo runs the hook and fails the commit if an email isn’t configured for that repo. This also works for other Git clients and not just for command line commits (see below screenshot for Gitbox). But remember – the hook will only be added to future inited/cloned repos, not existing ones. You’ll need to manually add it to any existing repos if you want it to run when committing.
So this solves my problem. I don’t have
user.email configured globally, but on a per-repository basis. And in-case I forget to set it up for a new repo, I’m not able to commit to it and a friendly message reminds me to configure it and how to do it.
Do you have a better way to work around this problem? I’d love to hear from you.
UPDATE 1 (2014-04): It seems that Dan Aloni does indeed have an easier way that produces almost the exact same result:
@orrsella '[user] email = "(none)"' in the global gitconfig, achieves the same goal as the hook— Dan Aloni (@DanAloni) April 11, 2014
To recap his solution, add to
And once you try to commit, you’ll get the following error message:
UPDATE 2 (2016-08): Philip Seeger wrote in to say that using
email = "(none)" will no longer work. Well, it will, but it will actually use
(none) as the email address.
Instead – starting with Git 2.8 – you can run the following from the command line to get a per-repo email configured:
From GitHub’s blog post on the 2.8 release:
Now you can tell Git not to guess, but rather to insist that you set
user.emailexplicitly before it will let you commit.