Managing dotfiles with GNU Stow
If you are working with linux/bsd based system, you are most likely accustomed to managing your configs with dotfiles. And you most likely have them stored with Git. But there is the never ending problem of how to actually use them. I have moved management of this under GNU Stow.
Let’s take a very typical dotfiles repository.
./nvim/init.lua
./tmux/tmux.conf
You want to have those files available as
~/.config/nvim/init.lua
~/.tmux.conf
The most popular approach would be to symlink the files under the expected location. We could also copy the files every time something changes, but that would be crazy. Are we the stuck with having to do those symlinks manually every time we install a new machine or create a virtual one? And what if we have dozens of such configs stored under git?
Symlink farm
GNU Stow is a symlink farm. This means, that it’s a system aimed at automating creating of those symlinks.
For Stow, the dotfiles directory is called “Stowed” directory. Now comes the cool part. Each folder in the Stowed directory (called “Package directory”) stores a separate directory tree. GNU Stow will join all those separate trees and create a proper structure under Target Directory, which by default is the parent of Stowed directory. Let’s look at example.
~/target/stow/one/config/one.conf
~/target/stow/two/config/two.conf
~/target/stow/three/config/three.conf
So, our home director now has a “Target” directory, which has a “Stow” directory. The Stow directory stores three configs which we want to sylink as
~/target/config/one.conf
~/target/config/two.conf
~/target/config/three.conf
Let’s stow the first one
cd ~/target/stow
stow one
And see what happened
cd ~/target
ls -lA
We get somethine like
lrwxrwxrwx 1 msapka wheel 15 Jun 9 23:01 config -> stow/one/config
drwxr-xr-x 5 msapka wheel 4096 Jun 9 22:55 stow
Stow created a config symlink in the target directory. Very cool, but it gets cooler! Let' stow the second one
cd ~/target/stow
stow two
and what we get
drwxr-xr-x 2 msapka wheel 4096 Jun 9 23:03 config
drwxr-xr-x 5 msapka wheel 4096 Jun 9 22:55 stow
Our config is no longer a symlink, but a real folder. Let’s see what’s inside here.
cd config
ls -lA
lrwxrwxrwx 1 msapka wheel 27 Jun 9 23:03 one.conf -> ../stow/two/config/one.conf
lrwxrwxrwx 1 msapka wheel 26 Jun 9 23:03 two.conf -> ../stow/one/config/two.conf
We have our two configs, but what has happened? Stow looked at both sub trees for “one” and “two"m and joined then in a way, that is possible. The only way for one.conf and two.conf to exist in config is if config is a normal directory. Extremely cool!
Let’s image that our target is actually homedir, so we have a ~/dotfiles directory. Then each package directory can mimic the tree struture of the actual config! Coming back to our example, we can have a
~/dotfiles/tmux/.tmux.conf
~/dotfiles/nvim/.config/nvim/init.lua
Then, after stowing both packages we have symlinks under our desired
~/.config/nvim/init.lua
~/.tmux.conf
GNU Stow is a very simple tool. All we understand what will happen with each sub tree.