DEV Community

Cover image for Yet another guide on backing up dotfiles

Posted on • Updated on • Originally published at

Yet another guide on backing up dotfiles

A few months ago I came across this article which explained how a bare git repository can be used to backup dotfiles in the *NIX home directory. I messed around with it for a while and finally ended up with a no-nonsense system for managing system dotfiles.

A bare git repository is almost like a regular git project that you might create with git init. The only difference is that it doesn't have a specific working tree but only the actual git repo (i.e. the .git folder).

Step One: Initializing the git repository

This is as simple as running the commands:

$ mkdir "${XDG_CONFIG_HOME}/cfg"
$ git init --bare "${XDG_CONFIG_HOME}/cfg/.git/"
Enter fullscreen mode Exit fullscreen mode

If you've used git for any period of time then you know that the git init command initializes an empty repository in the folder that you're currently in. Since we want to create a bare repository, we pass the --bare flag and the location of the git folder. This should create a .git folder in ~/.config/cfg. If you inspects its contents you'll find that they are similar to any other repository's .git folder.

Step Two: Accessing the repository via an alias/function

Add the following line to your .zshrc or .bashrc along with the rest of your aliases:

cfg() { git --git-dir="${XDG_CONFIG_HOME}/cfg/.git/" --work-tree="$HOME" "$@" ; }
Enter fullscreen mode Exit fullscreen mode

This function will allow us to stage and commit files to our backup repository. The --git-dir flag specifies the git repository we made in step one and --work-tree will allow us to track any file in our $HOME directory using the repo.

Step Three: Ignoring files we don't want to backup

Run exec $SHELl or restart your terminal to make the alias we made in the previous step available. Then, run the following command, so that the repository doesn't display the hundreds of files in your home directory every time you check it's status:

$ cfg config --local status.showUntrackedFiles no
Enter fullscreen mode Exit fullscreen mode

Step Four: Setup a remote repository

Create an empty remote repository (I will be using GitHub) and get its SSH or HTTP. On GitHub this is immediately available after the repo is created. Finally add the remote with:

$ cfg remote add origin <URL>
Enter fullscreen mode Exit fullscreen mode

At this point you can simply do something like:

$ cfg add ~/.vimrc
$ cfg commit -m "Adding .vimrc"
$ cfg push origin master
Enter fullscreen mode Exit fullscreen mode

This will make the repository start tracking your .vimrc and you can commit and push the file to GitHub. Pretty much all git commands like status and diff should now be available to you with the cfg function.

Getting your dotfiles on a new system:

Now all you have to do on a new system is run the following commands and you'll have all your settings back:

git init --bare "${XDG_CONFIG_HOME}/cfg/.git/"
cfg() { git --git-dir="${XDG_CONFIG_HOME}/cfg/.git/" --work-tree="$HOME" "$@" ; }
cfg config --local status.showUntrackedFiles no
cfg remote add origin
cfg pull origin master
Enter fullscreen mode Exit fullscreen mode

You might get some errors if you already have, say, a .zshrc in your new system. In this case you probably would want to delete this before pulling your files from the remote.

That's it we're done 🥳. Please do tell me if you face any issues with the script, in case you use it!

Top comments (2)

simmetopia profile image
Simon Bundgaard-Egeberg

Very nice take on it! Will definitely use the alias part. Have you heard of gnu stow? It's a symlink helper, which allows you to have your config in a random folder, then run stow configs (if that was the folder name) and it will symlink the structure of that folder to your home directory. Pretty neat, and only requires gnu stow. It's also available in homebrew for the maccies :)

nimai profile image
Nimai • Edited

No, I haven't tried gnu stow but I'll definitely check it out, thank-you :D