Different .gitconfig for a given subdirectory?
GitEmailGit ConfigGit 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