13

Following this SO post and the linked guidance, I set up a condition configuration like the following...

$ cat ~/.gitconfig 
[user]
    name = Random J. Hacker
    email = RandomJ@hack.er
[includeIf "gitdir:~/work/*"]
    path = ~/work/.gitconfig

$ cat ~/work/.gitconfig 
[user]
    name = Serious Q. Programmer
    email = serious.q@programmer.biz

In this way, all of the repositories I do clone when I'm working for Programmer Co. get my @programmer.biz work email address assigned as the default --author credential; and every random repo I clone to my desktop or /tmp or ~/.vscode or wherever gets my super legit @hack.er credential assigned as the author.

Unfortunately, I noticed the following behaviour...

$ git clone git@github.com:programmerbiz/repo.git
$ cd repo/
$ git config --list | grep user
user.name=Random J. Hacker
user.email=RandomJ@hack.er
user.name=Serious Q. Programmer
user.email=serious.q@programmer.biz

Oh no! My @hack.er user is picked up by the business repo!

I would like to automatically configure one and only one default [user] for all repos without resorting to a bash script. Is there an includeIf.Not operator, [else] block syntax, or similar that I can use in ~/.gitconfig to achieve this? The conditional includes documentation does not appear to support this use case.

Peter Vandivier
  • 606
  • 1
  • 9
  • 31
  • 2
    How about having a normal `[user]` section with the else-part, and then an includeif section with the specific part, this seems to work on Windows at least. – Lasse V. Karlsen Jul 30 '19 at 16:27
  • Did you try `includeIf` as described here? https://stackoverflow.com/a/46239540/3216427 – joanis Jul 30 '19 at 18:05
  • Can't you define it globally to `@fun.times` and follow that by the `includeIf` which overrides the name and email only when it applies? The "else" would be implicit in the preceding global settings. Actually, that's exactly what @Lasse suggested above. – joanis Jul 30 '19 at 19:14
  • Ah OK. I get it now. It would be worth editing the question to mention it there, since it wasn't clear you had tried that seemingly obvious solution and what was wrong with it. Interesting question, I hope someone provides a working answer. – joanis Jul 30 '19 at 19:23
  • Next question: when I reproduced your scenario, I also got the double creds in `git config --list`, but when I did `git commit` it used the right credentials. It looks to me like the later occurrence overrides the earlier one, even if `git config --list` still lists them both. – joanis Jul 30 '19 at 20:10
  • @joanis `git log` shows the last author listed on very cursory testing for me as well. Given the existence of multi-author commits [1](https://help.github.com/en/articles/creating-a-commit-with-multiple-authors) [2](https://stackoverflow.com/questions/7442112), I'd rather not have the cached credential "_just hanging around_" and _hope_ that it doesn't get picked up by some process that shouldn't see it. – Peter Vandivier Jul 30 '19 at 20:14
  • Well, the problem is that there is no "else" or "ifnot", you have includeIf and that's it. – Lasse V. Karlsen Jul 30 '19 at 20:46
  • 1
    @PeterVandivier Try `git log --format=raw` to convince yourself it's safe: according to `git log --help`, "The raw format shows the entire commit exactly as stored in the commit object." On my end with your scenario reproduced, I only see the "work" identity in my test commit in the `work` folder. – joanis Jul 31 '19 at 13:36

3 Answers3

4

What is the output of git config --list --show-origin | grep user?
You should see where the configurations are defined.

I would like to automatically configure one and only one default [user] for all repos

In this case, remove all the above users configuration and set a single entry in your global config

# Use the `--global` to store it under your user account configuration
# and it will be used as the default for all of your projects unless you
# define it in your local `.git/config`

git config --global user.name <....>
git config --global user.email <....>

---- 
# For specific project use the `--local` flag (will be stored in your `.git/config`

git config --local user.name <....>
git config --local user.email <....>
CodeWizard
  • 128,036
  • 21
  • 144
  • 167
  • 1
    Using `git config --local` per-repo is rather what I was trying to avoid with the conditional global config. +1 however - I never knew about the `--show-origin` option. Using this flag, it actually looks like locally setting a `[user]` doesn't "overwrite" the default global config setting as I was hoping/expecting. Perhaps I need to read up a bit on attribute precedence for git repos. – Peter Vandivier Jul 31 '19 at 07:18
2

The problem is the way you are specifying the gitdir, I had the same issue, and the path (full or relative) should end with a slash.

You have gitdir:~/work/*

This is how it should look:

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

You can then go to the directory and check if it worked:

cd ~/work
git config --list | grep user

Cheers!

Willemoes
  • 5,752
  • 3
  • 30
  • 27
1

If you have the luxury of being able to organize all of your repos into one or more parent folders, then the issue is sidestepped since you can use a separate includeIf directive for each directory. That may work well for some people, but after initially trying that I eventually determined I would still prefer to have a default user and email for the entire system for any repo that is not in a specific parent directory, mainly because I tend to create mini repos in various locations on my machine. I wish this weren't the case, but currently:

I believe the best answer to your question is to leave it as is.

After some testing I've determined that having duplicate entries in Git configs doesn't cause any issues, and it appears that the last one wins. So as long as you put the default before the includeIf directives, when you're inside of a repo that matches the includeIf, even though you can see duplicate entries, only the last user and email will be used. This exactly accomplishes your goal, and only looks weird if you look.

Side note: the comments to the question appear to confirm this answer. In another comment though, you mentioned you were concerned that perhaps some process might use the duplicate author data for automating Co-authored-by: text in a commit message. IMHO you don't have to worry about that since it wouldn't make sense to look at the config of the machine creating the commit to determine that information. Co-author info pretty much must be manual, since Git can't know which commits would require it, or who you're collaborating with when you make a commit.

TTT
  • 22,611
  • 8
  • 63
  • 69