630

.gitconfig is usually stored in the user.home directory.

I use a different identity to work on projects for Company A and something else for Company B (primarily the name / email). How can I have two different Git configurations so that my check-ins don't go with the name / email?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
priya
  • 24,861
  • 26
  • 62
  • 81

14 Answers14

568

As of git version 2.13, git supports conditional configuration includes. In this example we clone Company A's repos in ~/company_a directory, and Company B's repos in ~/company_b.

At the end of your .gitconfig file, you can put something like this:

[includeIf "gitdir:~/company_a/"]
  path = .gitconfig-company_a
[includeIf "gitdir:~/company_b/"]
  path = .gitconfig-company_b

Example contents of .gitconfig-company_a (the [core] section can be omitted if the global ssh key can be used):

[user]
name = John Smith
email = john.smith@companya.net

[core]
sshCommand = ssh -i ~/.ssh/id_rsa_companya

Example contents of .gitconfig-company_b:

[user]
name = John Smith
email = js@companyb.com

[core]
sshCommand = ssh -i ~/.ssh/id_rsa_companyb
Flimm
  • 136,138
  • 45
  • 251
  • 267
crea1
  • 11,077
  • 3
  • 36
  • 46
  • 2
    It's great to see this has been added in version 2.13. I have been using https://github.com/bddenhartog/git-profiles for awhile, but couldn't get it to work with Tower. – adrum May 11 '17 at 19:02
  • 5
    includeIf is a little finicky, see: https://stackoverflow.com/questions/43919191/git-2-13-conditional-config-on-windows/44117413#44117413 – rouble May 22 '17 at 18:15
  • The documentation page you linked to doesn't mention this... in fact, searching for includeIf doesn't yield any result in the documentation – Thomas Levesque Oct 13 '17 at 13:23
  • 1
    @ThomasLevesque That's weird. I'm sure it said something about it before. You can find it in the changelog https://github.com/git/git/blob/master/Documentation/RelNotes/2.13.0.txt and also over at https://www.kernel.org/pub/software/scm/git/docs/git-config.html – crea1 Oct 16 '17 at 05:33
  • 2
    @JosephLust you need to install **git >= 2.13** *(Ubuntu 16.04 has git 2.7)*. Get the latest version of git via [Git PPA](https://launchpad.net/~git-core/+archive/ubuntu/ppa) and it will work :) – Cas Dec 09 '17 at 21:49
  • 6
    I just want to note that the `gitdir` folder must end with slash (`/`), otherwise `git` would ignore the `ignoreIf` config (actually, it would result in `false`). – tukusejssirs Dec 21 '19 at 17:32
  • 20
    Do note that the directory-specific configuration will only take effect inside a repository as a subdirectory (example `~/company_a/repo_1`). If you're in a non-repository directory like `~/company_a` and run `git config user.email` you'll still get the global email address. **Don't let that confuse you.** – ADTC Jun 17 '21 at 03:57
  • @crea1 is there a way to register passwords based on different folders using this method? Currently, with this setup, we still have to type our username and password on the terminal before pushing. I was wondering if there is a way to store the passwords with a credential manager (like libsecret). Solutions on the web are either for a single account or for individual repos (and not for something in between ie. for multiple accounts). Check this out https://stackoverflow.com/questions/68577959/how-to-store-credentials-for-multiple-github-accounts-not-repos-using-libsecre – theairbend3r Jul 31 '21 at 10:58
  • 1
    it's also worth mentioning that if one wants to preserve some defaults in the `.gitconfig` and only apply, let's say a different email for that particular dir, the includeif clause should be added at the end of it. If added at the beginning and the same properties are specified afterwards, they will be overridden and won't have any effect. – dimisjim Aug 02 '22 at 09:08
548

There are 3 levels of git config; project, global and system.

  • project: Project configs are only available for the current project and stored in .git/config in the project's directory.
  • global: Global configs are available for all projects for the current user and stored in ~/.gitconfig.
  • system: System configs are available for all the users/projects and stored in /etc/gitconfig.

Create a project specific config, you have to execute this under the project's directory:

$ git config user.name "John Doe" 

Create a global config:

$ git config --global user.name "John Doe"

Create a system config:

$ git config --system user.name "John Doe" 

And as you may guess, project overrides global and global overrides system.

Note: Project configs are local to just one particular copy/clone of this particular repo, and need to be reapplied if the repo is recloned clean from the remote. It changes a local file that is not sent to the remote with a commit/push.

LightCC
  • 9,804
  • 5
  • 52
  • 92
teymourlouie
  • 6,645
  • 2
  • 21
  • 13
  • 152
    Is there is a possibility to make some "directory" config? I do some job at home and got folders with work projects and my own. So I got folders ~/job and ~/my with git repos and want different configs for projects under them. E.g. job/project1 has config from job/.gitconfig. – MainActivity Apr 08 '16 at 18:41
  • 7
    @Serge did you ever figure out if it was possible to create a directory level config? I have the same issue right now. – Questioning Jun 13 '18 at 14:11
  • 2
    No I set overall system config to personal data and make bash script to set job data to certain project configs in one command. – MainActivity Jun 14 '18 at 14:28
  • 3
    As an addendum: just `git config user.name` or `git config user.email` will show you the name or email Git will use for the current respository. – Abhishek Divekar Mar 11 '19 at 08:24
  • 1
    I ended up doing this **for zsh**: https://gist.github.com/pgarciacamou/3b67320e2940c8d7fa3d7bbd73873106, I hope this helps somebody. – pgarciacamou Apr 28 '19 at 23:53
  • I believe `--local` replaces `--project` with the newer version of git? – sachinruk Aug 07 '19 at 00:22
  • @Serge, Questioning, did you see Eugene's answer above about git config includes? I believe this provides your solution. https://git-scm.com/docs/git-config#_includes – timblaktu Apr 08 '20 at 22:07
  • 1
    In addition to script for setting per-project config it is useful to have common username and email _not set_. This causes credentials to be prompted before first commit and you will be aware of correct setting instead of automatic that can cause mistakes. Issue is resolved with such approach for me. – MainActivity Apr 10 '20 at 08:30
  • 1
    @timblaktu but even with eugene's approach, you can only include config's per each project right? so for ~/job/project1 i have to run git config command and also ~/job/project2 I have to do the same. It would be better to do this once for all subfolder of ~/job so when I create a new project under job directory it will have that config by default – theprogrammer Apr 20 '20 at 20:44
  • 6
    @theprogrammer Did you guys ever try this out? It works for me. https://stackoverflow.com/a/43884702/5383834 – Wit Apr 29 '20 at 10:56
380

The .git/config file in a particular clone of a repository is local to that clone. Any settings placed there will only affect actions for that particular project.

(By default, git config modifies .git/config, not ~/.gitconfig - only with --global does it modify the latter.)

Amber
  • 507,862
  • 82
  • 626
  • 550
98

Thanks @crea1

A small variant:

As it is written on https://git-scm.com/docs/git-config#_includes:

If the pattern ends with /, ** will be automatically added. For example, the pattern foo/ becomes foo/**. In other words, it matches foo and everything inside, recursively.

So I use in my case,
~/.gitconfig :

[user] # as default, personal needs
    email = myalias@personal-domain.fr
    name = bcag2
[includeIf "gitdir:~/workspace/"] # job needs, like workspace/* so all included projects
    path = .gitconfig-job

# all others section: core, alias, log…

So If the project directory is in my ~/wokspace/, default user settings is replace with
~/.gitconfig-job :

[user]
name = John Smith
email = js@company.com
bcag2
  • 1,988
  • 1
  • 17
  • 31
  • Done this , now correct user name and email is set in different directories . When I do git config user.name / git config user.email I get correct details . But when I comment in personal repo , it always picks up global official username email – Bhupendra Oct 09 '19 at 06:33
  • @Bhupendra In my sample, .gitconfig and .gitconfig-job is in my home, not in project directories. Do you need more than two ? Have you create a .gitconfig-alternativ in your home directory, as my .gitconfig-job in my sample, with 3 lines. – bcag2 Oct 11 '19 at 06:42
  • @bcag2 I too followed the same example given above. I have 2 configs work the default one and personal similar to gitconfig-job. When I am in the personal directory, on git config user.name gives me correct name but for pushing the commit it takes the default one whereas I need the personal one. – swapnil2993 Jan 13 '20 at 16:54
  • @swapnil2993 first I think at path issue but if `git config user.name` return correct one, it should be ok. Are you under GNU/Linux or other OS? – bcag2 Jan 14 '20 at 07:35
  • @bcag2 Resolved the issue. Just corrected the path. But git config user.name returning correct value was weird. Thanks for the answer. – swapnil2993 Jan 15 '20 at 08:50
  • 1
    A note on this: If you need the file path to be case-insensitive replace `gitdir` with `gitdir/i`. Example: `[includeIf "gitdir/i:~/workspace/"]` – mskolnick Sep 25 '21 at 13:43
31

To be explicit, you can also use --local to use current repository config file:

git config --local user.name "John Doe" 

Or as @SherylHohman mentioned, use the following to open the local file in your editor:

git config --local --edit
mim
  • 1,301
  • 14
  • 24
  • 1
    and if you do `git config --local --edit` it will create/open the local file for you so you can edit directly. This was important for me because for some unknown reason neither VSCode, nor my XYPlorer file explorer would show my .git folder (though other dot files and system files show, and traditionally my file explorer does show my .git folder if I want it to.) For my case it was much easier to edit the file directly than add several options via the command line. – SherylHohman Dec 19 '21 at 19:56
19

Another way is to use direnv and to separate config files per directory. For example:

.
├── companyA
│  ├── .envrc
│  └── .gitconfig
├── companyB
│  ├── .envrc
│  └── .gitconfig
└── personal
   ├── .envrc
   └── .gitconfig

Each .envrc should contain something like this:

export GIT_CONFIG_GLOBAL=$(pwd)/.gitconfig

And .gitconfig is usual gitconfig with desired values.

This is what I actually have in the custom .gitconfig files:

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

[include]
    path = ~/.gitconfig

Here only user.email is overwritten, the rest configuration is taken from the default ~/.gitconfig.

German Lashevich
  • 2,193
  • 27
  • 38
16

I am doing this for my email in the following way:

git config --global alias.hobbyprofile 'config user.email "me@example.com"'

Then when I clone a new work project, I have only to run git hobbyprofile and it will be configured to use that email.

ivand58
  • 773
  • 6
  • 19
13

You can also point the environment variable GIT_CONFIG to a file that git config should use. With GIT_CONFIG=~/.gitconfig-A git config key value the specified file gets manipulated.

Stefan Näwe
  • 3,040
  • 1
  • 18
  • 19
  • 3
    Cool; with a bit of clever shell magic this can be used to set things up so git picks the first .gitconfig it finds when traversing the dir tree up above current repo. Thanks! – ecmanaut Mar 20 '13 at 17:30
  • 1
    Do you have a link to this shell magic that does this? Sounds useful! – pchiusano Dec 05 '13 at 19:46
  • 1
    @pchiusano here's a rudimentary version of it in fish https://github.com/CtrlC-Root/dotfiles/blob/master/.config/fish/config.fish#L14 – ctrlc-root Mar 10 '15 at 20:51
  • it only affect git config command now https://github.com/git/git/blob/master/Documentation/RelNotes/1.6.0.txt#L41 – foray1010 Jan 23 '20 at 15:44
  • for *Git v2.32.0* and newer, use `GIT_CONFIG_GLOBAL`. Example: `GIT_CONFIG_GLOBAL=~/.gitconfig-another git commit -m "foo"` – Abdull Aug 30 '23 at 09:09
4

You can customize a project's Git config by changing the repository specific configuration file (i.e. /path/to/repo/.git/config). BTW, git config writes to this file by default:

cd /path/to/repo
git config user.name 'John Doe'  # sets user.name locally for the repo

I prefer to create separate profiles for different projects (e.g. in ~/.gitconfig.d/) and then include them in the repository's config file:

cd /path/to/repo
git config include.path '~/.gitconfig.d/myproject.conf'

This works well if you need to use the same set of options in multiple repos that belong to a single project. You can also set up shell aliases or a custom Git command to manipulate the profiles.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
2

Follow the Steps:

  1. Find .gitconfig from the system

    File Location For Windows : "C:\Users${USER_NAME}.gitconfig"

    File Location For Linux : "/usr/local/git/etc/gitconfig"

  2. Open .gitconfig file and add below lines as per your condition

     [includeIf "gitdir:D:\ORG-A-PROJECTS\"]
    
     [user]
    
         name = John Smith
    
         email = js@organizationx.com [includeIf "gitdir:~/organization_b/"]
    
     [user]
    
         name = John Doe
    
         email = jd@organizationy.com
    
Tejas Savaliya
  • 572
  • 7
  • 8
  • wrong file location for Linux, especially for ubuntu 18 or 20, there is no git folder in /usr/local/ ! – bcag2 Mar 12 '21 at 07:22
2

Add multiple SSH keys with Github config

After 13 August 2021, git is not supporting HTTPs authentication method, so I believe this answer needs to be updated.

Follow the steps below:

  • remove all SSH keys (public & private) for Git stored in directory ~/.ssh/.
  • create new SSH keys:
ssh-keygen -t rsa -b 4096 -C "account1@gmail.com"
ssh-keygen -t rsa -b 4096 -C "account2@gmail.com"

When asked for file names, give default ~/.ssh/id_rsa for account1 and ~/.ssh/id_rsa_acc2 for account2 respectively.

  • Start ssh-agent and add private keys for account1 and account2:
eval `ssh-agent`
ssh-add -k ~/.ssh/id_rsa
ssh-add -k ~/.ssh/id_rsa_acc2

confirm keys are added by command ssh-add -l

  • copy public keys for account1 and account2 and add it to your github account. command: cat ~/.ssh/id_rsa.pub | pbcopy (to check whether its copied: pbpaste

  • set account1's username and user email as global GitHub config:

git config --global user.name "acc1_username"
git config --global user.email "account1@gmail.com"
  • create ~/.ssh/config file with following configuration:
# account1 github
Host github.com
HostName github.com
User git
AddKeysToAgent yes
IdentityFile ~/.ssh/id_rsa

# account2 github
Host github.com-acc2
HostName github.com
User git
AddKeysToAgent yes
IdentityFile ~/.ssh/id_rsa_acc2
  • To set GitHub account2 for a project set username & email on project level in the project root directory:
git config user.name "acc2_username"
git config user.email "account2@gmail.com"
  • Now clone or add origin by using SSH link of GitHub repo:
# for account1 repo
git remote set-url origin git@github.com:acc1_username/reponame.git

# for account2 repo
git clone git@github.com-acc2:acc2_username/reponame.git

Feel free to add comments for any doubts.

1

Found out a really useful shell script wrapping over all the process of ssh key generation and typing out long commands again and again

Note: This is only for ZSh users

https://github.com/tw-yshuang/Git_SSH-Account_Switch

gtxtreme
  • 1,830
  • 1
  • 13
  • 25
0

I'm in the same boat. I wrote a little bash script to manage them. https://github.com/thejeffreystone/setgit

#!/bin/bash

# setgit
#
# Script to manage multiple global gitconfigs
# 
# To save your current .gitconfig to .gitconfig-this just run:
# setgit -s this
#
# To load .gitconfig-this to .gitconfig it run:
# setgit -f this
# 
# 
# 
# Author: Jeffrey Stone <thejeffreystone@gmail.com>

usage(){
  echo "$(basename $0) [-h] [-f name]" 
  echo ""
  echo "where:"
  echo " -h  Show Help Text"
  echo " -f  Load the .gitconfig file based on option passed"
  echo ""
  exit 1  
}

if [ $# -lt 1 ]
then
  usage
  exit
fi

while getopts ':hf:' option; do
  case "$option" in
      h) usage
         exit
         ;;
      f) echo "Loading .gitconfig from .gitconfig-$OPTARG"
         cat ~/.gitconfig-$OPTARG > ~/.gitconfig
         ;;
      *) printf "illegal option: '%s'\n" "$OPTARG" >&2
         echo "$usage" >&2
         exit 1
         ;;
    esac
done
Kev
  • 118,037
  • 53
  • 300
  • 385
  • Your script here is in Bash, while on Github you have Python version. Also `-s` is not handled in your Bash script. – Vadim Kotov Apr 20 '18 at 13:31
0

I had an error when trying to git stash my local changes. The error from git said "Please tell me who you are" and then told me to "Run git config --global user.email "you@example.com and git config --global user.name "Your name" to set your account's default identity." However, you must Omit --global to set the identity only in your current repository.

Erich Meissner
  • 205
  • 2
  • 5