How to manage your dotfiles#

On Unix systems, dotfiles are files that are stored in the home directory and contain configuration information. The XDG Base Directory Specification already splitted them in three categories and most applications how store their files in .cache, .config, and .local based on their purpose. And a small subset of application sticks to the root of the home directory like the most shells. In most cases you don’t need to manage your dotfiles across multiple machines, but for the ones you want to manage across multiple machines or want to be present in your devcontainer, you can use a utility like RCM and a dotfiles repository.

Setting up your repository#

The first step is to create a repository on GitHub and we use the GitHub command-line tool for this, but it can also be done via the web interface. After creating the repository, it is renamed to .dotfiles at the root of the user’s home directory and makes it hidden.

$ gh repo create dotfiles --public --clone
$ mv dotfiles ~/.dotfiles

The second step is to create a configuration file in rcrc in the repository. This file is used to configure RCM by telling which files to exclude or where to store files.

EXCLUDES="README*.md LICENSE install.sh"
DOTFILES_DIRS="$HOME/.dotfiles $HOME/dotfiles"

The third step is to create the installation script install.sh that can be run automatically. This script will create the directories and symlink the files to the correct location, but it will not overwrite existing files as the -f option is not used.

#!/usr/bin/env bash

set -e

# Determine path of repository
REPOPATH="$(
  cd -- "$(dirname "$0")" >/dev/null 2>&1
  pwd -P
)"

# Check if the command exists
[[ -x $(which rcup) ]] && rcup -d "$REPOPATH" -x "README*.md LICENSE install.sh"

The fourth and final step is to add the modifications to the repository and push them to GitHub.

$ cd ~/.dotfiles
$ git add rcrc install.sh
$ git commit -m "Add rcrc and install.sh"
$ git push

Installing RCM on Linux#

The RCM package isn’t installed on Linux by default but can be installed via the dnf or apt package managers.

On Debian and Ubuntu:

$ sudo apt install rcm

On Fedora:

$ sudo dnf install rcm

Now that btw the repository and the software has been installed we can quickly setup our dotfiles. The first to be set up is the rcrc configuration file.

$ rcup -d ~/.dotfiles/rcrc
$ ls -l ~/.rcrc
lrwxrwxrwx. 1 user01 user01 28 Feb 14 00:10 /home/user01/.rcrc -> /home/user01/.dotfiles/rcrc

Enable RCM in devcontainers#

By default, RCM is not enabled in devcontainers. To enable it, you need to add the following to the proper .devcontainer/Dockerfile file in the repository of your application. The second step is to enable dotfiles in the GitHub web interface. Or by adding "dotfile.repository": "user01/dotfiles" to settings.json to the user settings in VSCode.

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install --no-install-recommends rcm

Maintaining your dotfiles#

Adding existing dotfiles to the repository#

Let’s start with a simple example and add an existing file called .vimrc to the repository. The file is located in the root of the user’s home directory.

$ ls -l ~/.vimrc
-rw-rw-r--. 1 user user01 446 Feb 14 00:11 /home/user01/.vimrc

With the command mkrc we can move an existing file to the repository and directly create a symlink to it.

$ mkrc ~/.vimrc

If we check the file again we see that it is now in the repository and a symlink to it is created.

$ ls -l ~/.vimrc
lrwxrwxrwx. 1 user01 user01 29 Feb 14 00:12 /home/user01/.vimrc -> /home/user01/.dotfiles/vimrc

The command rcup can be used to deploy the repository, but nothing has to be updated.

$ rcup -v
identical /home/user01/.vimrc

The same goes for lsrc which shows the mapping between the files in the repository and on the file system.

$ lsrc
/home/user01/.vimrc:/home/user01/.dotfiles/vimrc

As a final step, the new file needs to be added to git and push to the repository on GitHub.

$ cd ~/.dotfiles
$ git add vimrc
$ git commit -m "Add vimrc"
$ git push

The above steps can be done for other files as well and even for files in directories or subdirectories.

Creating new dotfiles#

It can be useful to create new dotfiles in the repository. This can be done by using the touch command in the repository and running rcup afterward. In the example below we create a new file called screenrc and add it to the repository.

$ touch ~/.dotfiles/screenrc
$ rcup
$ lsrc
/home/user01/.vimrc:/home/user01/.dotfiles/vimrc
/home/user01/.screenrc:/home/user01/.dotfiles/screenrc

As a final step the new file needs to be added to git and push to the repository on GitHub.

$ cd ~/.dotfiles
$ git add screenrc
$ git commit -m "Add screenrc"
$ git push

Updating dotfiles#

Updating your dotfiles is as easy as running rcup, but the repository needs to be pulled manually to get the latest version from the repository on GitHub.

$ git -C ~/.dotfiles pull
$ rcup

As RCM by default creates symbolic links to the files in the repository, it is possible to detect updates that were made locally easily with the command git diff, and if required these changes can be committed and pushed to the repository with regular git commands.

$ git -C ~/.dotfiles diff
diff --git a/vimrc b/vimrc
index 17ac999..8633541 100644
--- a/vimrc
+++ b/vimrc
@@ -4,6 +4,8 @@ filetype indent plugin on

 syntax on

+set cc=80
+

Note

On GitHub Codespaces and VSCode devcontainers the dotfiles repository is automatically pulled when the container is created or rebuilt.

Which dotfiles to include#

Which dotfiles to place under version control is a bit more complicated and maybe even more a philosophical question than a technical question. The golden rule is to never put any dotfiles under version control that have credentials in them or are sensitive information like which servers to connect to as it may be abused by others to gain access to your account.

Another rule is to not include any dotfiles that should be part of a project repository. Some of those files are .editorconfig, .gitattributes, and .gitignore, but those also have the option to only contain global settings and to be overruled by the project repository.