Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save bgauduch/06a8c4ec2fec8fef6354afe94358c89e to your computer and use it in GitHub Desktop.
Save bgauduch/06a8c4ec2fec8fef6354afe94358c89e to your computer and use it in GitHub Desktop.
Git config with multiple identities and multiple repositories

Setup multiple git identities & git user informations

/!\ Be very carrefull in your setup : any misconfiguration make all the git config to fail silently ! Go trought this guide step by step and it should be fine 😉

Setup multiple git ssh identities for git

  • Generate your SSH keys as per your git provider documentation.

  • Add each public SSH keys to your git providers acounts.

  • In your ~/.ssh/config, set each ssh key for each repository as in this exemple:

      Host github.com
      	HostName github.com
      	User git
      	IdentityFile ~/.ssh/github_private_key
      	IdentitiesOnly=yes
      Host gitlab.com
      	Hostname gitlab.com
      	User git
      	IdentityFile ~/.ssh/gitlab_private_key
      	IdentitiesOnly=yes

Setup dynamic git user email & name depending on folder

/!\ Require git 2.13+ for conditional include support.

The idea here is to use a different git user name & email depending on the folder you are in.

  • In your ~/.gitconfig, remove the [user] block and add the following (adapt this exemple to your needs) :

      [includeIf "gitdir:~/code/personal/"]
      	path = .gitconfig-personal
      [includeIf "gitdir:~/code/professional/"]
      	path = .gitconfig-professional
  • In your ~/.gitconfig-personal, add your personnal user informations:

      [user]
      	email = user.personal@users.noreply.github.com     # note we use the noreply github mail
      	name = personal_username
  • In your ~/.gitconfig-professional, add your professional user informations:

      [user]
      	email = user.professional@dns.com
      	name = professional_username

Setup a GPG key

If you need to add a GPG key and bind it to a user to sign your commits, you can do so like this:

You should have GPG installed and configured like the GPG suite

  • Add the GPG key ID to your ~/.gitconfig-<PROFILE> config and enable commit signing:

    [user]
      email = your.mail@domain.com
      name = Your NAME
      signingkey = SIGNING_KEY_ID
    [commit]
      gpgsign = true
  • Make sure to register the right GPG binary in your ~/.gitconfig:

    [program]
      pgp = /path/to/your/gpg2/bin

Test your setup

  • Now each repository will use the custom user info setup depending on the top-level folder.

  • Check your settings are taken into account, for instance in ~/code/personal/ :

    $ cd ~/code/personal/
    $ git config --get user.email    	# should return user.personal@users.noreply.github.com as per the exemple
    $ git config --get user.name     	# should return personal_username as per the exemple
    $ git config --get user.signingkey	# should return the GPG key ID as configured for the user
  • Do the same for each folder you have setup.

  • You can also display and check the global git config: git config --list --global

    • Or just the local config for the repository folder you are in: git config --list
  • Done !

Roadmap

  • use git config commands instead of config file manual editions (editing config directly is kind of dangerous but is more understandable, maybe keep it like this ?)
@slmg
Copy link

slmg commented May 20, 2020

Thanks for the gist. To partially address your roadmap, here's how to deal with the includeIf section only using git config commands:

git config --file=.gitconfig-personal --add user.name personal_username
git config --file=.gitconfig-personal --add user.email user.personal@users.noreply.github.com

git config --global --add includeif.gitdir:~/code/personal/.path .gitconfig-personal

@bgauduch
Copy link
Author

bgauduch commented May 26, 2020

Thanks for the tip @slmg !

Copy link

ghost commented Oct 8, 2020

Thanks for the gist. To partially address your roadmap, here's how to deal with the includeIf section only using git config commands:

git config --file=.gitconfig-personal --add user.name personal_username
git config --file=.gitconfig-personal --add user.email user.personal@users.noreply.github.com

git config --global --add includeif.gitdir:~/code/personal/.path .gitconfig-personal

