The best way to store your dotfiles: A bare Git repository
Disclaimer: This post is heavily based on the one at https://www.atlassian.com/git/tutorials/dotfiles which goes more into the details
Some other sources you might want to check out:
- Hacker News thread on people’s solutions to store their dotfiles.
- User
StreakyCobra
showed his elegant setup
The only pre-requisite is to install Git.
In his words the technique below requires:
No extra tooling, no symlinks, files are tracked on a version control system, you can use different branches for different computers, you can replicate you configuration easily on new installation.
TLDR;
Store your dotfiles in a Git bare repository which acts as a “side” folder (like $HOME/.dotfiles
or $HOME/.myconfig
) using a specially crafted alias. This alias runs the git
-command against that repository and not the usual .git
local folder, which would interfere with any other Git repositories around.
Starting from scratch
Create a bare git repo in your home folder and define an alias to work with it:
# __init repo git init --bare $HOME/.dotfiles alias # __create an alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME' # __set config option dotfiles config --local status.showUntrackedFiles no # __add alias to .bashrc echo "alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'" >> $HOME/.bashrc # __add alias to .zshrc # echo "alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'" >> $HOME/.zshrc
After this you can manage every file within the $HOME
folder with the newly created dotfiles
alias, like:
dotfiles status dotfiles add .vimrc dotfiles commit -m "Add vimrc" dotfiles add .bashrc dotfiles commit -m "Add bashrc" dotfiles push
Install your dotfiles onto a new system (or migrate to this setup)
If you already store your configuration/dotfiles in a Git repository, on a new system you can migrate to this setup with the following steps:
# Add the bare repo directory to a '.gitignore' file echo "dotfiles/" >> .gitignore # clone your repo into a '.dotfiles' directory git clone --bare <git-repo-url> $HOME/.dotfiles # Define the alias in the current shell scope: alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME' # Checkout the actual content from the bare repository to your '$HOME': dotfiles checkout
The step above might fail with a message like:
error: The following untracked working tree files would be overwritten by checkout: .bashrc .gitignore Please move or remove them before you can switch branches Aborting
This is because your $HOME
folder might already have some stock configuration files which would be overwritten by Git. The solution is simple: back up the files if you care about them, remove them if you don’t care. I provide you with a possible rough shortcut to move all the offending files automatically to a backup folder:
mkdir -p .dotfiles-backup && \ dotfiles checkout 2>&1 | egrep "\s+\." | awk {'print $1'} | \ xargs -I{} mv {} .dotfiles-backup/{}
Re-run the check out if you had problems:
dotfiles checkout
Set the flag showUntrackedFiles
to no
on this specific (local) repository:
dotfiles config --local status.showUntrackedFiles no
You’re done, from now on you can now type dotfiles
commands to add and update your dotfiles:
dotfiles status dotfiles add .vimrc dotfiles commit -m "Add vimrc" dotfiles add .bashrc dotfiles commit -m "Add bashrc" dotfiles push
For completeness this is what I ended up with (tested on a freshly minted Alpine Linux virtualbox):
git clone --bare https://github.com/cblte/dotfiles.git $HOME/.dotfiles function dotfiles { /usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME $@ } mkdir -p .dotfiles-backup dotfiles checkout if [ $? = 0 ]; then echo "Checked out config."; else echo "Backing up pre-existing dot files."; dotfiles checkout 2>&1 | egrep "\s+\." | awk {'print $1'} | xargs -I{} mv {} .dotfiles-backup/{} fi; dotfiles checkout dotfiles config status.showUntrackedFiles no
Wrapping up
I hope you find this technique useful to track your configuration. If you’re curious, my dotfiles live here. Also please do stay connected by following @cblte.
Bonus
To get the script from here into the Alpine virtualbox machine we use the help of the null-pointer from envs.sh
# 1. Save the above script in a temporary file in /tmp/get-dotfiles.txt # 2. The use the nullpointer to store it temporarily curl -F"file=@/tmp/get-dotfiles.txt" https://envs.sh` # 3. in the virtualbox make sure curl and git are # installed by running doas apk add git curl # 4. now download the shell script with curl and the # url from second step curl https://envs.sh/ab.txt -o get-dotfiles.sh # 5. change permission and run the file chmod +x get-dotfiles.sh ./get-dotfiles.sh