1

Most of my Git repo can be classified as github repo or company repo, both have a considerable number. And obviously I need to use different email address for this two different kind of repos.

I read the git manual and searched a lot, and find there are only two ways to config the user email: globally and per-repo.

So, If I want to use different email address for this two kind of repos, I have two choice:

  1. Set the global email address to one of them, and carefully set per-repo email address for other repos.
  2. Always set email address per-repo, and force it via git config --global user.useConfigOnly true

Neither is satisfactory :(

The ideal solution maybe looks like url.insteadOf

[url "https://github"]
  insteadOf = git://github
  user_email = xxx@gmail.com

So is there any solution for this case? maybe via git hook or some other magic?

Notice: my question is very different from this one since I need Automatic Switching not just add per-repo configs one by one.

luochen1990
  • 3,689
  • 1
  • 22
  • 37
  • Possible duplicate of [Can I specify multiple users for myself in .gitconfig?](https://stackoverflow.com/questions/4220416/can-i-specify-multiple-users-for-myself-in-gitconfig) – phd May 13 '19 at 15:44
  • Especially see the answer https://stackoverflow.com/a/43654115/7976758 about conditional includes. There is also an interesting idea with a pre-commit hook: https://stackoverflow.com/a/23107012/7976758. – phd May 13 '19 at 15:45
  • @phd they are different since I'm asking for an automatic solution – luochen1990 May 14 '19 at 02:13
  • 1
    Conditional includes are completely automatic and future-proof. – phd May 14 '19 at 10:31
  • @phd Thanks very much, Conditional Includes is just what I want, but I find that the related answer is not highly voted in the above question you have mentioned, I think it fits this question much better. I think we should keep this question since it have a very different emphases and can help people find what they want :) – luochen1990 May 14 '19 at 12:11

3 Answers3

2

The new git feature (from git 2.13) named Conditional Includes is the key. Following is my solution:

$ cat ~/.gitconfig | head -5

[includeIf "gitdir:~/gh/**"]
    path = ~/.github.gitconfig

[includeIf "gitdir:~/work/**"]
    path = ~/.work.gitconfig

$ cat ~/.github.gitconfig

[user]
    name = MyName
    email = my-personal-emal@gmail.com

$ cat ~/.work.gitconfig

[user]
    name = MyName
    email = my-company-email@company.com

[init]
    templatedir = ~/work/.gittemplates

This solution not strictly follows what I want (auto switch by repo url of remote origin), but it works well if you did clone your repos into different root directories.

And If you want to force yourself to set the email outside the repo root directories, you can just set useConfigOnly = true in the global config and cover them to false in the conditional included files.

Hope this can help you :)

luochen1990
  • 3,689
  • 1
  • 22
  • 37
  • This is great. I first defined a `[user]` which is applied by default, followed by an `[includeIf "gitdir:**/CompanyName*/**"]` which kicks in when needed. Perfect! – AgentRev Nov 10 '22 at 21:14
2

git v2.36 added the hasconfig:remote.*.url: option to includeIf.

Add something like this at the bottom of your global .gitconfig:

# Default user
[user]
    name = Real Name
    email = realname@yourmail.com

# Work user override
[includeIf "hasconfig:remote.*.url:**/CompanyName/**"]
    path = ~/.work.gitconfig

# Anonymous user override
[includeIf "hasconfig:remote.*.url:**/Anon1234/**"]
    path = ~/.anon.gitconfig

.work.gitconfig in home folder:

[user]
    name = Real Name
    email = realname@company.com

.anon.gitconfig in home folder:

[user]
    name = Anon1234
    email = anon1234@yourmail.com
AgentRev
  • 749
  • 1
  • 8
  • 20
1

I had to deal with the same issue and found a tricky way. Use it carefuly.

All the trick is about this command: HOME=$var git <anything>.

HOME=$var switch your home directory for the command. By default Git look for ~/.gitconfig, so controlling $HOME is controlling ~/.gitconfig.

Also, Git config file allow to include other Git config files, to "import" it:

[include]
    path = /path/to/.gitconfig

That means you can set up a "default" ~/.gitconfig with aliases and default email and add "levels" ~/foo/.gitconfig, ~/foo/bar/.gitconfig, etc and manage "dependencies".


Here is my script, please refere to the recursive-gitconfig repository, but for the sake of SO I prefere include it here.

# Look for closest .gitconfig file in parent directories
# This file will be used as main .gitconfig file.
function __recursive_gitconfig_git {
    gitconfig_file=$(__recursive_gitconfig_closest)
    if [ "$gitconfig_file" != '' ]; then
        home="$(dirname $gitconfig_file)/"
        HOME=$home "$(which git)" "$@"
    else
        "$(which git)" "$@"
    fi
}

# Look for closest .gitconfig file in parents directories
function __recursive_gitconfig_closest {
    slashes=${PWD//[^\/]/}
    directory="$PWD"
    for (( n=${#slashes}; n>0; --n ))
    do
        test -e "$directory/.gitconfig" && echo "$directory/.gitconfig" && return
        directory="$directory/.."
    done
}


alias git='__recursive_gitconfig_git'

It basically find the "nearest" Git config file decending from ./ to ~/ and set $HOME to it's directory.

More doc here.


With that you should be able to manage several identities, ssh keys, etc depending of your current location, so, depending of the repo you are working on.

Arount
  • 9,853
  • 1
  • 30
  • 43