Use a different user.email and user.name for Git config based upon remote clone URL
Asked Answered
B

4

58

I configure my global ~/.gitconfig properties user.name and user.email like this:

git config --global user.email "[email protected]" 
git config --global user.name "mkobit"

This is the default configuration I want for working on personal projects, open source stuff, etc.

When I am working on a project from a specific domain, a corporate domain for example, I am configuring it for each repository when I clone it so that it uses a different user.name/user.email:

git clone ssh://[email protected]:1234/groupA/projectA.git
cd projectA
git config user.email "[email protected]"
git config user.name "m.kobit"

One decent option would be to setup an alias for cloning these kinds of repositories:

git config --global alias.clonecorp 'clone \ 
        -c user.name="m.kobit" -c user.email="[email protected]"'
git clonecorp ssh://[email protected]:1234/groupA/projectA.git

Both of these can be error prone because they both depend on me being smart and following the right steps. Evidence shows that this is near-guaranteed for me to screw-up sometime.

Is there a way to configure Git such that repositories from a certain domain (the mycorp.com in this example) will be configured a certain way?

Braun answered 4/1, 2016 at 18:10 Comment(1)
I've been looking for exactly the same thing. Such a disappointment really. Especially if you maintain multiple copies of the same repos or delete/re-clone regularly in dev or auto build environments. Something similar to managing managing different ssh_ids would do.Apc
B
64

The release of Git 2.13 has introduced a feature called conditional includes. In 2.13 the only supported configuration is filesystem path. That is easy to use in this case because I am already separating them.

The example provided on the release notes is:

You can configure two conditional includes in your home directory's ~/.gitconfig file:

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

Now you can put whatever options you want into those files:

$ cat ~/.gitconfig-work
[user]
name = Serious Q. Programmer
email = [email protected]

$ cat ~/.gitconfig-play
[user]
name = Random J. Hacker
email = [email protected]

Old answer

In Git 2.8, a global configuration user.useconfigonly has been added that insists the user set their user.email and user.name are set before committing. Here is the relevant text from the linked blog post by Github:

But if, say, you want Git to use one email address for your open source projects and a different one for your work projects, you've undoubtedly made the mistake of committing to a new Git repository without having first set your email address in that repository. In this situation, Git emits a warning, but it creates the commit anyway, using an email address that it guesses from the local system hostname. If you're trying to do something as complicated as different addresses for different projects, this is almost certainly not what you want.

Now you can tell Git not to guess, but rather to insist that you set user.name and user.email explicitly before it will let you commit:

git config --global user.useconfigonly true

This doesn't solve the auto-config based on certain clone URLs, but does make the process a little bit less error prone by forcing configuration at the start.

Braun answered 29/3, 2016 at 23:32 Comment(3)
thank you! I want to add here, that it is very important to use trailing slashes in the condition: ~/work/.Colligate
Can you verify it's correctly setup by going to a repo in child folder and run git config user.name? I cannot get a values when I try to access it.Monotheism
Note, now even more keywords are supported, see also git-scm.com/docs/git-config#_conditional_includes for a complete list and additional info.Meditation
A
13

as of 2.36.0 git now supports this by remote url

~/.gitconfig file:

[includeIf "hasconfig:remote.*.url:[email protected]*/**"]
    path = .gitconfig-public
[includeIf "hasconfig:remote.*.url:[email protected]*/**"]
    path = .gitconfig-work

Then add your customization to above referenced configs.

Aquanaut answered 6/12, 2022 at 20:56 Comment(0)
S
10

I found myself in the same situation: Realizing that i used my corporate email for commits just right after pushing to non-corporate repositories... So i wrote a small git-hook which you might find useful as well: https://github.com/DrVanScott/git-clone-init

Based on a configurable pattern file it will initialize user.email and user.name on git clone.

Standoff answered 24/4, 2017 at 22:27 Comment(0)
T
2

When I am working on a project from a specific domain, a corporate domain for example, I am configuring it for each repository when I clone it

Make sure to use Git 2.22 (Q2 2019) if your condition include config IncludeIf uses a pattern:

See commit 19e7fda (26 Mar 2019) by Nguyễn Thái Ngọc Duy (pclouds).
(Merged by Junio C Hamano -- gitster -- in commit 078b254, 22 Apr 2019)

config: correct '**' matching in includeIf patterns

The current wildmatch() call for includeIf's gitdir pattern does not pass the WM_PATHNAME flag.
Without this flag, '*' is treated almost the same as '**' (because '*' also matches slashes) with one exception:

'/**/' can match a single slash.
The pattern 'foo/**/bar' matches 'foo/bar'.

But '/*/', which is essentially what wildmatch engine sees without WM_PATHNAME, has to match two slashes (and '*' matches nothing).
Which means 'foo/*/bar' cannot match 'foo/bar'.
It can only match 'foo//bar'.

The result of this is the current wildmatch() call works most of the time until the user depends on '/**/' matching no path component.
And also '*' matches slashes while it should not, but people probably haven't noticed this yet. The fix is straightforward.


With Git 2.36 (Q2 2022), you also have git config hasconfig:remote.*.url:.

Meaning, the conditional inclusion mechanism of configuration files using "[includeIf <condition>]" has learned to base its decision on the URL of the remote repository the repository interacts with.

; include only if a remote with the given URL exists (note
; that such a URL may be provided later in a file or in a
; file read after this file is read, as seen in this example)
[includeIf "hasconfig:remote.*.url:https://example.com/**"]
    path = foo.inc
[remote "origin"]
    url = https://example.com/git
Teeterboard answered 22/4, 2019 at 18:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.