It's no secret that I'm a big fan of git, and of distributed version control in general; they offer a compelling toolset and degree of flexibility that you would be hard pressed to find in a “traditional” centralized version control system. Instead of discussing the merits of a DVCS or performing feature comparisons between particular implementations -- there are enough of those already -- let's take a look at how you can bend Git to your will through configuration, and a few useful aliases. If you've not encountered this before, you'll be surprised at how much can be accomplished with just a few lines in a configuration file.

Your .gitconfig

This is where the magic happens. Git, by default, will attempt to find a .gitconfig file in three places:

  • GIT_DIR/config for per-repository configurations
  • ~/.gitconfig for user-specific configurations
  • $(prefix)/etc/gitconfig for system-wide configurations

Read up on the various options and overrides that git-config accepts, as well as alternative methods to interactively add/remove/replace configuration options.

For the rest of this article we'll be adding configurations to ~/.gitconfig, but there's nothing stopping you from doing it in a per-repository (or even system-wide) configuration file instead.

For reference, here is a simplified version of the config I use:

Now let's go through what these configuration options actually do.

[color]

[color]
    diff = auto
    status = auto

These were, in all likelihood, the first configuration options I setup once I had installed Git for the first time. I work in a terminal window all day, and having proper and consistent colourization makes all the difference when attempting to quickly determine the state of your repository:

Vim editor

With these options set, all diff, status and branch commands will have (where appropriate) colourized output.

[user]

If you ever plan on making your repository available to other developers, these options are essential for identifying who you are. They're pretty self-explanatory:

[user]
    name = Joël Perras
    email = joel.perras@gmail.com

[status]

The sole configuration I have under this segment is something of a personal preference. When I'm four folders deep into a repository and I invoke git status, I don't need to see where the changed/added/deleted files are relative to where I invoked the command -- I'm far more interested in their absolute location relative to the repository root. That's where relativePaths = false comes in handy:

[status]
    relativePaths = false

[core]

There are some files you just never want to commit, no matter what project you're working on. As an avid vim user, I sometimes have a few *.swp files lying around (mostly due to my own fault), which have no place in any project history. Instead of adding an ignore rule to each and every repository, I added this configuration directive to my ~/.gitconfig, indicating where my global never-track-any-of-these-file-patterns exists:

[core]
    excludesfile = /Users/joel/.gitignore

[alias]

Now we get to the interesting stuff. Aliases in Git are exactly what you expect them to be: user-defined shortcuts that group together pre-existing git (and sometimes shell) commands and their options.

Edit: As some people have pointed out, there are a few flags/commands that will not work unless you have git 1.7.2 or above installed. Pardon the confusion.

[alias]
    d  = diff
    dc = diff --cached
    lc = log ORIG_HEAD.. --stat --no-merges
    gl = log --oneline --decorate --stat --graph
    st = status -sb
    serve = !git daemon --reuseaddr --verbose  --base-path=. --export-all ./.git
    prune-all = !git remote | xargs -n 1 git remote prune
    whatis = show -s --pretty='tformat:%h (%s, %ad)' --date=short
    whois = "!sh -c 'git log -i -1 --pretty=\"format:%an <%ae>\n\" --author=\"$1\"' -"

Some explanations:

git d and git dc

I'm often taking diffs between different revisions in projects, so these two are quite heavily used.

git lc

Lists all new commits after you fetched. This is especially useful when working on a very active project with multiple developers.

git gl

This is the default command that I invoke when I wish to inspect the log. The output is concise as well as informative:

Git Graph

git st

My preferred method of viewing the status of a repository, which gets rid of the fluff that usually accompanies the help-type text of git status:

Git Status

git prune-all

Since git remote prune doesn't know how to prune all of your remotes at once, let's teach it that trick. This is especially useful if you're tracking many remotes from various contributors to a project where the branches get nuked/renamed on a regular basis.

git whatis <commit-ish>

Pass this command a hash, branch name or tag, and it will give you a one-liner containing the commit message associated to it as well as the date it was committed on. Useful when git show is more information than you need.

git whois <name|email>

Another one of those useful commands when you're working on a project with a multitude of collaborators, and need to fish out an email address when all you remember is part of their name, or vice versa. Note that if the collaborator in question never configured their name and/or email address (as described above), then this command will not be very useful.

Conclusion

And that's it! With nothing more than a few lines in a configuration file, we've managed to make Git be more informative as well as more concise. If you have any tips/tricks/configs that you can't live without, leave a comment below.


Quite a few of the aliases and what I would consider "sane" configuration options have been lifted from the official wiki for Git. I highly recommend perusing it, once you've become familiar with Git itself.