My usual method for setting up a new computer is to install Syncthing and add all my main synchronized folders, then rsync any specific dotfiles (.vimrc, .gitconfig, etc) to the new system.

It’s never super clean, but this does speed me up enough to get moving quickly. I’ve considered setting up a more global $HOME sync folder with a ton of excludes, but I want to be a bit more intentional about updating my system configuration.

I decided to just use a private GitHub repo to store these dotfiles, taking a lot of care to avoid committing any secrets (I like to assume that anything I store on someone else’s computer will eventually be public).

This turned out to be so much easier than I expected, just a simple alias to override the $GIT_DIR and a custom exclude file to make sure I only add very specific files to this repo.

git init --bare $HOME/.cfg
echo "*" >> $HOME/.cfg/info/exclude

alias dotfile="git --git-dir=$HOME/.cfg/ --work-tree=$HOME"

I have the above alias added to my .zshrc (so bonus: it is automatically sync’d!) and can do all the normal git commands by calling dotfile:

dotfile remote add origin
dotfile add .gitconfig
dotfile add .zshrc
... # etc
dotfile commit -m 'add my dotfiles'
dotfile push -u github main

Now, to setup a new machine, I need to setup my dotfile repo in my home directory. Just as before when I initialized a bare git repo with a custom GIT_DIR, I need to clone my repo on the new system with the bare flag and pointing to the same .cfg directory for consistency. You can test this non-destructively by creating a temporary folder and referencing it instead of $HOME in the commands below:

⚠️ This will overrwrite any tracked files in $HOME ⚠️

git clone --bare $HOME/.cfg
git --git-dir=$HOME/.cfg --work-tree=$HOME checkout -f

Now I can do things like manage OS-specific entries and files via branches, or try out major changes without worrying about leaving myself in a broken state on this machine or another one.