dotfiles.md (3725B)
- ---
- date: 2019-12-30
- layout: post
- title: Managing my dotfiles as a git repository
- ---
- There are many tools for managing your dotfiles - user-specific configuration
- files. GNU stow is an example. I've tried a few solutions over the years, but I
- settled on a very simple system several years ago which has served me very well
- in the time since: my $HOME is a git repository. [This
- repository](https://git.sr.ht/~sircmpwn/dotfiles), in fact. This isn't an
- original idea, but I'm not sure where I first heard it from either, and I've
- extended upon it somewhat since.
- The key to making this work well is my one-byte `.gitignore` file:
- ```
- *
- ```
- With this line, and git will ignore all of the files in my $HOME directory, so I
- needn't worry about leaving personal files, music, videos, other git
- repositories, and so on, in my public dotfiles repo. But, in order to track
- anything at all, we need to override the gitignore file on a case-by-case basis
- with `git add -f`, or `--force`. To add my vimrc, I used the following command:
- ```
- git add -f .vimrc
- ```
- Then I can commit and push normally, and .vimrc is tracked by git. The gitignore
- file does not apply to any files which are already being tracked by git, so any
- future changes to my vimrc show up in git status, git diff, etc, and can be
- easilly committed with `git commit -a`, or added to the staging area normally
- with `git add` — using `-f` is no longer necessary. Setting up a new
- machine is quite easy. After the installation, I run the following commands:
- ```
- cd ~
- git init
- git remote add origin git@git.sr.ht:~sircmpwn/dotfiles
- git fetch
- git checkout -f master
- ```
- A quick log-out and back in and I feel right at $HOME. Additionally, I have
- configured $HOME as a prefix, so that ~/bin is full of binaries, ~/lib has
- libraries, and so on; though I continue to use ~/.config rather than ~/etc. I
- put $HOME/bin ahead of anything else in my path, which allows me to shadow
- system programs with wrapper scripts as necessary. For example, ~/bin/xdg-open
- is as follows:
- ```sh
- #!/bin/sh
- case "${1%%:*}" in
- http|https|*.pdf)
- exec qutebrowser "$1"
- ;;
- mailto)
- exec aerc "$1"
- ;;
- *)
- exec /usr/bin/xdg-open "$@"
- ;;
- esac
- ```
- Replacing the needlessly annoying-to-customize xdg-open with one that just
- does what I want, falling back to /usr/bin/xdg-open if necessary. Many other
- non-shadowed scripts and programs are found in ~/bin as well.
- However, not all of my computers are configured equally. Some run different
- Linux (or non-Linux) distributions, or have different concerns being desktops,
- servers, laptops, phones, etc. It's often useful for this reason to be able to
- customize my configuration for each host. For example, before $HOME/bin in my
- $PATH, I have $HOME/bin/$(hostname). I also run several machines on
- different architectures, so I include $HOME/bin/$(uname -m)[^1] as well. To
- customize my sway configuration to consider the different device configurations
- of each host, I use the following directive in ~/.config/sway/config:
- ```
- include ~/.config/sway/`hostname`
- ```
- Then I have a host-specific configuration there, also tracked by git so I can
- conveniently update one machine from another. I take a similar approach to
- per-host configuration for many other pieces of software I use.
- Rather than using (and learning) any specialized tools, I find my needs quite
- adequately satisfied by a simple composition of several Unix primitives with a
- tool I'm already very familiar with: git. Version controlling your configuration
- files is a desirable trait even with other systems, so why not ditch the
- middleman?
- [^1]: `uname -m` prints out the system architecture. Try it for yourself, I bet it'll read "x86_64" or maybe "aarch64".