Dotfiles Management

I have few dotfiles to manage in my system. I use mutt and vim. I use a shell. Each on of these applications has its own dotfiles. Moreover, some of these dotfiles have even further supporting dotfiles. My mutt configurations uses multiple configurations that are scattered in the .mutt/ folder. My shell dotfiles sources other files. This can be difficult to manage and replicate.

Previously, I managed all of that in a git repository that lives in ~/src/dotfiles. I also created two scripts: on that copies the files from the repository to their desired location in the system, and the other to do the opposite. This was easy to manage at first, but become a significant work to manager as the number of files grew: I had to edit the scripts, configure some logic of how to copy in and out. Moreover, I needed two different repositories for my dotfiles: one is personal that I use and can publish, while the other is mainly for work: dealing with work tools, work configurations, etc. that I do want to publish only within the company’s git server. Dealing with two different repositories with simple scripts will be a burden.

The first solution that comes to mind is symlinks. If you are not familiar with symlinks, they are essentially references to files. Thus you define a reference to your dotfiles in your system, but the actual file lives in your dotfiles repository. This will work and indeed there is a solution: GNU stow can manages these symlinks.

I also found that there is another tool conveniently called dotfiles, which manages these dotfiles automatically. I know very little about this tool.

However, I do not prefer these two solutions because it is another dependency that I need to introduce and know how to use. Moreover, I do not know if these tools support multiple dotfiles repositories, and investing the time to find out how that will work does require some work.

Looking around, I found this solution. This simple, yet effective method, was enough for me, and does not require me to learn a significant amount of tooling.

I created my dotfiles repository with the command:

git init --bare $HOME/.dotfiles
alias dotfiles='git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
dotfiles config --local status.showUntrackedFiles no
echo "alias dotfiles='git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'" >> $HOME/.zshrc

This will instantiate the dotfiles repository, and create a dotfiles alias to manager the repository. dotfiles command will act exactly as git, so you will be able to run commands such as dotfiles status and dotfiles commit. To add a files, you can use dotfiles add <file>.

For getting the files on the machine, you will need first to clone it:

alias dotfiles='git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
git clone --bare <git-repo-url> $HOME/.dotfiles
dotfiles config --local status.showUntrackedFiles no
dotfiles checkout

And if checkout fails due to the files already existing, then you can move then .dotfiles-backup to back them up and check the differences:

mkdir -p .dotfiles-backup && \
dotfiles checkout 2>&1 | egrep "\s+\." | awk {'print $1'} | xargs -I{} mv {} .dotfiles-backup/{}

You can run a similar process, with dotfiles-work for work repository. I have not had a problem yet with this solution and it seems to be simple and working just fine. Thanks of course to Nicola and his very helpful article.