GNU Stow is a symlink farm manager originally designed for managing software
installations in /usr/local. Its elegant approach to directory tree
management makes it perfect for dotfile organization, providing a powerful
solution to a common developer problem.
Before diving into why Stow excels at dotfile management, understanding the
problem space is important. Developers accumulate configuration files
(dotfiles) that customize their tools - .bashrc, .gitconfig, .vimrc,
and many others. Managing these files across multiple machines, backing them
up, and sharing them becomes challenging without proper tooling.
Stow operates on a straightforward principle: it manages symlinks between a "stow directory" (your dotfiles repository) and a "target directory" (usually your home folder).
graph LR
A[Stow Directory] -->|Creates Symlinks| B[Target Directory]
subgraph "~/.dotfiles (Stow Dir)"
C[git/.gitconfig]
D[vim/.vimrc]
E[zsh/.zshrc]
end
subgraph "~/ (Target Dir)"
F[.gitconfig]
G[.vimrc]
H[.zshrc]
end
C -.->|Symlink| F
D -.->|Symlink| G
E -.->|Symlink| H
style A fill:#e8f5e9
style B fill:#e3f2fd
Stow's intelligence lies in its "folding" algorithm:
- Empty Target: Creates a symlink to the source directory
- Existing Symlink: Updates if it points to stow, conflicts otherwise
- Real Directory: "Folds" by descending into both directories
- Real File: Reports a conflict
This algorithm allows Stow to intelligently merge directory trees while maintaining clear ownership of files.
After evaluating numerous dotfile management solutions, we selected GNU Stow for several compelling reasons:
Advantages:
- Simplicity: No configuration files, no complex setup.
- Transparency: Creates standard symlinks - no magic.
- Modularity: Natural package-based organization.
- Conflict detection: Prevents accidental overwrites.
- Reversibility: Unstow and restore original state.
- Ubiquity: Available in most package managers.
- Maturity: Stable tool with decades of development.
Trade-offs:
- No templating: Can't customize files per machine.
- Manual operations: Requires explicit stow/unstow commands.
- Symlink limitations: Some tools don't follow symlinks.
- No encryption: Secrets need separate handling.
| Solution | Pros | Cons | Why not chosen |
|---|---|---|---|
| Bare Git Repo | No symlinks, direct tracking | Complex setup, error-prone commits | Too error-prone for team use |
| Dotbot | YAML configuration, plugins | Additional dependency, configuration complexity | Over-engineered for our needs |
| Homesick | Ruby-based, git integration | Ruby dependency, less flexible | Language-specific dependency |
| Manual scripts | Complete control | Maintenance burden, reinventing the wheel | Too much custom code |
| rcm | Thoughtbot's solution, tags | Less intuitive than stow | Stow's simplicity wins |
Stow encourages organizing dotfiles by application:
dotfiles/
├── git/
│ ├── .gitconfig
│ └── .gitignore_global
├── vim/
│ ├── .vimrc
│ └── .vim/
│ ├── colors/
│ └── plugins/
└── zsh/
├── .zshrc
└── .zshenv
This mirrors how system packages are organized and makes selective installation trivial.
Modern applications follow the XDG specification:
dotfiles/
└── app/
└── .config/
└── app/
├── config.yml
└── themes/
Stow handles nested directories elegantly, creating parent directories as needed.
When starting fresh with existing dotfiles:
# Move existing files into repo
mv ~/.gitconfig ~/.dotfiles/git/
# Create symlink
stow git
# Or adopt existing files
stow --adopt git # Moves existing files into stow directoryThe bare git repo method tracks files directly:
git --git-dir=$HOME/.dotfiles --work-tree=$HOME add .bashrcWhy Stow is better:
- Clear separation between tracked and untracked files.
- No risk of accidentally committing sensitive files.
- Easier to understand what's managed.
- Natural package organization.
Tools like chezmoi, dotbot, or yadm offer features like:
- Templating
- Encryption
- Auto-commit
- Machine-specific configs
Why Stow is better (for our use case):
- Zero configuration required.
- No abstraction layer to learn.
- Standard Unix tools (just symlinks).
- Debug issues when things go wrong.
- No vendor lock-in.
Many developers write custom scripts:
ln -sf $DOTFILES/vimrc ~/.vimrc
ln -sf $DOTFILES/bashrc ~/.bashrcWhy Stow is better:
- Handles directory creation.
- Conflict detection.
- Rollback support.
- Maintains symlink farm consistency.
- Battle-tested edge case handling.
When Stow encounters directories, it "folds" them:
Initial state:
~/.config/
└── existing-app/
└── settings.ini
Stow package:
myapp/
└── .config/
└── myapp/
└── config.ini
After stowing:
~/.config/
├── existing-app/
│ └── settings.ini
└── myapp -> ~/.dotfiles/myapp/.config/myapp
This intelligence prevents unnecessary directory symlinks while maintaining organization.
Stow's conflict handling ensures safety:
$ stow vim
WARNING! stowing vim would cause conflicts:
* existing target is neither a link nor a directory: .vimrc
All operations aborted.Resolution strategies:
- Backup and remove:
mv ~/.vimrc ~/.vimrc.bak && stow vim - Adopt existing:
stow --adopt vim - Force (dangerous):
stow --override=.* vim
- Symlink overhead: Negligible (one extra inode lookup).
- Stow operation speed: O(n) where n is number of files.
- Memory usage: Minimal, processes one file at a time.
- Disk usage: Only inodes for symlinks.
- Clear boundaries: Obvious what's version controlled.
- No execution: Stow just creates symlinks.
- Permission preservation: Symlinks don't change file permissions.
- Audit trail: Git history shows all changes.
- Symlink attacks: Mitigated by user-only operations.
- Secret management: Must handle separately from Stow.
- Public repos: Risk of accidentally committing secrets.
- Never stow directories containing secrets.
- Use
.gitignoreaggressively. - Regular security audits of public repos.
- Consider private repos for sensitive configs.
- New machine setup: Clone and stow - minutes not hours.
- Experimentation: Unstow to test vanilla configs.
- Sharing: Colleagues can selective adopt your tools.
- Backup: Natural version control through Git.
- Shared configurations with personal overrides.
- Onboarding with selective adoption.
- No forced tool choices.
- Learn from others' setups.
GNU Stow strikes the perfect balance between simplicity and functionality for dotfile management. While it lacks advanced features like templating or encryption, its Unix philosophy approach - do one thing well - makes it an ideal choice for developers who value:
- Simplicity over feature richness.
- Transparency over abstraction.
- Stability over innovation.
- Standards over proprietary solutions.
For teams and individuals managing dotfiles, Stow provides a robust, understandable, and maintainable solution that stands the test of time.