Are there pitfalls to putting $HOME in git instead of symlinking dotfiles?

Yes, there is at least one major pitfall when considering git to manage a home directory that is not a concern with subversion.

Git is both greedy and recursive by default.

Subversion will naively ignore anything it doesn't know about and it stops processing folders either up or down from your checkout when it reaches one that it doesn't know about (or that belongs to a different repository). Git, on the other hand, keeps recursing into all child directories making nested checkouts very complicated due to namespace issues. Since your home directory is likely also the place where you checkout and work on various other git repositories, having your home directory in git is almost certainly going to make your life an impossible mess.

As it turns out, this is the main reason people checkout their dotfiles into an isolated folder and then symlink into it. It keeps git out of the way when doing anything else in any child directory of your $HOME. While this is purely a matter of preference if checking your home into subversion, it becomes a matter of necessity if using git.

However, there is an alternate solution. Git allows for something called a "fake root" where all the repository machinery is hidden in an alternate folder that can be physically separated from the checkout working directory. The result is that the git toolkit won't get confused: it won't even SEE your repository, only the working copy. By setting a couple environment variables you can tip off git where to find the goods for those moments when you are managing your home directory. Without the environment variables set nobody is the wiser and your home looks like it's classic file-y self.

To make this trick flow a little smoother, there are some great tools out there. The vcs-home mailing list seems like the defacto place to start, and the about page has a convenient wrap up of howtos and people's experiences. Along the way are some nifty little tools like vcsh, mr. If you want to keep your home directory directly in git, vcsh is almost a must have tool. If you end up splitting your home directory into several repostories behind the scenes, combine vcsh with mr for quick and not very dirty way to manage it all at once.


I wouldn't want my entire home directory checked into version control simply because it means every subdirectory I go into would have the version-control context of my home dir. Commands like git checkout would have an actual action in that case, causing issues if I accidentally run something from the wrong directory, whether that something is git itself or a script that calls git.

It also makes it more likely to add something to the repo that you don't want, which would not have been an issue when you had everything checked in, but now becomes a problem. What if you accidentally add a private key file (perhaps out of habit) and push it to github?

Having said that, I think the primary disadvantages are not really technical — just wanting to save me from myself.

As for symlinking: You could clone your repo into a subdirectory, and have a script which updates any symlinks that need to be updated. The amount of maintenance required for this script might outweigh the benefits of having it at all, though; symlinking might turn out to be less work.

With symlinks, you can also easily make distro-specific (or even host-specific) additions that get checked into git. Your symlink-update script will ignore files intended for incompatible platforms or different hosts, and only update the appropriate ones.

Something like:

HOMEREPO=$HOME/homerepo
HOST=$(hostname)
UNAME=$(uname)

for dotfile in $HOMEREPO/shared/* $HOMEREPO/host-$HOST/* $HOMEREPO/uname-$UNAME/*
do
    target=$HOME/$(basename $dotfile)
    [ ! -r $target ] && ln -s $dotfile $target
done

Personally: I use symlinks, and I don't symlink directories; only the files within. This gives me some flexibility to make site-local changes in those directories (ie. add/remove files). Setting up my account on a new system is tedious because I have to recreate all the symlinks by hand.


To give another point of view: I have my $HOME under git since sometime now and didn't find any drawbacks. I obviously do not sync this git repo to github; I use a service which have private repos. I also do not put any media files or downloads or packages under git control.

  • git status is a kind of "to do, to clean" checklist.

  • I have a ~/tmp for temporary things, which is gitignored.

  • I like to see in git status anything that a recently installed software dare to add to my $HOME, and often delete these files, or even uninstall the culprits.

  • I add manually the really useful local files and dirs to .gitignore, which has a 'know what you do when installing things' benefit.

  • If I build a new VM or install a new PC, I just clone my remote home to $HOME and have immediately everything I need under hands.

  • Things like vundle for vim plugins are not necessary anymore.

I dislike complexity. When I tweak any rcfile, I just do it, commit and push. Then, as a reflex, I git pull in $HOME every other day, and have always the latest config. It is that simple.

Machines currently under this regimen: Home laptop, work PC, work VM, plus 3 or 4 remote servers.