Manage Your Dotfiles with GNU Stow
Stop copying config files by hand. GNU Stow creates symlinks from a single git-tracked directory — one command, no scripts, no hassle.
I was thinking about tracking my dotfiles for a few days. After exploring how others track their configs, I came across GNU Stow. It lets you manage configuration files across machines using symlinks — without writing a single custom script.
Instead of manually copying dotfiles between machines, I keep them in a single git repository (~/dotfiles) and use Stow to symlink everything into place.
The concept
Stow relies on a simple directory tree. You create a stow directory (~/dotfiles), and inside it you create subdirectories for each package (e.g., bash, vim, tmux). When you run stow, it mirrors every file under the package directory into the parent of the stow directory (typically $HOME).
# Example directory structure:
# ~/dotfiles/
# ├── zsh/
# │ └── .zshrc
# ├── tmux/
# │ └── .tmux.conf
# └── nvim/
# └── .config/
# └── nvim/
# After running `stow .` from ~/dotfiles:
# ~/
# ├── .zshrc -> ~/dotfiles/zsh/.zshrc
# ├── .tmux.conf -> ~/dotfiles/tmux/.tmux.conf
# └── .config/
# └── nvim/ -> ~/dotfiles/nvim/.config/nvim/Stow always maps the content of the stow directory to the target directory (defaults to the parent of the stow directory). Combine this with a clean git repo and you never lose a config again.
Basic usage
# Create your central dotfiles directory
mkdir ~/dotfiles
# Create a package directory for bash
mkdir ~/dotfiles/bash
# Move your existing .bashrc into the package directory
mv ~/.bashrc ~/dotfiles/bash/
# Navigate into the stow directory and symlink the package
cd ~/dotfiles
stow bash
# Now ~/.bashrc is a symlink pointing to ~/dotfiles/bash/.bashrc!If you are running from outside the stow directory, use the -d and -t flags:
stow -d ~/dotfiles -t ~ bash-d ~/dotfiles— the stow directory-t ~— the target directory (your home folder)bash— the package to symlink
Advanced commands
# Add a new file to a package later? use Restow (-R)
# It removes old symlinks and creates new ones in one shot:
stow -R bash
# Completely remove symlinks for a package with Delete (-D):
stow -D bash
# Dry-run (-n / --no) prints what would happen without doing it:
stow -n -v bash
# The -v (verbose) flag is essential here to see what Stow would do.
# Stow multiple packages at once:
stow bash vim git
# Stow every package in the current directory:
stow *Dealing with conflicts and ignoring files
Stow never silently overwrites. If a real file already exists where a symlink should go, it throws an error:
# WARNING: in target home:
# * existing target is not owned by stow: .bashrcFix it by removing or backing up the conflicting file first:
mv ~/.bashrc ~/.bashrc.backup
stow bashSometimes you want Stow to ignore certain files inside a package — a README.md, .git, or .DS_Store:
stow --ignore="README.md" bashTo avoid typing ignore flags every time, create a .stowrc file inside ~/dotfiles:
echo "--ignore=README.md" > ~/dotfiles/.stowrc
echo "--ignore=\\.git" >> ~/dotfiles/.stowrc
echo "--ignore=\\.DS_Store" >> ~/dotfiles/.stowrcStow reads .stowrc automatically whenever you run it from the stow directory.
Summary of flags
| Command | Meaning |
|---|---|
stow bash | Symlink everything under bash/ to the target |
stow -R bash | Restow: rebuild symlinks (clean + create) |
stow -D bash | Delete: remove all symlinks for the package |
stow -n -v bash | Dry-run with verbose output |
stow -d DIR -t TARGET PACKAGE | Specify stow dir, target dir, and package |