Manage dotfiles using vcsh and mr
hackDevelopers are very picky about their working environment. We may consolidate
various .
files tailed for our tastes over years and track the change in a
version control system, preferably git
. Unfortunately, git or other VCS is not
designed to maintain multiple working copies in a single directory. We may
end up copying or linking the dot files to the home directory, like dfm
does. The more external projects are added as
submodule or
subtree, the harder to manage. The
last straw to me is that the monolithic dotfiles
is not portable: not even
across my Linux workstation to the VPS.
LinuxJournal has a great tutorial about vcsh
for the rescue. After
poking around and some error and trial, it is now dead simple to duplicate the
working environment:
brew install vcsh mr
vcsh clone git@github.com/kunxi/mrrc.git mr
mr update
mr
will pull oh-my-zsh,
neobundle.vim and my configurations
for zsh, git and vim.
The next step is to chsh -s /bin/zsh
; then launch vim. NeoBundle will prompt
to download and install the vim plugins, voilà.
Behind the scenes
It is quite impressive how concise vcsh is, mere 462 loc in shell as version
1.20130829 is. It leverages the awesome git to do all the heavy-lifting. When
you clone a remote repository foo
, vcsh does the following behind the scene:
- create a folder in
.config/vcsh/repo.d/foo.git
, and export it asGIT_DIR
. - create
$VCSH_BASE
directory, i.e your home directory by default; and export it asGIT_WORK_TREE
- Thus the work tree and git meta data, aka .git folder, are separated. We
can use
git fetch
to pull the remote repository into theGIT_DIR
, and merge the changes back to theGIT_WORK_TREE
.
This approach allows us to share the $HOME
across multiple git repositories, a
perfect solution to address the dotfiles problem!
Use cases
With the mechanism in the mind, we can explore other use cases to streamline the dotfiles.
Mount the submodule
If your dotfile depends on an external project, like NeoBundle.vim to .vimrc, you can use mr to mount the external project to the specified destination:
[$HOME/.config/vcsh/repo.d/neobundle.git]
checkout = mkdir -p ~/.vim/bundle; VCSH_BASE=~/.vim/bundle/neobundle.vim vcsh clone https://github.com/Shougo/neobundle.vim neobundle
The trick here is to override the VCSH_BASE
environment variable, so the git
meta data is cloned in $HOME/.config/vcsh/repo.d/neobundle.git
, but the
working copy is merged in the specified bundle directory.
Divide and Merge
As the above examples shows, each git repository is an atomic configuration for a specific application. We can checkin the screenrc and tmuxrc, and pick whatever available in the target environment.
Some application supports configuration inclusion, then we can leave the
personal credentials to a private git repository and pick them with
vcsh clone
.
Conclusion
The separation of the git meta data and working copy solves the dotfiles issues elegantly, just as the FTSE claims:
We can solve any problem by introducing an extra level of indirection.