How I use GNU Stow to organize my dotfiles
4 mins read
#dotfiles
#linux
#ricing
Introduction
Over the past year, I’ve gone through multiple solutions for managing my dotfiles. From using bare repositories to tools like yadm. However, none felt efficient enough for my needs. Knowing how symlinks work, I remembered reading about using them to manage dotfiles and decided to explore this idea further. That’s how I discovered GNU stow.
Dotfiles
As an average Arch Linux enjoyer, I do have some configs laying around in my home
directory, you can find my dotfiles repository on GitHub. Here’s how the repository is organized:
$ tree ~/.dotfiles/home/ouassim/.dotfiles├── alacritty├── flameshot├── git├── i3├── lazygit├── nvim├── picom├── polybar├── ranger├── rofi├── tmux├── wal├── zed└── zsh
Each directory groups related configurations, but the structure doesn’t directly affect the output.
About GNU Stow
GNU Stow might not immediately seem like a natural fit for managing dotfiles, but it’s surprisingly effective. According to its official description:
GNU Stow is a symlink farm manager which takes distinct packages of software and/or data located in separate directories on the filesystem, and makes them appear to be installed in the same place.
In simpler terms, Stow mirrors the structure of one directory into another by creating symbolic links, making it perfect for managing a version-controlled directory of dotfiles and linking them to their appropriate locations.
How GNU Stow Works
To use Stow effectively, it’s helpful to understand these concepts:
- Package: A set of files or directories to be “installed.” For dotfiles, this is a folder containing related configuration files.
- Stow directory: The parent directory holding one or more packages.
- Target directory: The location where symlinks will be created.
When you “stow” a package, it creates symlinks in the target directory that point into the package.
Let’s say I have my dotfiles repository located in ~/.dotfiles
. Within this repository, I have a zsh
package, containing the .zshrc
dotfile:
$ pwd/home/ouassim/.dotfiles # <- repository
$ find zshzsh # <- packagezsh/.zshrc # <- dotfile
The target directory is my home
directory, as this is where the symlinks need to be created. I can now stow the zsh
package into the target directory like so:
stow --target=/home/ouassim zsh
Stow will now create appropriate symlinks of the package into the target directory:
$ ls -l ~/.zshrclrwxrwxrwx 1 ... /home/ouassim/.zshrc -> .dotfiles/zsh/.zshrc
Note that you can stow packages that contain several files or even a complex directory structure. Let’s look at the configuration for neovim which lives below ~/.config/nvim
:
$ pwd/home/ouassim/.dotfiles
$ find nvimnvimnvim/.confignvim/.config/nvimnvim/.config/nvim/init.lua...
To stow the neovim package:
stow nvim
Verify the symlink:
$ ls -l ~/.config/nvimlrwxrwxrwx 1 ... nvim -> ../.dotfiles/nvim/.config/nvim
Removing Symlinks
To remove a package’s symlinks (unstow), use the -D
or --delete
option:
# unstow zsh packagestow -D zsh
This removes the symlink:
$ ls -l ~/.zshrcls: cannot access '/home/ouassim/.zshrc': No such file or directory
Ignoring files and directories
Stow, by default, ignores certain files and directories, as defined in its built-in ignore list. You can customize this behavior by adding a .stow-local-ignore
file in your stow directory.
The default ignore file includes:
# Comments and blank lines are allowed.
RCS.+,v
CVS\.\#.+ # CVS conflict files / emacs lock files\.cvsignore
\.svn_darcs\.hg
\.git\.gitignore\.gitmodules
.+~ # emacs backup files\#.*\# # emacs autosave files
^/README.*^/LICENSE.*^/COPYING
Automating with a Makefile
To simplify the process, I use a Makefile
in my dotfiles repository:
all: stow --verbose --target=$$HOME --restow */
delete: stow --verbose --target=$$HOME --delete */
The --restow
flag ensures outdated symlinks are removed before creating new ones. Updating or cleaning up my dotfiles has become as simple as:
make # Update symlinksmake delete # Remove all symlinks
Version Controlling Your Dotfiles
Using Git to track your dotfiles helps keep changes organized and enables easy synchronization across machines:
git initgit add .git commit -m "storing initial dotfiles"
Add a .gitignore
to exclude unwanted files and a README.md
to document your setup.
Conclusion
I hope this has helped you understand better how to manage your dotfiles. While this method may not be for everyone, it’s my preferred approach.
You can check out my dotfiles repository here. It’s a work in progress, but it might give you some inspiration.
Thanks for reading, PEACE ✌️.