Michał Sapka's website

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?

GNU Stow is a symlink farm. This means, that it’s a system aimed at automating creating of those symlinks.

GNU Stow website

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.