I dont see includeif as a option under git config --gloabl --add , am i missing something? running git 2.28.0

@slmg
Copy link

slmg commented Oct 8, 2020

It is shown under git config.

> git --version
git version 2.25.1

> git config --help | grep includeIf
       The include and includeIf sections allow you to include config directives from another source. These sections behave identically to each other with the exception
       that includeIf sections may be ignored if their condition does not evaluate to true; see "Conditional includes" below.
       You can include a config file from another by setting the special include.path (or includeIf.*.path) variable to the name of the file to be included. The
       You can include a config file from another conditionally by setting a includeIf.<condition>.path variable to the name of the file to be included.
           [includeIf "gitdir:/path/to/foo/.git"]
           [includeIf "gitdir:/path/to/group/"]
           [includeIf "gitdir:~/to/group/"]
           [includeIf "gitdir:/path/to/group/"]
           [includeIf "onbranch:foo-branch"]

@slmingol
Copy link

slmingol commented Dec 6, 2020

Keep in mind that every time you run git config --file=.gitconfig-personal --add user.name or whatever git config cmd it'll keep adding entries to the specified file. It's likely better to use --replace-all.

@offwork
Copy link

offwork commented Dec 6, 2020

I repeated the steps over and over but the name and mail are not recognized by git. I had already tried something similar to this before but failed. I can try if I see something different.

@igorbrites
Copy link

I repeated the steps over and over but the name and mail are not recognized by git. I had already tried something similar to this before but failed. I can try if I see something different.

I was having the same problem, but I realised that the path without the trailing / does not work. The commands from @slmg saved the day! Thanks guys!

@YaoC
Copy link

YaoC commented Jul 9, 2021

I repeated the steps over and over but the name and mail are not recognized by git. I had already tried something similar to this before but failed. I can try if I see something different.

Are you trying it in a git repo, it doesn't work if the working directory is not a git repo. See this.

@Vrixyz
Copy link

Vrixyz commented Sep 2, 2021

On windows I had to include the case insensitive postfix /i [includeIf "gitdir/i:~/Documents/work/"]

Or maybe I should have put every letters in small letters despite windows showing capitals..? either way it's working now, thanks !

@shelllee
Copy link

Is there a way we could set .gitconfig for per domain such as github.com and gitlab.com?

@bgauduch
Copy link
Author

@shelllee not that I'm aware of !

Not sure what you are trying to do here, but it seem's to be the use case of this gist : separate ssh config depending on the host as described here

Be aware that Git config is independent from your ssh config, which git uses to connect to the Git hosts !

@shelllee
Copy link

@shelllee not that I'm aware of !

Not sure what you are trying to do here, but it seem's to be the use case of this gist : separate ssh config depending on the host as described here

Be aware that Git config is independent from your ssh config, which git uses to connect to the Git hosts !

I found this: https://github.com/DrVanScott/git-clone-init, which automatic setup of user identity on git clone by post-checkout hook.

@bgauduch
Copy link
Author

@shelllee not that I'm aware of !
Not sure what you are trying to do here, but it seem's to be the use case of this gist : separate ssh config depending on the host as described here
Be aware that Git config is independent from your ssh config, which git uses to connect to the Git hosts !

I found this: https://github.com/DrVanScott/git-clone-init, which automatic setup of user identity on git clone by post-checkout hook.

Well okay, I think I initially misunderstood 😅

but I really don't see the point adding another external tool since you can configure the exact same behavior with git includeif instruction as described here.

Up to you 😉

@tw-yshuang
Copy link

tw-yshuang commented Dec 14, 2021

I create a CLI command to handle this!
Checkout my repo~~
This repo uses ssh-agent to switch your ssh account.

Git_SSH-Account_Switch

A CLI tool can switch an ssh account to your current shell. You will easily switch to your git account & ssh key when using the server, and using your account to manipulate the project on the server.

Installation

$ bash ./setup.sh

it will add some code in your profile & $logout_profile, and setup git-acc & .gitacc on the $HOME.
file:

