Rationale
Storing dotfiles in a git repository is fairly easy. While it's straightforward to simply initialise a git repository directly within your home directory, this presents problems with managing ignore lists and potentially opens the door to interaction from other git repositories stored within your home directory. Alternatively you could have an isolated git repository elsewhere and symlink your home directory's dotfiles to that directory, but that's pretty ugly.
A slightly modified technique is to use a "bare" git repository in a sub-directory somewhere off $HOME, and then your dotfiles in $HOME are literally the same as the files in git. I use $HOME/.dotfiles and alias the git command with the necessary parameters to a new dotfiles
command, specifically for interacting with the dotfiles repository.
Setup
All we needs is a git repository initialised somewhere, treating $HOME as its root.
git init --bare $HOME/.dotfiles
alias dotfiles='git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
dotfiles config --local status.showUntrackedFiles no
This will give you a git repository in ~/.dotfiles
and a dotfiles
command in your current terminal to work with it.
To make the dotfiles command permanent, you will need to add it to your .zshrc (shown) or .bashrc
echo "alias dotfiles='git --git-dir=\$HOME/.dotfiles/ --work-tree=\$HOME'" >> $HOME/.zshrc
The echoed string has $HOME
escaped to prevent it being expanded before being written into .zshrc, which will work fine locally but may cause problems when you share this across different machines.
You can then interact with this like any other git repository:
dotfiles status
# No files will be shown as we are using status.showUntrackedFiles=no
dotfiles add ~/.zshrc
dotfiles commit -m "Add .zshrc to dotfiles"
# Add a remote
dotfiles remote add origin git@mygithost.com:myname/dotfiles.git
dotfiles push
Restoring on another machine
Restoring this on another machine is not quite trivial because git won't overwrite existing files.
This is a short script that will move existing files to ./.dotfiles-backup/
(relative to the current working directory) and then restore the dotfiles from the repository.
Assuming you have your .zshrc checked in, you won't need to set the dotfiles alias again.
#!/usr/bin/env bash
git clone --bare git@mygithost.com:myname/dotfiles.git $HOME/.dotfiles
function dotfiles {
git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME $@
}
mkdir -p .dotfiles-backup
dotfiles checkout
if [ $? = 0 ]; then
echo "Checked out dotfiles"
else
echo "Couldn't check out dotfiles due to existing files. Backing up existing files to .dotfiles-backup"
dotfiles checkout 2>&1 | grep -E "^\s+\S+" | awk {'print $1'} | xargs -d $'\n' sh -c 'for arg do echo "Backing up $arg"; mkdir -p .dotfiles-backup/"$arg"; mv "$arg" ".dotfiles-backup/$arg"; done' _
echo 'Backed up'
fi;
dotfiles checkout
dotfiles config --local status.showUntrackedFiles no
echo 'Done'