Git Configuration

Like any other tools, git can be configured.

You can script those configurations and store them at different places within configuration files.

This article answers the following questions:

(1) Why using git configuration? What is that useful for?
(2) What can I configure and how?
(3) What a configuration file might look like?

It will also present you with a use-case to store different git user profiles and there specific ssh keys.

 Why using git config?

Having git configurations stored in place allows you to (1) have a nice commit history with your user information displayed on Github or Gitlab’s UI. It is a way to reconciliate the user stored on the remote with the user stored on your local.

It provides also a (2) handy way to share configuration like git aliases (see this article).

Last but not the least, it allows you to (3) have different config (e.g. ssh and user identification) if you want for instance to switch users if you are multi-tenant (e.g. your ssh key to connect for Gitlab or Github might be different. Same for the email and username in used).

Anatomy of a configuration file

A git config file is a simple file. It can have different names depending on where it is located. Generally when located at the root, the name will be .gitconfig.

zsh> tail -n 3 ~/.gitconfig
[user]
    name = John Doe
    email = john.doe@gmail.com

The data in there are written like in a toml file.

A git config file has different sections. The default one is [core]. Another useful one is [user].

Alias are put under the alias section.

Here is an example of what a simple .gitconfig file might look like:

[alias]
    p=pull
    c=commit
    cm=commit -m
    s=status
    sw=switch
    a=add
    alias=!git config -l | grep alias | cut -c 7-
    cam=commit -am
    lo=log --oneline
    sc=switch -c
    rsm=rm -r --cached
    asm=submodule add
[user]
    name = John Doe
    email = "john.doe@gmail.com"

More here: https://git-scm.com/docs/git-config#_configuration_file

 The different configuration scopes (global, local)

By default, git config will read the configuration options from different git config files in that order:

(1) /etc/gitconfig
(2) ~/.gitconfig
(3) .git/config (at the repository level)
(4) .git/config.worktree (at the repository level)

They are also overwritten in that order. The local one taking precedence over the global configurations.

To read all the current configurations, you can either cat those files or simply run:

zsh> git config --list --show-scope --show-origin

Note: the show-origin argument will list where the config comes from.

If you want to see what are the specific values hold for the current config (depending on your pwd) you can use the get argument:

zsh> git config --get user.name
John Doe
zsh> git config --get user.email
john.doe@gmail.com

Note: depending on where you are located – i.e. the working directory – the value returned by the get command might change.

For instance, let’s say you have two git configuration files with different configuration in place:

zsh> pwd
~/my-workplace-folder

zsh> tree -a .
.
├── .git
    └── config
├── git-project-A
└── git-project-B

zsh> cat .git/config
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[user]
    name = Jane Doe
    email = jane.doe@gmail.com

zsh> git config user.name
Jane Doe

zsh> git config --global user.name
John Doe

zsh> cat ~/.gitconfig
[user]
    name = John Doe
    email = john.doe@gmail.com

You can also edit the git config files via command lines:

zsh> pwd
~/my-workplace-folder

zsh> git config --local user.name "Baby Doe"
zsh> git config --local user.email "baby.doe@gmail.com"

zsh> tail -n 3 .git/config
[user]
    name = Baby Doe
    email = baby.doe@gmail.com

zsh> git config --get user.name
Baby Doe

zsh> git config --global --get user.name
John Doe

One important note when setting value via command line though:

If you add an equal e.g. git config --local user.name = "Baby Doe", the “=” char will be interpreted by the command as the string value passed to user.name and will ignore silently the rest of the line. You will end up with the following file:

ssh> cat .git/config                                                                                                                
[user]
    name = =

Thus, make sure to write this instead:

zsh> git config --local user.name "Baby Doe"

Use-case: different git user profiles

I have a gitlab/ folder and a github/ one.

zsh> tree .
├── github/
└── gitlab/

By default, I want my git config (user name and email) to be associated with gitlab.

However, I want those config to be overwritten when my working directory if under the github/ folder.

Note that because I want those two users to be able to ssh push and pull from the remote repositories, they both have a specific ssh key configured:

zsh> ls -la ~/.ssh
id_rsa_gitlab
id_rsa_gitlab.pub
id_rsa_gitlhub
id_rsa_github.pub

Note: you can create a new ssh key running:

zsh> sh-keygen -o -t rsa -C "gitlab@gmail.com"

Step 1 – in the global ~/.gitconfig file:

[user]
    name = "Gitlab User"
    email = "gitlab@gmail.com"
[includeIf "gitdir:~/github/"]
    path = ~/github/.gitconfig

Step 2 – in the github/ folder:

zsh> git init # create the .git folder
zsh> cat <<EOT >> .gitconfig
[core]
    sshCommand = "ssh -i ~/.ssh/id_rsa_github"
[user]
    name = "Github User"
    email = "github@gmail.com"
EOT
zsh> pwd
~/github/

zsh> git config user.name
Github User

zsh> cd ~/gitlab
zsh> git config user.name
Gitlab User

Note: withing the github/ folder, one must remain careful and keep in mind in case of overlapping issues that there is therefore now two git config files, one being .gitconfig and the second one being .git/config.