11 ms·
Using GNU Stow to manage your dotfiles
- BruceIV 12y agoLooks useful; I just symlink into a folder on my dropbox, which accomplishes much the same thing with about the same effort.
- pjungwir 12y agoVery nice! This is something I've always meant to set up but never bothered with. He mentions installing different subsets of your dotfiles on different machines. To do that easily and have it "written down", I'd put a Makefile into the dotfiles directory with .PHONY targets for each machine, and have those targets run the right `stow` commands for me.
- sjLonghorn 12y agoYou might also checkout https://github.com/andsens/homeshick https://github.com/andsens/homeshick. Similar idea, but tailored for dotfiles.
- arenaninja 12y agoThank the programming deities for this one. I've been doing a balancing act with VMs lately and I was about to push my dotfiles to github, but it just seemed like a really bad idea
- jryan49 12y agoI've been doing this for a year or two with dropbox. I've tried vcsh and others and stow has been by far the best so far.
- AceJohnny2 12y ago> but many/most dotfiles reside at the top-level of your home directory, where it wouldn't be a good idea to initialize a VCS repository. Right. Which is why I use git with a workspace detached from the git directory. The git directory is in ~/dotfiles/.git, with "git config core.worktree ~", and I set an alias "dgit=git --git-dir ~/dotfiles/.git". The advantage of this method is that there are no symlinks to maintain, however initial clone is a bit painful, since you have to move the files and set the config. It's not perfectly straightforward, but it's as close to it as I could get it.
- emillon 12y agoThat's exactly how vcsh works too.
- zorbo 12y agoThis is great! It fixes the only problem I have with maintaining my dotfiles as a git repo: the .git dir in ~. That interferes with so many things such as the CtrlP vim plugin, the integration of git with the bash prompt and many other things. Thank you for this.
- AceJohnny2 12y agoYeah, the git in the bash prompt thing was the most annoying thing to me, honestly :) Since there is interest, I'll elaborate on the understated "a bit painful" part of moving the files after an initial clone which leaves the files in the ~/dotfiles dir. The problem is that I didn't find an easy "move and overwrite recursively" command in Linux. Here's the magic command from my script: git ls-files --cached -z | rsync -av --from0 --remove-source-files --files-from - ${dir} ~/ && find . -type d -empty -delete To spell it out, it's having git list all the files in the repo (so skipping any unversioned files such as the .git dir itself), using the NUL byte as file termination to avoid any (most?) special character issues in file names, and using rsync to move the files over thanks to --remove-source-files. However rsync doesn't remove empty directories (durr), so have the find do that. Also, you probably want to set "git config status.showUntrackedFiles no" ;)
- mbudde 12y agoI have very similar setup to yours, but my solution is to use a bare repository. To set up dotfiles on a new computer is just $ git clone --bare git@github.com:mbudde/homedir.git .homegit $ git --git-dir=.homegit --work-tree=~ checkout -f # Overwrite existing files $ echo '*' >> .homegit/info/exclude And then I have a simple git wrapper script [1]. I moved from using an alias to a script for some reason I can't remember (and of cause I didn't write it in the commit message -_-). [1] https://github.com/mbudde/homedir/blob/master/usr/bin/hgit https://github.com/mbudde/homedir/blob/master/usr/bin/hgit
- 4ad 12y agoThis makes no sense. Somehow having a versioned dotfiles directory with either a Makefile or a shell script is "hard" because either you need to have Python (no you don't, shell script is fine) or you forget the name of the install script (type ls), but somehow using this software (which needs to be installed) is "easier". With this software you also need to remember the magic invocation, a trivial thing in both scenarios, but nevertheless something the author complained about, and you also need to install stow. Previously the author complained about adding dependencies in the form or Python (which made no sense, but still, he complained about dependencies) but now he adds this new dependency (which is more rare than python anyway...).
- shawndumas 12y agoThis use case is one of the expressed reasons for stow's existence. "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. This is particularly useful [to] facilitate a more controlled approach to management of configuration files in the user's home directory, especially when coupled with version control systems." [1] Installing a single binary might be easier than installing a scripting environment on a server that may have existing versioning considerations. (brew install stow | sudo apt-get install stow) You literally type `stow bash` and you're done. ---- [1]: http://www.gnu.org/software/stow/ http://www.gnu.org/software/stow/
- 4ad 12y agoYou literally type make and you're done too.
- LukaD 12y agoThis is how I manage my dotfiles since I discovered stow a couple of months ago. The only thing that bugs me is that I haven't figured out an elegant way to have some configs include machine specific configs. For example a set of bash aliases that I only use at work but don't want at home. My best idea is to source all files in, say ~/.bashrc.d and put machine specific configs in there... Haven't tried it out yet.
- anu_gupta 12y agoNot sure if this would work with Stow, but in my .bashrc I just do this: if [ -f ~/config/bashrc_$(hostname -s) ]; then source ~/config/bashrc_$(hostname -s) fi this gives me machine specific configs.
- jackalope 12y agoYou can do something similar to target *nix platforms like Darwin|FreeBSD|Linux|NetBSD|OpenBSD with: if [ -f ~/config/bashrc_$(uname -s) ]; then source ~/config/bashrc_$(uname -s) fi
- LukaD 12y agoGreat idea! It wouldn't work for me though as I tend to call all my machines 'fuckup' (I know...) ;)
- RexRollman 12y agoIn that case, you could have it read or check the existence of something else, like a file in /etc.
- mjcarroll 12y agoI also use stow to manage my common personal dotfiles, as well as my employer-specific dtofiles. The way I do this is to keep my general files in my dotfiles repository, but then keep work specific ones in a separate repo (dotfiles-employer). This separate repo has .private versions of all of my commonly used dotfiles (for example .bashrc.private), and my top-level files will check for the existence and source these, if present. Both repos will be installed using stow, with the work dotfiles generally just extending the personal dotfiles.
- cientifico 12y agoFor that use case, I normally use unison: http://www.cis.upenn.edu/~bcpierce/unison/ http://www.cis.upenn.edu/~bcpierce/unison/ Then I have a script to automatically sync that files.
- cjoelrun 12y agoI gave GNU Stow a try, but thought it did too much. Ended up using dotfiles (https://pypi.python.org/pypi/dotfiles https://pypi.python.org/pypi/dotfiles). My dotfiles (https://github.com/cjoelrun/dotfiles https://github.com/cjoelrun/dotfiles). I handle system specific stuff in each config: OS checks in zsh, emacs, tmux configs. Allows me to move between OSX and Arch linux.
- JadeNB 12y ago> I gave GNU Stow a try, but thought it did too much. Not to argue with your experience, but it's hard to see how it could do less—it literally just creates a bunch of symlinks. (It seems to have grown a bunch of options since I last looked at it, but it seems that they can all be ignored if you want simplicity. (I've only ever used `-d`, `-t`, and `-D`.)
- jackalope 12y agoI prefer dedicated repositories (I use mercurial) for each app (vim, mutt, etc.) or context (X11) that include Makefiles for creating the necessary links or handling some environment-specific details. This still allows me to cherry pick what I want on each machine, but keeps the commit history in the appropriate repo.
- jeffreyrogers 12y agoI just have a dotfiles repo on github that I clone to any new computer I'm using. Then make a symbolic link between the dotfiles and the repo (`ln -s ~/dotfiles/.whatever ~/.whatever`). Super simple.
- bradleyland 12y agoThis is almost exactly the same strategy, only stow handles the symlinks for you, so you don't have to go through and `ln -s` all your files/directories. Your dotfiles still go in a git repo.
- Symbiote 12y agoI put the "ln -s" commands in a shell script. git clone ... ~/.my-config ~/.my-config/setup-links Done. Some servers at work don't have Git installed (and certainly not Stow), so I rsync ~/.my-config from my workstation to my home directory. (There's little need for me to edit my .zshrc on a server.)
- barrkel 12y agoI maintain environments on Windows (Cygwin), Linux, OS X and Solaris machines. Some of these are work, some are home. Not all files overlap. Additionally, I have scripts that are only relevant when I have a certain program installed, or a certain source tree available. I ended up spending a weekend writing my own system that composed a PATH, .bashrc, .bash_profile etc. based on machine configuration. A single git clone isn't quite enough, especially if you don't want to smash everything into one repo (I don't have my home stuff installed at work, for example).
- shawndumas 12y agosee jackalope's helpful comment -- https://news.ycombinator.com/item?id=8488828 https://news.ycombinator.com/item?id=8488828
- Symmetry 12y agoSince I have a setup script I run on any new installation creating symlinks from my git repo isn't a big deal. https://github.com/aclough/dotfiles/blob/master/setup.sh https://github.com/aclough/dotfiles/blob/master/setup.sh
- kawsper 12y agoI just move stuff to my home-folder with a very simple Ruby install script. It checks for existence of tools, and if they aren't there they will be installed, and the config files will be overridden. https://gist.github.com/kaspergrubbe/99853334b0e91b540a34 https://gist.github.com/kaspergrubbe/99853334b0e91b540a34
- leourbina 12y agoPersonally I really like https://github.com/thoughtbot/rcm https://github.com/thoughtbot/rcm. It is simple, and to the point. Using it is straightforward, and it has allowed me to change machines and migrate my dotfiles seamlessly.
- Evan-Purkhiser 12y agoA while back I got very interested in cleaning up my configuration files. I wanted to figure out out a way to store all of the configurations I use across multiple machines into a single repository, while at the same time not having to worry about symlinking and installing configurations for things I don't need on a particular machine. I looked at a lot of different things like Stow and homeshick and the like and really didn't like any of the solutions. So I ended up writing my own tool. I've wanted to write up something for it for awhile now and post it around, but I just haven't yet. Anyway, here's my tool: https://github.com/EvanPurkhiser/dots https://github.com/EvanPurkhiser/dots
- andsens 12y agoHi, I'm the maintainer of homeshick and would be very interested in knowing which shortcomings of homeshick motivated you to write your own tool. Could you elaborate?
- hardwaresofton 12y agoI created something a while ago (that I haven't updated in a while, I shamefully admit) that also handles dot files: http://configr.io http://configr.io I also do namespaced dotfile saving (folder by application), but I focused on WGET/CURL-ability (which is unfortunately hard to divine from the current website UI -- the curl command is not obvious, as you have to have content-disposition turned on.
- Lambdanaut 12y agoHandling dotfiles doesn't have to be a hard problem. Here's a simple script I wrote that copies them to and from a git repository. https://github.com/Lambdanaut/dotfiles/blob/master/cp_dotfiles.sh https://github.com/Lambdanaut/dotfiles/blob/master/cp_dotfil...
- mijoharas 12y agoI don't know whether it was just unclear to me or unclear in this article but (after checking man stow), here is the relevant section of the man page that cleared up how it worked for me: The stow directory is assumed to be the value of the "STOW_DIR" environment variable or if unset the current directory, and the target directory is assumed to be the parent of the current directory (so it is typical to execute stow from the directory /usr/local/stow). Each package given on the command line is the name of a package in the stow directory (e.g., perl). By default, they are installed into the target directory (but they can be deleted instead using "-D").
- bgar 12y agoWhat I do is just keep all of the dotfiles in ~/dotfiles and symlink them to the home directory, then I can keep track of them with git. Doesn't have to be any more work than that. Maybe it's not an issue for me because I only use one machine, and when I switch to another, I just pull down my dotfiles from github and symlink them again. I only do this every couple years.
- ibrahima 12y agoThis is what I do as well, and I also have a little script that creates all the symlinks in my home directory as well. Dead simple, and it works. I was hoping Stow would somehow be an improvement over that but I don't really see how it does anything more for you.
- oinksoft 12y agoI agree and think don't understand why you'd want your dotfiles to depend on Make, Ruby/rake, etc. let alone something like Stow. Git and a shell are enough; you can eliminate the Git dependency by packaging from a post-receive hook too.
- anoother 12y agoThe article doesn't explain how stow 'knows' where to place the symlinks. The answer is (of course) in the help output: -d DIR, --dir=DIR Set stow dir to DIR (default is current dir) -t DIR, --target=DIR Set target to DIR (default is parent of stow dir)
- akincisor 12y agoI wrote my own hack to do the same: https://github.com/aksrikanth/settings/blob/master/bin/setup.sh https://github.com/aksrikanth/settings/blob/master/bin/setup... It works well enough, and I have to set it up once.
- staticshock 12y agoI've been reasonably happy with my solution to this, which is https://github.com/staticshock/seashell https://github.com/staticshock/seashell It's a fully contained Makefile that gives my dotfiles repo `make && make install` semantics. `make` initializes whatever needs to initialize locally on that system, and `make install` creates all the necessary symlinks in the $HOME directory.
- zyxley 12y agoStow also goes nicely with managing a directory in Dropbox for syncing game saves, app config data, etc, for apps that don't have any native support for cross-machine syncing but still work well enough when you fake it with symlinks.
- slavik81 12y agoI have no desire to use this for dotfiles, but GNU Stow sounds like it solves a real problem for me with the programs I install from source. Being able to uninstall without manually tracking down each file would be wonderful.
- mw42 12y agoFor installation from source I use CheckInstall [1]. It will keep track of all the files created during a make install, and create a standard deb or rpm package that can then be installed and removed by the distribution's package manager. [1] http://www.asic-linux.com.mx/~izto/checkinstall/docs/README http://www.asic-linux.com.mx/~izto/checkinstall/docs/README
- KC8ZKF 12y agoRCS is a good option for dotfiles. RCS is a version control system that is useful for individual files which must remain in a specific location.
- seanp2k2 12y agoMaybe I just don't have enough dotfiles, but I just symlink mine into Dropbox.
- deepakprakash 12y agoRecently spent some time organizing my dotfiles and discovered fresh[1] which I've been using to great success. Both for servers I manage and on my mac. The fact is that most people are going to be reusing (and probably be better of) a lot of code from other well tested dotfiles. `fresh` lets you pick and choose what you want directly from other's repos in addition to adding whatever you want and produces a single bundle (or multiple if you need it). As far as I can tell, its a self contained shell script and does not have any dependencies (if that is a concern). Its definitely worth checking out. [1] https://github.com/freshshell/fresh https://github.com/freshshell/fresh
- dvdkhlng 12y agoI use a similar construct for managing config files (mostly the stuff that goes to /etc/*): put all the config for a specific program (or problem) into a VCS-handled directory, then add a Makefile with an "install" target that copies everything into its place. Using GNU install (instead of ln or cp) allows for copying files (and creating directories) with fine control about permissions and ownership. This can also be done recursively: toplevel Makefile for a machine's configuration files calls the sub-makefiles that install apache, asterisk, openvpn configurations etc.
- JadeNB 12y agoNote that this was an official use case for Stow for at least a year before the linked post: This is particularly useful for keeping track of system-wide and per-user installations of software built from source, but can also facilitate a more controlled approach to management of configuration files in the user's home directory, especially when coupled with version control systems. (from https://www.gnu.org/software/stow https://www.gnu.org/software/stow), where "especially …" links to http://lists.gnu.org/archive/html/info-stow/2011-12/msg00000.html http://lists.gnu.org/archive/html/info-stow/2011-12/msg00000.... (There's nothing wrong with re-discovering it, of course!)