- GNU Stow allows you to centralize dotfiles in a single repository and link them to the system using symlinks in a clean and reversible way.
- There are two main organizational models: unified repository and package-based approach, with different levels of modularity.
- Combining Stow with Git makes it easy to version, back up, and replicate configurations across multiple machines with just a few commands.
- Good practices such as using .stow-local-ignore, respecting the directory structure, and avoiding mixing real files and symlinks ensure a robust workflow.

If you use Linux, macOS or Termux on Android Every day, sooner or later, you end up accumulating a bunch of configuration files scattered all over your home directory: .zshrc, .bashrc, .config, nvim, Hyprland, etc. When you only have one computer you can survive, but as soon as you work with several computers or servers, keeping all this up to date is a whole different story.
In this context, the following comes into play GNU Stow, a symbolic link manager which has become one of the cleanest, simplest, and most reversible ways to manage dotfiles. It's not the only possible approach (there are alternatives like Git bare repositories, yadm, Chezmoi, Dotbot…), but its minimalist philosophy is a perfect fit if you want something powerful without too much fuss behind it.
What exactly is GNU Stow and why is it useful for managing .dotfiles?
GNU Stow is, originally, a “symlink farm manager”A tool designed to organize multiple file "packages" in one location and expose them in another directory using symbolic links. Although it was conceived for managing local software installations, the community quickly adopted it for handling dotfiles because it fits perfectly.
The basic idea is very simple: you save all your settings in a single file. central repository (for example ~/dotfiles)These files are structured as if they were going to live in your home directory, and Stow takes care of creating symlinks from your home directory to those files. This allows you to version them with Git, clone them on multiple machines, and reproduce your environment with one or a few commands.
Something important: Stow is not “a dotfile tool” in the strict senseIt doesn't store its own state, maintain a database, use templates, or employ encryption. It simply creates and deletes symbolic links following a directory structure. This is precisely why it's so easy to understand and revert.
This minimalist philosophy contrasts with more complex solutions like Chezmoi, which add templates, secret management, integration with password managers, and a more automated workflow. With Stow, you're in charge: everything is in the file system and your Git repo, without intermediate layers.
Advantages of using Stow compared to other ways of managing dotfiles
Before Stow became popular, many people managed their dotfiles using "cp" and "mv" commands.Configurations were copied manually between computers, or a repository was maintained that required constant updating. It was easy to end up with multiple versions of the same file and not know which one was actually in use.
With Stow, all the “real” files live in your dotfiles directory and Your $HOME directory only contains symbolic linksThis means that when you edit, for example, ~/.zshrc, you're actually modifying the file inside your repository. There are no duplicates, no desynchronization, and no need to remember what to copy and where.
Another clear advantage is reversibility: If you want to undo what Stow has done, simply run “stow -D package” From your dotfiles folder, delete all symbolic links created for that package. This does not delete your actual configurations (which remain in the repository), it only removes the symbolic links to the target package.
Furthermore, Stow works very well with Git: You can version ~/dotfiles like a normal repositoryYou can make commits, create branches, use GitHub or GitLab as a backup, etc. Stow automatically ignores the .git folder when generating links, so you don't run the risk of filling your $HOME directory with internal Git files.
Finally, unlike other heavier tools, Stow is usually available on any Linux distro and even on macOS via HomebrewIt's basically a script written in Perl with very few dependencies and works in any environment UNIX.
Common alternatives: Git bare, yadm, Chezmoi, Dotbot…
When you consider managing dotfiles seriously, the same list of options usually appears: Git repository “bare”, yadm, Dotbot, Chezmoi, plus StowEach approach has its own style and audience, so it's important to place Stow within that ecosystem.
The method of bare Git repository This involves initializing a repository without an associated working tree and using Git aliases so that $HOME itself acts as the working directory. Advantages: there are no symbolic links, Git works directly on your actual files, and the command flow is very simple. Many users comment that they were surprised by how easy it was to follow a "DT"-style tutorial and have it working without touching any symlinks.
Moreover, Chezmoi focuses entirely on advanced dotfile managementFeatures include: templates for handling differences between machines, integration with password managers, file encryption with GPG or AGE, hooks for running scripts during installation, robust cross-platform support, and more. It's ideal if you need managing secrets, supporting many different systems, or automating complex installations.
Stow is at the opposite extreme: He knows nothing about secrets, templates, or scriptsIt simply creates clean symlinks. For many users, that's a virtue: less to learn, less "magical" behavior, and greater transparency. If you need heavy conditional logic, Chezmoi is probably a better fit; if you just want to keep your configurations organized without complications, Stow is a very reliable classic.
There are also tools like Yadm or Dotbot, which automate tons of tasks (including running post-installation scripts, cloning repositories, installing packages, etc.). Even so, a good number of developers still prefer Stow because it is easy to audit, integrates well with existing Git workflows, and adapts seamlessly to both minimalist setups and more demanding desktop environments.
Organizational approaches: unified repository vs package-based repository
When you start using Stow, one of the first decisions you have to make is How to structure your dotfiles repositoryBroadly speaking, there are two popular patterns: the unified approach and the package-based approach.
In the unified model, your dotfiles repository has virtually the same form as your $HOME directory: files like .bashrc or .zshrc in the root, and folders like .config/nvim or .config/lazygit insideSomething like this:
dotfiles-unified/
├── .bash_aliases
├── .bash_completion/
│ └── alacritty.bash
├── .bashrc
└── .config/
├── lazygit/config.yml
└── nvim/…
With this design, you enter the repo folder, you run stow. and suddenly, All your settings are linked to your $HOME directoryIt's incredibly convenient when you want to clone your entire environment to a new machine with a single command and don't need much differentiation between systems.
The package-based approach works differently: You create a subdirectory per “module” or applicationFor example, one for bash, another for nvim, another for lazygit, another for zsh, another for Hyprland, etc. Each directory contains the files with the full path they would have in your $HOME directory. Something like:
dotfiles-packages/
├── bash/
│ ├── .bash_aliases
│ ├── .bash_completion/alacritty.bash
│ └── .bashrc
├── lazygit/.config/lazygit/config.yml
└── nvim/.config/nvim/…
With this scheme you can decide which packages to "activate" on each machine: On one machine you run “stow bash nvim lazygit”, on another perhaps “stow zsh nvim”This is very useful when you work with multiple distributions (for example, Arch on one PC and Fedora on another) or with different shells (fish on one machine, bash on another) and you want to keep everything in a single repository, but choose what to apply in each environment.
The catch? It's a bit more complex: "Stow" is no longer enough. And that's it; you just need to remember which packages you need.Alternatively, you can create a small script per machine that calls Stow with the appropriate combination. Even so, many users prefer this fine-grained control, especially if they have highly specific software on each machine.
How Stow works internally: the concept of directory “mirroring”
The key to understanding Stow is its system of mirror directory structures (directory mirroring)Stow does not guess paths; it simply looks at how the files are organized within the "package" and places the corresponding symlinks in the destination directory.
For example, if an application expects its configuration in:
~/.config/ghostty/
Your module inside ~/dotfiles should have exactly that relative path:
~/dotfiles/ghostty/.config/ghostty/
Anything you place inside (for example, a file called config) will be linked by Stow to the correct location. This way, Ghostty will continue to read its configuration from ~/.config/ghostty/config, but that file will actually point to the one stored in your repository.
This pattern repeats for any tool: Waybar would have something like ~/dotfiles/waybar/.config/waybar/, Neovim ~/dotfiles/nvim/.config/nvim/and so on. The process is extremely uniform, making scaling to more programs almost mechanical.
For dotfiles that live directly in $HOME (such as ~/.gitconfig or ~/.zshrc) the logic is identical: Within the git package you will have a .gitconfig file in the root directoryStow will then create the link in your home directory when you run “stow git”.
Step by step: setting up a dotfiles repository with Stow
The typical workflow with Stow is simple and can be summarized in a few well-defined steps, both on Linux and macOS. The important thing is to get used to the fact that the "real" files are always inside the repo. and not scattered throughout your $HOME.
To begin, create the directory where your dotfiles will live. Many people use ~/.dotfiles or ~/dotfilesThe name is the least important thing:
mkdir -p ~/.dotfiles
cd ~/.dotfiles
Then Move your current configuration files to the repositoryFor example, if you have a .bashrc file in your home directory and you want to manage it with Stow, you could do the following:
mv ~/.bashrc ~/.dotfiles/.bashrc
If you prefer the package-based approach, instead of leaving the file in the root of the repo, you would put it in a "bash" folder, keeping the full path:
mkdir -p ~/.dotfiles/bash
mv ~/.bashrc ~/.dotfiles/bash/.bashrc
The procedure with configurations that are inside .config is analogous: You replicate the directory structure within the repoFor example, for Neovim you could have:
mkdir -p ~/.dotfiles/nvim/.config/nvim
mv ~/.config/nvim/* ~/.dotfiles/nvim/.config/nvim/
Once the files are in your repository, it's a good idea to delete or rename the originals in $HOME to avoid conflicts. Later, Stow will recreate the symbolic links in the paths where applications expect to find their configs.
Install GNU Stow on different platforms
The installation of Stow varies slightly depending on the platform, but overall it is extremely straightforward. On macOS, it's common to use Homebrew., the most widespread package manager on this system:
brew install stow
In Linux distributions like Debian or Ubuntu, the usual practice is to use apt:
sudo apt install stow
En Arch Linux and derivatives, you can find it in the official repositories and it is installed with pacman without much mystery:
sudo pacman -S stow
Once installed, you have the "stow" command in your PATH. There are no daemons or background services, just a binary that runs when you need it.You can check that everything is working correctly with a "stow --version" command and you're done.
On systems where you already use tools like Oh My Zsh, Stow fits in very well: you can keep both the .zshrc file and the configuration of plugins and themes in your central repo and apply everything with a couple of commands. Many users with several Mac Or, using a mix of Linux and macOS, they say that this way they manage to have the same shell and the same prompt everywhere..
Ignore unwanted files with .stow-local-ignore
One of the fine details of Stow is the ignore system. By default, Stow already ignores certain typical version control files such as .git, .gitignore, .gitmodules, CVS directories, RCS, etc. However, there are situations where you need more specific control, for example on macOS with the infamous .DS_Store.
Stow allows you to create a file called .stow-local-ignore in the directory from which you run the command. That file defines which patterns should be ignored locally. Once you create it, you stop using the default ignore list, so you have to add them yourself and include any extras.
A typical example of .stow-local-ignore content would include comments and patterns for CVS conflicts, Emacs backups, version control files, and at the end .DS_Store so that Stow doesn't complain or try to link those files generated by Finder:
# Comentarios y líneas en blanco permitidas
RCS
.+,v
CVS
\.#.+
\.cvsignore
\.svn
_darcs
\.hg
\.git
\.gitignore
\.gitmodules
.+~
\#.*\#
^/README.*
^/LICENSE.*
^/COPYING
.DS_Store
Thanks to this, you prevent Stow from trying to create completely irrelevant file links and You avoid annoying mistakes when stowearing or unstowearing packagesThis is especially useful if you frequently browse your repository using graphical interfaces that generate auxiliary files.
Remember that Stow's ignore is independent of the .gitignore you use in your repository: The first controls what is linked, the second what is versioned.Between the two, you can fine-tune the behavior of both Stow and Git.
Basic Stow usage: linking and unlinking configuration packages
With everything prepared, Stow's daily operations are very concise. You should always run Stow from within your dotfiles repo directory, not from your $HOME or from arbitrary routes, so that the relative routes it generates make sense.
Imagine you already have a module called “ghostty” in ~/dotfiles/ghostty/.config/ghostty with your configuration file. Once it's in the repository, you can store it with:
cd ~/dotfiles
stow ghostty
This command causes symbolic links to appear on your system from ~/.config/ghostty to the files located in ~/dotfiles/ghostty/.config/ghostty. If you do an “ls -l ~/.config/ghostty” you will see mushrooms (->) indicating the target of each symlinkconfirming that everything is correctly linked.
If you opt for a unified approach and want to link everything at once, You can run “stow .” from the root of the repoStow will interpret each subdirectory as a package or directly work on the structure if you have a flat one, and create symlinks for everything that fits.
To revert a specific package, simply call Stow with the -D option (for "delete" in the tool's terminology). For example:
cd ~/dotfiles
stow -D ghostty
That removes the symlinks I had created for that module without touching the original files that are still in the repository. It's a very clean way to "uninstall" configurations from a specific machine. without losing them completely.
It is crucial to avoid a very common mistake: Do not run Stow from $HOME or from other folders outside the repoIf you do this, you risk creating links in unexpected places and ending up with your home directory cluttered with things that don't belong. Always: `cd` to the repository, then `stow`.
Integrate Git and GitHub into your dotfile workflow with Stow
The beauty of this whole setup is combining Stow with Git so that your dotfiles are versioned, remotely backed up, and easily replicable on other machinesThe process is very straightforward and no different from any other project you manage with Git.
From your dotfiles folder, initialize a new repository if you haven't already done so:
cd ~/dotfiles
git init
From there you can add your files, make commits, and work with branches as usual. A possible Boot could be:
git add .
git commit -m "Primer commit de mis dotfiles"
The next step is usually to create a repository on GitHub, GitLab, or another service and add it as a remote. Something like this:
git remote add origin git@github.com:tuusuario/dotfiles.git
git push -u origin main
Keep in mind that, although some people publish their dotfiles in public repositories, The most prudent course of action is to use private repositories if you handle sensitive data. or routes that could reveal too much personal information. In any case, you can supplement this with external encryption for secrets if necessary.
To fine-tune what gets versioned, it's also a good idea to have a .gitignore file in the repository where you add, for example, .DS_Store or other files that you don't want to upload. Stow already ignores .git by itself, but Git knows nothing about .stow-local-ignoreTherefore, the two files serve different purposes and complement each other well.
The day-to-day routine is very clear: You clone your dotfiles repository to a new machine, install Stow, run “stow .” or “stow package1 package2…” and you have your replicated environmentIf you later change your Neovim configuration or your .zshrc, you commit and push, and on the other machines a simple git pull followed by stow is enough to update links if you have added new files or packages.
Passionate writer about the world of bytes and technology in general. I love sharing my knowledge through writing, and that's what I'll do on this blog, show you all the most interesting things about gadgets, software, hardware, tech trends, and more. My goal is to help you navigate the digital world in a simple and entertaining way.