My dotfiles repository has gone through several iterations over the years, evolving as my needs and expectations change. I'm currently going through my third and most advanced version using a template engine to manage differences between systems. I wanted to go back and talk about each of the major versions, the reasons why I originally picked them, and why I had to change the system. Finally, I'll introduce you to this new system that I developed!
1. Just The Files
My first version was very simple. I had my .bashrc, .tmux.conf, .vimrc et cetera all in the top level of the repository, and maintained symbolic links to their locations in the home directory.
This was easy enough to manage with the few configurations I had, and I never had to create a script to automatically link the dotfiles. However, this simple structure did not scale well across multiple machines. I could only check-in any files that were identical between all systems. As a result, I often abstracted as much as I could into a single file that would then reference the machine-specific parts in well defined locations. For example, my i3 configuration would often bound keys to scripts like ~/.local/bin/i3/volume_up.
Eventually my configuration became too complicated for such a simple system, so I organized it a little and created a basic shell script to help me. This new system would be able to copy files relevant to this system and apply multiple "overlays" or "layers" at a time. There were two standard layers, the "common" layer and the layer chosen by the system's hostname. Files in the hostname layer override the common layer. It was also capable of managing "optional" layers that provided additional configurations, but I never did use that feature.
This version was very short-lived because it was unmaintainable. I was able to keep track of all of the machine-specific configurations, but if any single file diverged between two systems, I had to maintain the two files, which would most often share a lot of the same content besides having some differences.
This is the latest (and hopefully final) version of my dotfiles repository. When I ran into the problem of similar but different files, I figured that there must be a way to keep a single copy of the similar options. That solution was provided through the use of template engines, which allow you to render parts of the content dynamically by writing code inline.
I chose the Mako templating system for this implementation because I have some prior experience using it. I am sure Jinja2 would also work well. There is a Python script that uses the Mako API and walks a templates/ directory, parsing all of the files as templates and rendering them to files in the home directory after loading in some host-specific configuration files.
I'm still in the honeymoon phase with this implementation. I haven't yet found any problems, but I'm still working on porting everything to it. So far, it is a great tool, and I hope someone else can also benefit from it! The script is very short and easy to understand for anyone with moderate experience in Python, and some basic instructions are included in the README.