[git] Is it possible to have different Git configuration for different projects?

.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?

This question is related to git git-config

The answer is


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 "[email protected] 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.


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.


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 <[email protected]>

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

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

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

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=$(pwd)/.gitconfig

And .gitconfig is usual gitconfig with desired values.


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.


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.


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 = [email protected]
    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 = [email protected]

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

git config --global alias.hobbyprofile 'config user.email "[email protected]"'

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


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.

In your .gitconfig 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

[user]
name = John Smith
email = [email protected]

Example contents of .gitconfig-company_b

[user]
name = John Smith
email = [email protected]

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 = [email protected] [includeIf "gitdir:~/organization_b/"]
    
     [user]
    
         name = John Doe
    
         email = [email protected]