Different .gitconfig for a given subdirectory?

GitEmailGit Config

Git Problem Overview


I use two different git emails, one for work and one for public projects. Initially I thought that I could create a separate .gitconfig with a different email in a folder where all my public repos are in, and that git would respect that, but alas it seems that doesn't work. What's the best way to easily setup something similar? I want to avoid having to specifically change the email in each public repo.

Git Solutions


Solution 1 - Git

The best way to do this since git 2.13 is to use Conditional includes.

An example (copied from an answer here):

Global config ~/.gitconfig

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

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

Work specific config ~/work/.gitconfig

[user]
    email = [email protected]

Solution 2 - Git

As mentioned in other answers you can't really set your credentials per directory. But git allows you to do so on a per repository basis.

# Require setting user.name and email per-repo
$ git config --global user.useConfigOnly true

This way, on your first commit you will get an error asking you to provide name and email. In your repo folder add your credentials once to your repo and from then on you'll commit with this identity:

$ cd path/to/repo
$ git config user.name My Name
$ git config user.email [email protected]

Solution 3 - Git

I have the exact same problem. As a temporary solution, I have this in my .bashrc:

alias git='GIT_AUTHOR_EMAIL=$(
      p=$(pwd)
      while [[ $p != "$HOME" ]]; do
        [ -e $p/.gitemail ] && cat $p/.gitemail && break
        p=$(dirname $p)
      done) GIT_COMMITTER_EMAIL=$(
      p=$(pwd)
      while [[ $p != "$HOME" ]]; do
        [ -e $p/.gitemail ] && cat $p/.gitemail && break
        p=$(dirname $p)
      done) /usr/bin/git'
alias g=git

This way I've got two different .gitemail files in the parent directories:

  • ~/work/.gitemail
  • ~/github/.gitemail

Note that I'm only switching user.email this way, everything else is centralized in ~/.gitconfig. It's a solution, but it's not great.

Hoping someone on StackOverflow has a better idea...

Solution 4 - Git

Having switched over to ZSH, this is my revised solution to the problem using "profiles" triggered on directory changes. The nice thing about this solution is that it can be used for other settings.

Pop this into your zsh config:

#
# Thanks to: Michael Prokop. 
# More documentation: 
# http://git.grml.org/?p=grml-etc-core.git;f=etc/zsh/zshrc;hb=HEAD#l1120
#
CHPWD_PROFILE='default'
function chpwd_profiles() {
    local -x profile

    zstyle -s ":chpwd:profiles:${PWD}" profile profile || profile='default'
    if (( ${+functions[chpwd_profile_$profile]} )) ; then
        chpwd_profile_${profile}
    fi

    CHPWD_PROFILE="${profile}"
    return 0
}
chpwd_functions=( ${chpwd_functions} chpwd_profiles )

chpwd_profile_default # run DEFAULT profile automatically

And then elsewhere in your zsh git customizations:

zstyle ':chpwd:profiles:/home/user/work(|/|/*)'  profile work
zstyle ':chpwd:profiles:/home/user/fun(|/|/*)'   profile fun

# configuration for profile 'default':
chpwd_profile_default()
{
  [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
  print "chpwd(): Switching to profile: default"

  export GIT_AUTHOR_EMAIL="[email protected]"
  export GIT_COMMITTER_EMAIL="[email protected]"
}

# configuration for profile 'fun':
chpwd_profile_fun()
{
  [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
  print "chpwd(): Switching to profile: $profile"

  export GIT_AUTHOR_EMAIL="[email protected]"
  export GIT_COMMITTER_EMAIL="[email protected]"
}

# configuration for profile 'work':
chpwd_profile_work()
{
  [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
  print "chpwd(): Switching to profile: $profile"

  export GIT_AUTHOR_EMAIL="[email protected]"
  export GIT_COMMITTER_EMAIL="[email protected]"
}

Solution 5 - Git

The real answer is that its impossible.

However, thanks to @pithyless , and because I was already using a custom 'c' function to switch directories followed by an auto ls, this is what I'm doing now:

# cd + ls, and change git email when in personal projects folder 
function c {
  if [[ "`abspath $1`" == *"$HOME/Projects"* ]]; then
    export GIT_AUTHOR_EMAIL="[email protected]"
  else
    export GIT_AUTHOR_EMAIL="[email protected]"
  fi
  cd "${@:-$HOME}" && ls;
}

Solution 6 - Git

Have a centralized mechanism for creating repos. Like some script in your path etc. whereby you do:

repo create -t public -n name

or something like that.

The repo command ( just an example, nothing to do with the one from Android ) will create the repo for you in the necessary location and read a config file and set the credentials for that repo (in the .git/config for that repo ) based on the type being public or private etc.

Solution 7 - Git

I had same needs, but I wanted all .gitconfig sections can be overrided and not only user.email and user.name.

Because I not found anything I done this: https://github.com/arount/recursive-gitconfig

Here is the current code, but please refer to the github source to get last updates:

# Look for closest .gitconfig file in parent directories
# This file will be used as main .gitconfig file.
function __recursive_gitconfig_git {
    gitconfig_file=$(__recursive_gitconfig_closest)
    if [ "$gitconfig_file" != '' ]; then
        home="$(dirname $gitconfig_file)/"
        HOME=$home /usr/bin/git "$@"
    else
        /usr/bin/git "$@"
    fi
}

# Look for closest .gitconfig file in parents directories
function __recursive_gitconfig_closest {
    slashes=${PWD//[^\/]/}
    directory="$PWD"
    for (( n=${#slashes}; n>0; --n ))
    do
        test -e "$directory/.gitconfig" && echo "$directory/.gitconfig" && return 
    directory="$directory/.."
    done
}

alias git='__recursive_gitconfig_git'

This allow me to use specific .gitconfig depending what repository I'm playing with.

Hope this can help some of you

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSuanView Question on Stackoverflow
Solution 1 - GitChris CrewdsonView Answer on Stackoverflow
Solution 2 - GitTorsten WalterView Answer on Stackoverflow
Solution 3 - GitpithylessView Answer on Stackoverflow
Solution 4 - GitpithylessView Answer on Stackoverflow
Solution 5 - GitSuanView Answer on Stackoverflow
Solution 6 - GitmanojldsView Answer on Stackoverflow
Solution 7 - GitArountView Answer on Stackoverflow