zsmb.coEst. 2017



Managing Git configurations

2019-02-25 • Márton Braun

Nearly every developer uses Git, and I believe that most of them will admit that they have, at least on one occasion, used credentials that they didn’t mean to when creating a commit. This issue is very understandable: we tend to have multiple email addresses we use for this purpose, whether it be for school, work, or personal projects. People consulting for a variety of companies may receive email addresses from the clients that are to be used for commits. With all these, it’s easy to mix them up and occasionally use the wrong one.

Of course, using the wrong format of your name or the wrong email address is one thing (although there are places where this is taken seriously as well), but there can be even more in a Git config than that: you might be signing your commits, and having the wrong signing key on a commit is certainly not as negligable as using the wrong email address might be.

Now, let’s take a look at some approaches for managing your credentials in Git, and see how you can make sure you’re always using the correct one.

Global-only

The simplest approach to Git is to use just a single configuration where you set your credentials. This can be done either from the command line:

git config --global user.email "helloworld@example.com"
git config --global user.name "Hello World"

Or you can put these values in your ~/.gitconfig file manually:

[user]
    email = helloworld@example.com
    name = Hello World

Either way, if this is all the configuration you perform, any repository you create commits in will use these same settings.

While you could technically check (and if need to, change) these global settings before every single commit, it would be tedious and very easy to forget. This approach only really works in the rare case where you need the exact same configuration for all of your repositories. Perhaps if it’s a work computer that you exclusively use for work.

Global with local overrides

This second strategy is what seems to be used by most people, at least anecdotally. Other than your global configuration, you may also maintain local configurations on a per-repository basis.

The local configuration can be set from the command line very similarly to the global one, just without the --global option:

git config user.email "helloworld@example.com"
git config user.name "Hello World"

Or again, by editing the configuration file .git/config directly, using the same syntax as in the global one.

Employing these two methods together will let you use the global configuration that you need most of the time as your default, and override it for repositories that need different settings on a case-by-case basis.

This requires you to remember to set up the local configs for repositories where you need a non-default configuration, which is quite easy to forget. This is how most accidental commits with bad credentials happen, implicitly using the default global configuration (at least in my experience).

Local-only

This next method is the one I personally use, and while a little tiresome, it guarantees that you use the correct configuration for each project.

You can skip setting up a global Git configuration altogether, and rely solely on local, per-repository configurations. If you haven’t set a local configuration yet, you’ll be prompted to do so the first time you try to create a commit. This way you’ll be sure you’re using the correct one, as you have set it explicitly!

This setup comes at the cost of having to perform configuration for every new repository you work in once. The way I made this relatively painless is by maintaining a file I can access quickly that contains all my different sets of credentials, ready for copy-pasting into a new local config.

Conditional includes

Since Git 2.13 (May of 2017), Git config files support conditional includes. You can use these to set your credentials for all Git repositories in a given directory. For example, for school and work, you can configure your global Git config as such:

[includeIf "gitdir:~/Documents/School/"]
    path = .gitconfig-school
[includeIf "gitdir:C:/Work/"]
    path = .gitconfig-work

Note the importance of trailing slashes in the gitdir parameter - these configs won’t work without them!

You’ll of course have to create the various .gitconfig-* files that you refer to in the includes. For example, ~/.gitconfig-school might look like this:

[user]
    email = helloworld@school.edu
    name = Hello World

Wrap-up

To sum up all these different ways of managing your configs:

  • Global-only only works if you have a single set of credentials.
  • Global and local can work if you usually use one set of credentials, and there’s only a very small number of repositories where you need a different one. It relies on remembering to set separate configurations for the exceptions, which is error-prone.
  • Local-only is completely foolproof and my recommendation, as it forces you to choose your credentials for a given project the first time you try to create a commit.
  • Conditional includes are more convenient than local-only, and work great if you keep your projects well organized.

I hope you’ve learned something and can adopt one of the latter approaches in this list. Off you go now. There’s commits to author correctly.



You might also like...

@JvmOverloads for Android Views

The @JvmOverloads annotation is a convenience feature in Kotlin for interoperating with Java code, but there is one specific use case on Android where it shouldn’t be used carelessly.

Retrofit meets coroutines

Retrofit's coroutine support has been a long time coming, and it's finally coming to completion. Take a look at how you can use it to neatly integrate networking into an application built with coroutines.