Keeping your $HOME in Git, the right way

Posted on 17.12.2014 by Kim N. Lesmer.
This tutorial describes how you can keep your home directory in a Git repository.

So a lot of interesting websites on the Internet are talking about the benefits and pitfalls of keeping your entire $HOME directory in Git. As with most technology there are many ways to accomplish the same goal, but some are better than others.

Some are using makefiles with a lot of symbolic links, others are using a huge .gitignore which results in an unmaintainable nightmare, others are trying to script themselves out of the problems, and again some end up giving up.

But there actually exists a really easy way to accomplish this.

First of all, it makes no sense at all to keep your entire $HOME in a Git repository. Only the relevant files in your $HOME should be put in Git. But how do we accomplish that while at the same time not having to maintain a huge .gitignore with a bunch of files to ignore (that we have to remember to update each time an unimportant file gets added to our $HOME)? And what about other Git repositories that resides in our $HOME directory as well?

Okay, heres how you can accomplish your goal in a really simple way.

Create a .gitignore in your $HOME directory and let it only contain a single asterisk sign. Lets use the cat command and look at mine:

$ cd $HOME
$ cat .gitignore
*

The asterisk sign in .gitignore makes Git ignore everything by default, which is actually what we want.

Then add stuff manually from you $HOME into Git with the force -f option:

$ git init
$ git add -f foo.txt
$ git add -f bar.txt
$ git add -f mydir1
$ git add -f mydir2
$ git commit -a

Now the file "foo.txt", "bar.txt" and the directories "mydir1" and "mydir2" has been added to your $HOME Git repository and everything else has been ignored.

The benefit of this approach is:

  • You're using a white list, only adding stuff you really need Git to follow.
  • All other repositories in $HOME automatically gets ignored and they are not effected by your main .gitignore in your $HOME.
  • Your $HOME Git repository is not affected by any other .gitignore in other ignored repository.
  • You don't have to update .gitignore.
  • If you're using a remote bare repository you can then easily push and pull to and from that repository without affecting any other files in your $HOME.

You only actually have to remember to add files manually and then commit changes when needed.

This is a really simply, yet powerful way to keep your $HOME directory in Git.

So how do you clone your $HOME directory from your bare repository server to a new box?

Lets say you're using some remote SSH server as your bare git repository (called home.git)

$ git clone --bare . home.git

You then need to upload that to your SSH server.

Then you add that as a remote server (the name 'my_repo' is just an example, call it whatever you like):

$ git remote add my_repo ssh://foo@bar.com/home/foo/repo/home.git

Now you can push and pull to the remote repository from your $HOME directory.

So, now you have just finished installing your favorite Linux or BSD on a new box, and of course now you want a copy of your $HOME into this newly created machine. You cannot however simply start cloning.

This will NOT work:

$ cd $HOME
$ git clone ssh://foo@bar.com/home/foo/repo/home.git

Git will complain with: fatal: destination path '.' already exists and is not an empty directory., which makes sense.

And you cannot do "pull" either as Git will complain about overwriting files - if similar files already exists.

What you need to do on the new box is this:

$ cd $HOME
$ git init
$ git remote add my_repo ssh://foo@bar.com/home/foo/repo/home.git
$ git fetch my_repo master
$ git reset --hard my_repo/master

Now you can push and pull on that box too.

That's it!

Feel free to email me any suggestions or comments.