Stow and replace existing dotfiles

1.5k views Asked by At

I'm using most recommended method of managing dotfiles on mac by using stow. e.g., https://alexpearce.me/2016/02/managing-dotfiles-with-stow/

I found that it works great and does what I need to if I'm doing a clean install. I have a folder structure that looks like this inside my ~/dotfiles folder

.
├── install.sh
└── zsh
    └── .zshrc

when I run

stow zsh

It correctly sets the symlink in place from ~/.zshrc

.zshrc -> dotfiles/zsh/.zshrc

Problem however is if .zshrc is already present in the home folder, then stow will not override it with symlink. Instead it will just throw and error.

WARNING! stowing zsh would cause conflicts:
  * existing target is neither a link nor a directory: .zshrc
All operations aborted.

I understand I can manually "rm ~/.zshrc" file before running stow and will work.

I'm trying to see if there is cleaner way of setting up symlinks without having to manually run rm command for all the existing dotfiles.

1

There are 1 answers

2
lorenzo-bettini On

Assuming you have the dotfiles in a Git repository and that you have committed the current changes, you can use this "trick": stow provides this option:

--adopt               (Use with care!)  Import existing files into stow package
                      from target.  Please read docs before using.

By looking at the man page (https://www.gnu.org/software/stow/manual/html_node/Invoking-Stow.html):

When stowing, if a target is encountered which already exists but is a plain file (and hence not owned by any existing stow package), then normally Stow will register this as a conflict and refuse to proceed. This option changes that behaviour so that the file is moved to the same relative place within the package’s installation image within the stow directory, and then stowing proceeds as before. So effectively, the file becomes adopted by the stow package, without its contents changing.

So, assuming ~/.zshrc is an existing file, and you have ~/dotfiles/zsh/.zshrc, you run (instead of stow zsh, which would cause a conflict):

stow --adopt zsh

This will replace your ~/dotfiles/zsh/.zshrc with the contents of the existing ~/.zshrc and will create the link:

~/.zshrc -> ~/dotfiles/zsh/.zshrc

Now, you just need to restore your dotfiles/zsh/.zshrc, e.g., with git --reset hard.

In fact, the manual also says:

This is particularly useful when the stow package is under the control of a version control system, because it allows files in the target tree, with potentially different contents to the equivalent versions in the stow package’s installation image, to be adopted into the package, then compared by running something like ‘git diff ...’ inside the stow package, and finally either kept (e.g. via ‘git commit ...’) or discarded (‘git checkout HEAD ...’).