logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

dotfiles.md (3725B)


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