As vim, tmux, zsh and git user you have some preferences for the tools you are using. But if you have a set of environment you are working, e.g. a server running Linux, a MacBook at home running with OSX and a Windows machine at work with cygwin you have a slightly different set of configs. But the greatest part is common. So there are many solutions for dotfiles setup and I wanted to share my favourite, too.

Repository

Of course I have all my files in a git repository, not only for versioning but also for synchronize the environments.

Directory Setup

I have cloned the .dotfiles directory into the folder ~/.dotfiles. But w/o checking the contained files out. You can do this by

git clone <source-url> --no-checkout .dotfiles

Then open the config file of the git repository. It is located at ~/.dotfiles/.git/config.

Within the section [core] append the following line:

worktree = ../../

This will define your home directory as checkout folder. Now you can checkout the dotfiles using

git --git-dir=~/.dotfiles/.git checkout

Config File Setup (in the repository)

I have a directory called .configs containing all the machine specific config files, and a set of zsh scripts. The main config files are in the root folder

The Tricky Part

I use symlinks in the home directory called <configfile>.local that link to the machine specific file/folder in the .configs directory. This way I can always edit the .local file without thinking about the hostname of the current machine. To create the symlinks an the files if neccessary I have created a script. It works for me:

#!/bin/bash

homedir=~
eval homedir=$homedir
echo "Configs placed in your homedirectory: ${homedir}"

if [[ "$OSTYPE" == "win32" ]]
then
   hostname=`hostname | tr -d '\040\011\012\015'`
else
   if [[ "$OSTYPE" == "darwin"* ]]
   then
      hostname=`hostname -s | tr -d '\040\011\012\015'`
   else
      hostname=`hostname | tr -d '\040\011\012\015'`
   fi
fi

gitdir=`git --git-dir=${homedir}/.dotfiles/.git rev-parse --git-dir`
hasgit=$?
configsbasepath=${homedir}/.configs

create_dir_if_needed(){
      if [[ ! -d "${1}" ]]; then
         mkdir -p "${1}";
      fi
}
create_file_dir_if_needed(){
      filedir=`dirname ${1}`
      echo ${filedir}
      create_dir_if_needed ${filedir}
}
add_to_git(){
   if [ ${hasgit} ]; then
      git --git-dir=${gitdir} add ${1}
   fi
}
create_local_link_if_not_exists(){
   link=${homedir}/.${1}.local
   if [ ! -f ${link} ];then
      ln -s ${2} ${link}
   fi
}
create_for_host_if_not_exists(){
   file=${configsbasepath}/${1}.${hostname}
   if [ ! -f ${file} ];then
      create_file_dir_if_needed ${file}
      touch ${file};
      add_to_git ${file}
   fi
   create_local_link_if_not_exists ${1} ${file}
}
create_dir_for_host_if_not_exists(){
   file=${configsbasepath}/${1}-${hostname}
   create_dir_if_needed ${file}
   touch ${file}/.gitkeep
   add_to_git ${file}/.gitkeep
}

create_dir_and_link(){
   create_dir_for_host_if_not_exists ${1}
   if [ ! -f ${1} ]; then
      ln -s ${configsbasepath}/${1}-${hostname} .${1}
   fi
}
create_and_link(){
   create_for_host_if_not_exists ${1}
   if [ ! -f ${1} ]; then
      create_file_dir_if_needed .${1}
      ln -s ${configsbasepath}/${1}.${hostname} .${1}
   fi
}
pushd ${homedir} > /dev/null
create_for_host_if_not_exists "zshrc.theme"
create_for_host_if_not_exists "vimrc"
create_for_host_if_not_exists "zshrc"
create_for_host_if_not_exists "tmux"
create_for_host_if_not_exists "muttrc"
create_for_host_if_not_exists "gitconfig"
create_and_link "ssh/config"
create_dir_and_link "tmuxinator"
popd > /dev/null

At the very bottom you can see for which config files a .local symlink and file will be created. There are a few utility functions that perform the action and do some checks. And a way to determine a hostname on all systems I use.

Hints

Feel free to send me hints on how to improve the setup, or share your setup with me.

dotfiles git shell vim zsh

This is my new blog. It may contain interesting thins, or not. The articles may cover some of the following topics: parenting, coding, vim, infrastructure, public transport troubles, gadgets, recipes, ...

Who I am

I am a software developer, housband and father who likes to learn new stuff. I like food, cooking, gadgets. I love my daughter and my wife. I live and work in Munich. And I really love that city.

Links

https://github.com/m42e

Social Networks

Well a few weeks ago I decided to quit nearly all the social networks. They produce a lot of white-bread information I do not take care of. But somehow you read your "streams" multiple times a day so you don't miss the one of a thousand news you are interested in. That's the reason I quit.

Contact me

matthias-blog@bilger.info