1

I have a work computer where $HOME/.gitconfig has user.email to RotatingPieces@work.tld. My home computer has $HOME/.gitconfig has user.email to Rotating.P@SuperKawaiiAnimeWeb.net. And there is the virtual machine with R.Pieces@DogeMemes.net. And the laptop has... .

These e-mail addresses are correct for most of the repositories cloned on these machines. But sometimes I do mix up what I am doing on what machine. Doing work stuff at home and the other way around.

So when I do something in my public GitHub/BitBucket/GitLab/Whatever repository at I then commit as RotatingPieces@work.tld. Working from home creates commits as Rotating.P@SuperKawaiiAnimeWeb.net. Because of this I accidentally link these two e-mail addresses together. It happens by accident all the time.

Is there some way to stop this? What can I do to stop myself from leaking my e-mail addresses when working on the same repository on different machines?

Things that don't work:

  • Changing $HOME/.gitconfig files. These e-mail addresses are correct for most of the repositories cloned on these machines.
  • Using git commit --author=.... I would forget the --author option all the time.
  • Setting an e-mail address in .git/config of the cloned repository. This only works for this machine for this repository. I would have to remember that for every time I make a new clone of a repository. Too easy to forget.

The best solution would be a server-side or client-side commit hook that you can just commit into a repository which then is run by git. Or some hook or e-mail address filter I could activate in the GitHub web UI. However such a thing probably doesn't exist for obvious abuse reasons.

Anyone got any ideas for a solution?

RotatingPieces
  • 413
  • 2
  • 8

3 Answers3

6

I've had the same issue for a while: I want different email addresses to be used for work projects, open source projects, personal projects, and so on, and I want it to be set automatically based on folder structure rather than remembering to do it per repo.

This solution will automate the process of setting the email on a per-repo basis. One assumption I'll make is that you have divided your projects into folders based on owner (or rather, based on the email address you want to use). E.g.:

code/
  work/
    (All subfolders use work email.)
  open-source/
    (All subfolders use open source email.)
  personal/
    (All subfolders use personal email.)

According to the Git Docs, post-checkout hooks are run after a git clone command, so we can use a global post-checkout hook to set the email per-repo.

First, do:

git config --global init.templatedir '~/.git_template'

(From Git commit hooks - global settings.)

Then create that folder and a subfolder called hooks. Add the following script as ~/.git_template/hooks/post-checkout:

#!/bin/bash
# Automatically set Git config values from parent folders.

dir=$(pwd)
while [ "$dir" != "/" ]
do
  # First directory would be the new Git repo, so skip it.
  dir=$(dirname $dir)
  if [ -f $dir/.gitconfig ]
  then
    for config in $(git config --file $dir/.gitconfig --list)
    do
      var=$(echo $config | cut -d = -f 1)
      value=$(echo $config | cut -d = -f 2)
      actual=$(git config $var)
      if [ "$actual" != "$value" ]
      then
        git config $var $value
      fi
    done
  fi
done

(You can also find this script at my GitHub repo git-template.

Now, for each of the folders I mentioned, add a .gitconfig file with the appropriate email. Do e.g.:

git config --file /mnt/data/code/open-source/.gitconfig user.email "open-source@scott-weldon.com"

Now, as long as you git clone into the right folder, your repos will automatically have the correct email address set in the local config.

Bonus features:

  1. For those repos you have already cloned, you can just cd to the relevant Git directory and call ~/.git_template/hooks/post-checkout directly to update the email.

  2. You can add whatever config you want to the .gitconfig files, and those settings will also be added to the repo.

Known issues:

  1. Currently it searches the directories from pwd to /, when it should reverse the order. This shouldn't be hard to fix, so I'll add that to my solution at some point.

  2. The script will be executed after every checkout, not just after initial clone, so there may be a small performance penalty. However, the conditionals ensure that it won't set the value if it has already been set, or if no .gitconfig file is found.

  3. Due to #2, there isn't a way to override the settings with repo-specific values.

Scott Weldon
  • 9,673
  • 6
  • 48
  • 67
  • 1
    **+1** thanks a lot, this helped me solve my problem. I resolved the known issues and added a few more improvements [here](http://stackoverflow.com/a/40450106/5427663). There's probably more that could be done :) – TheOperator Nov 06 '16 at 13:57
  • @TheOperator: Cool, looks great! Mind if I update my script (here and on GitHub) with your improvements? – Scott Weldon Nov 07 '16 at 17:35
  • 1
    Yes, no worries, glad I could help! If you want, you could add a link to my answer in the other thread on GitHub :) – TheOperator Nov 09 '16 at 09:11
2

I think the best solution is what you've said in your third bullet (set author in local configuration in .git/config). This answer address the remaining problem, which is to remember to set this configuration after each new clone.

Assuming those repositories can be expressed by some pattern, the best idea I have is to have a global pre-push hook in each machine that:

  • Check if the remote URL (pre-push hook second parameter) matches the pattern of your public repos.
    • If they match: check if current author email from local configuration is the expected one.
      • If it is OK: continue push.
      • Else: abort push.
    • Else: continue push.
André Sassi
  • 1,076
  • 10
  • 15
  • Same thinking: enforce a self-discipline of validating all new commits before pushing them. Check that the commiter and author are a certain e-mail address. – Kaz Sep 28 '16 at 21:08
  • 1
    *“have a global pre-push hook”* – What do you mean with global hook? As far as I am aware, there is no mechanism for global hooks, you have to set them up per repository. – poke Sep 28 '16 at 21:15
  • @poke, _global_ is not the right word indeed, but it is common to put "global" hooks in the template directory (`git config --global init.templatedir`), so they get copied into every new repository. See: http://stackoverflow.com/questions/2293498/git-commit-hooks-global-settings – André Sassi Oct 01 '16 at 12:09
1

The problem is, even if you had a way to prevent you from using the wrong email address, how is that system supposed to know when you’re using the wrong author information? If you’re doing works stuff from home, how exactly should it know that this is work stuff so your usual home address is wrong? The same applies to the other direction.

The only solution is to remember it yourself, otherwise it just won’t work. So you should set the author information locally for each repository. You could also use hooks, but those also need to be set up individually for each repository, so you’re better off just changing the config (that’s much easier).

You could also set up a new shell alias which sets the HOME environment variable to somewhere else before running the real git command. That way you could switch between two environments depending on the command you run. You could even hide the default git one, so you have to choose explicitly.

Another thing you could do, is to simply clear the author information from your global .gitconfig. That way, Git will always warn you about it. But instead of setting it globally then, just set it individually for each repository. That’s a bit tedious, but at least you get forced to think about which identity you want to choose,

poke
  • 369,085
  • 72
  • 557
  • 602