git-acc.sh -> $HOME/.git-acc, git-acc function.
.gitacc -> $HOME/.gitacc, save info. that regist on git-acc.

Control

        +---------------+
        |    git-acc    |
        +---------------+

SYNOPSIS

  git-acc [account]|[option]

OPTIONS

  [account]               use which accounts on this shell, type the account name that you register.
  -h, --help              print help information.
  -add, --add_account     build git_account info. & ssh-key.
      -t, --type          ssh-key types, follow `ssh-keygen` rule, 
                          types: dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa(default)
  -rm, --remove_account   remove git_account info. & ssh-key from this device
  -out, --logout          logout your current ssh-acc.


EXAMPLES

  $ git-acc tw-yshuang

@cbbdev
Copy link

cbbdev commented Mar 9, 2022

Hello, sorry to be a little late to the party but after running into a similar issue and finding this solution, it inspired a more dynamic way to include the custom config files. When having multiple projects at the same time, the "IncludeIf..." can became too verbose and may also lead to confusion if some of those configs contain similar settings (or names). In order to alleviate this, we still placed the custom ".gitconfig" file inside each project, but in the global ".gitconfig" (in windows should be under C:\Users$user) and add an alias there like this:
[alias] set-config = !git config --global include.path $(git rev-parse --show-toplevel)/.gitconfig
We named it "set-config" but of course you can change that to your liking. after that, just do:

  • git init (to reload)
  • git set-config
    This will automatically set the path to the current project being used, meaning that it can be used without limitations or having to manually add multiple "if" statements.
    Thanks to @bgauduch for this post and hope this helps!

@Xat59
Copy link

Xat59 commented Jun 22, 2022

For your information you must now specify the .git folder in the gitdir such as :

[includeIf "gitdir:~/code/personal/repo1/.git"]

Another useful tip, you can use globbing on parent directory to detect new repos without editing your git-config file :

[includeIf "gitdir:~/code/personal/**/.git"]

@825i
Copy link

825i commented Nov 22, 2023

For your information you must now specify the .git folder in the gitdir such as :

[includeIf "gitdir:~/code/personal/repo1/.git"]

Another useful tip, you can use globbing on parent directory to detect new repos without editing your git-config file :

[includeIf "gitdir:~/code/personal/**/.git"]

Thanks! I will pulling my hair out wondering why it didn't work. Also thanks for the globbing advice because that would have been my next question!

@MGREMY
Copy link

MGREMY commented Apr 24, 2024

Thanks man ! Note that git config --get xxxx.xxxx works only when you are inside a repository, otherwise it doesn't show anything 👍

@offwork
Copy link

offwork commented Apr 25, 2024

Hi there!

Simple solution for Mac and fish-shell users like me:
After the ssh keys are created, run the agent command for fish:

eval $(ssh-agent -c)

and then install the ssh keys on the mac keychain:
ssh-add --apple-load-keychain -A ~/.ssh/github_personal
ssh-add --apple-load-keychain -A ~/.ssh/bitbucket_work

and then install the ssh keys on the mac keychain.

Screenshot 2024-04-25 at 15 42 29

@shellheim
Copy link

I originally had a problem with using two hosts and when I signed my commits, the signature would be invalid on the web UI because my global git email was set to github only. What I wanted to do was figure out a way to automatically change the user.email variable to the respective noreply addresses.

That can be done using the IncludeIf directive, just have to use the right globbing pattern.
My config is like this :

[includeIf "hasconfig:remote.*.url:**github.com:*/*.git"]
	path = github_config 

[includeIf "hasconfig:remote.*.url:**codeberg.org:*/*.git"]
	path = codeberg_config

Where github_config and codeberg_config are files with their respective emails. The globbing pattern is just :

**example.com:*/*.git

for ssh remote urls.

@amaury-d
Copy link

amaury-d commented Sep 2, 2024

@shellheim nice tip 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment