Dotfiles are files and directories that define application configurations. They are preceded with a “.” which hides them, by default, within many file browsers. To maintain a uniform experience, users may aim to sync their dotfiles across development environments. This management process is often cumbersome, and is compounded by the number of machines a user frequently access'. Although historically I have a single laptop, where I favor simplicity over functionality, I am plagued by an addition for distro-hopping and fresh installs. This makes dotfile management important.

My dotfiles management approach is a blend of many solutions, most notably Atlassian’s dotfile tutorial. Basically it relies on (1) defining your $HOME directory as a git repository, (2) renaming the git directory (e.x., $HOME/.dotfiles), and (3) aliasing a command to automatically set this environment.

I encapsulate this functionality in a dotfiles script within my scripts repository. This script wraps git by overriding the init and clone commands with short sequences to manage the aforementioned environment. Then all other commands are forwarded to git using the line below:

git --git-dir=$HOME/.dotfiles --work-tree=$HOME "${args[@]}"

Here is the output of this scripts help command:

hamersaw@ragnarok:~$ dotfiles help
    help                display this help menu
    clone <git-repo>    clone an existing dotfiles repository
    init                initailize a new dotfiles repository
    version             display the application version
    *                   forward arguments to git

Creating a new dotfiles repository

Initializing a fresh dotfiles repository using this script is very similar to a conventional git repository – call init, make an initial commit, and push to a remote repository. The script aliases the init command to setup a bare repository in the users $HOME directory and configures it to not show untracked files (a personal preference).

# initialize new dotfiles repository
dotfiles init

# add a remote repository
dotfiles remote add <name> <url>

# redacted - make initial commit

# push local commits to remote repository
dotfiles push -u origin

Manage dotfiles

Non-overridden arguments, which are basically everything except init and clone, are forwarded to git. This means that git operations work more or less identical to a conventional git repository. Therefore, tracking the status, adding untracked changes or new files, committing these modifications, and pushing the commits works as shown below:

# view dotfiles modifications
dotfiles status

# add an untracked change
dotfiles add .config/foo/bar.yaml

# commit tracked repository changes
dotfiles commit -m "baz"

# push dotfiles to remote repo
dotfiles push

Clone an existing dotfiles repository

Syncing dotfiles between environments requires cloning the remote git repository within the new system. The script overrides the clone command to setup a bare repository and again configures it not to show untracked files. Sometimes I have encountered git repository checkout conflicts, this is common when using different distros or replacing an existing configuration. Fortunately, git makes merging or replacing existing files simple by warning of any conflicts. With this setup it is typically easy to delete the existing dotfile to continue the checkout command.

# setup tracking of remote repository
dotfiles clone <url>

# checkout all files within the remote repository
dotfiles checkout

This post is part 2 / 5 of the Script Series:

  1. Introduction
  2. A Script for Managing Dotfiles
  3. Due: A Kanban TODO List Script
  4. Scripting Your UI Color-Palette
  5. Password Management with Stash

4 day(s) offloaded in the 100DaysToOffload challenge.