Keeping your home in Git, the right way

Published on 2014-12-17. Modified on 2021-04-08.

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. But there actually exists a really easy and simple 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?

Here's how you can accomplish your goal. Create a .gitignore in your $HOME directory and let it only contain a single asterisk sign *.

$ cat .gitignore
*

The asterisk sign in .gitignore makes Git ignore everything by default, which is exactly what we want. Then we just add stuff manually from $HOME into Git with the -f (force) option:

$ git init
$ git add -f foo.txt
$ git add -f bar.txt
$ git commit -a -m "Add two new files"

Now the files foo.txt and bar.txt" has been added to our $HOME Git repository and everything else has been ignored.

The benefit of this approach is:

You just have to remember to add files manually using the -f options and then commit changes when needed and it's easy to turn that into an alias.

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?

Let's 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 and turn it into your origin:

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

You can also just log into the server and create the remote repository there:

$ mkdir -p foo/repo/home.git
$ cd foo/repo/home.git
$ git init --bare

The first time you need to push something you need to set it upstream:

$ git push --set-upstream origin main

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

But what if you have just finished installing your favorite Linux or BSD on a new box and of want a copy of your $HOME on this new machine. You cannot simply start cloning.

This will NOT work:

$ 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.

This makes sense.

And you cannot do a "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:

$ git init
$ git remote add origin ssh://foo@bar.com/home/foo/repo/home.git
$ git fetch
$ git reset --hard origin/main

Again, the first time you need to push something you need to set it upstream:

$ git branch --set-upstream-to origin/main

The same goes if you begin by a pull.

Now you can push and pull on that box too.

That's it!