3 Comments

Stow Your Dotfiles – GNU Stow for Managing Symlinks

If you’ve done much work with command line tools, you’ve undoubtedly wrestled with dotfiles, those pesky configuration files in your home directory that are hidden from view by having a dot at the beginning of their name. Bash uses a .bashrc configuration file. Vim uses a .vimrc file and a .vim directory for additional scripts. Tmux uses a .tmux.conf file. Git uses a global .gitconfig. Untold other tools follow the pattern.

Dotfiles are indispensable for configuring your system, so it’s helpful to have them in a single, version-controlled directory. Since Vim, Bash, Tmux, and friends don’t know to look in your dotfiles directory, you’ll need to symlink from your home directory to each file’s actual location. Managing those symlinks for all your dotfiles can be a pain, and there are several tools designed especially for helping manage your dotfiles. The best tool I’ve found so far is GNU Stow1.

Basics

Stow allows you to collect dotfiles into various packages that can be symlinked as a group. If you’re in a ~/dotfiles directory with a git subdirectory, you can run stow git and Stow will symlink all the files in ~/dotfiles/git into the home directory.

In general, Stow symlinks files from packages into the their grandparent directory. If you’d like to symlink them elsewhere, use the -t option, which allows you to specify a target directory for creating symlinks.

Managing Project Dotfiles

Stow’s -t option is incredibly useful for me, because not only do I rely on dotfiles in my home directory, but in many project directories as well. I put project-specific Vim scripts alongside the source code in a .vimlocal file. I create a project workspace in Tmux by running a .tmuxrc file. I have scripts related to my workflow in a directory called (for some reason) .rj.

All these project-specific dotfiles are scattered across my source code directories. Since they have to do with my preferences and not the team’s, I don’t check them into the source code, which means if I delete the project directory for any reason, I won’t have my scripts when I re-clone the repository.

Thanks to Stow, I can move all these project dotfiles into one version-controlled directory and delete my complex system of scripts for backing up my precious configuration files. Here’s how.

I’ve created a directory called project-dotfiles and within it a directory for each project with dotfiles I want to preserve. Then I moved the dotfiles from my various project directories to the corresponding subdirectory in project-dotfiles. For each project, I ran Stow with the project directory as the target and the project dotfiles directory as the package. For instance,

stow -t ~/code/awesome-project awesome-project

Stow symlinked the files in project-dotfiles/awesome-project to ~/code/awesome-project.

Next Steps

You can also create files that are shared between projects. Suppose you want to include a Vim script useful for Ruby on Rails projects. You can create a ruby-on-rails subdirectory in project-dotfiles, then run

stow -t ~/code/ruby-on-rails-project ruby-on-rails
stow -t ~/code/some-other-project ruby-on-rails

and Stow will symlink the files in your ruby-on-rails package into two different project directories.

One of the best side-effects of using Stow and symlinked dotfiles is that you can edit dotfiles the same way you do now, and the changes show up in your centralized directory, ready to be committed to version control.

Stow has not only cleaned up how my home directory dotfiles are organized, but my project dotfiles as well, and it’s allowed me to delete several scripts I was using to manage all those dotfiles. Everything is a lot more well-organized when it’s properly Stowed.



1 Thanks to Brandon Invergo for bringing it to my attention.