Every new machine means hours of setup. Installing tools, configuring your shell, recreating aliases, finding your old vim config. Dotfiles management solves this - version control your configuration and set up any machine in minutes with your personalized environment.
Your Environment, Everywhere
Clone your dotfiles repo, run one script, and your new machine feels like home. Shell config, git aliases, editor settings - all synced.
Core Concept
Dotfiles are configuration files that start with a dot (hidden on Unix). A dotfiles repo stores them centrally and symlinks them to your home directory:
Key Techniques
Repo Structure
Organize configs by tool or category
Symlink Strategy
ln -s or GNU Stow for linking
Install Scripts
Automate setup for new machines
Machine-Specific
Conditional configs per OS/host
Practical Examples
Basic Install Script:
#!/bin/bash
set -euo pipefail
DOTFILES_DIR="$HOME/dotfiles"
# Files to symlink
files=".bashrc .zshrc .gitconfig .vimrc .tmux.conf"
echo "Creating symlinks..."
for file in $files; do
src="$DOTFILES_DIR/$file"
dest="$HOME/$file"
# Backup existing file
if [[ -f "$dest" && ! -L "$dest" ]]; then
echo "Backing up $dest to $dest.backup"
mv "$dest" "$dest.backup"
fi
# Create symlink
ln -sf "$src" "$dest"
echo "Linked $file"
done
echo "Done! Dotfiles installed."
Using GNU Stow (cleaner approach):
# Directory structure for stow:
# ~/dotfiles/
# bash/
# .bashrc
# git/
# .gitconfig
# vim/
# .vimrc
# .vim/
# plugins/
# tmux/
# .tmux.conf
# Install all packages
cd ~/dotfiles
stow bash git vim tmux
# Or install specific packages
stow vim
# Uninstall
stow -D vim
# Stow automatically creates symlinks in parent directory ($HOME)
Machine-Specific Configuration:
# In .zshrc - load machine-specific config
if [[ -f "$HOME/.zshrc.local" ]]; then
source "$HOME/.zshrc.local"
fi
# In .gitconfig - conditional includes
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personal
# In .bashrc - OS-specific settings
case "$(uname -s)" in
Darwin)
# macOS specific
alias ls='ls -G'
export PATH="/opt/homebrew/bin:$PATH"
;;
Linux)
# Linux specific
alias ls='ls --color=auto'
;;
esac
Secrets Handling (NEVER commit secrets):
# .gitignore - exclude sensitive files
*.local
.env
*-secrets
credentials.*
# In .bashrc - load secrets from non-tracked file
if [[ -f "$HOME/.secrets" ]]; then
source "$HOME/.secrets"
fi
# Alternative: use a password manager or 1Password CLI
eval $(op signin)
export API_KEY=$(op read "op://Vault/API Key/credential")
Why This Matters
- ✓ Instant Machine Setup - New laptop to productive in minutes, not hours
- ✓ Consistent Environment - Same aliases, keybindings, and tools everywhere
- ✓ Version Controlled - Track changes, rollback mistakes, see history
- ✓ Shareable - Learn from others' configs, share your improvements
- ✓ Disaster Recovery - Rebuild your environment after any failure
Cheatsheet
Essential Files to Track:
| File | Purpose | Priority |
|---|---|---|
.zshrc / .bashrc |
Shell config, aliases, prompt, PATH | High |
.gitconfig |
Git aliases, user info, settings | High |
.vimrc / init.lua |
Vim/Neovim configuration | High |
.tmux.conf |
tmux keybindings, appearance | Medium |
.ssh/config |
SSH host aliases (not keys!) | Medium |
.config/ |
App configs (starship, alacritty, etc.) | Medium |
Brewfile |
macOS package list for Homebrew | Optional |
Starter Repo Structure:
dotfiles/
├── .bashrc
├── .zshrc
├── .gitconfig
├── .vimrc
├── .tmux.conf
├── .config/
│ ├── starship.toml
│ └── alacritty/
│ └── alacritty.yml
├── scripts/
│ └── install-packages.sh
├── Brewfile # macOS packages
├── install.sh # Main setup script
├── .gitignore # Exclude .local, secrets
└── README.md
Pro Tips
Never Commit Secrets
Use .local suffix for machine-specific files containing secrets. Add *.local to .gitignore. Source these files in your main configs.
Use GNU Stow
Install with brew install stow or apt install stow. It handles symlinks automatically with proper directory structure - no custom scripts needed.
Track Homebrew Packages
Run brew bundle dump to generate a Brewfile. On a new Mac, brew bundle installs everything. Commit Brewfile to your dotfiles.
Use a Private Repo
Even without secrets, your configs can reveal info you don't want public. Use a private GitHub repo. You can still share specific files publicly.
Learn from Others
Search "dotfiles" on GitHub. Developers like mathiasbynens, jessfraz, and holman have well-documented repos. Steal ideas, but understand what each config does.
Getting Started
-
1
Create the Repo
Run
mkdir ~/dotfiles && cd ~/dotfiles && git init -
2
Copy Your Configs
Move your existing dotfiles:
cp ~/.zshrc ~/dotfiles/ -
3
Create Symlinks
Link back:
ln -sf ~/dotfiles/.zshrc ~/.zshrc(or use stow) -
4
Write Install Script
Create install.sh that automates steps 2-3 for new machines
-
5
Push to GitHub
Create a private repo and push:
git remote add origin ... && git push -u origin main
Never Start From Scratch Again
Your dotfiles repo is the best time investment you'll make. Set up any machine in minutes, not hours.
Explore Dotfiles Resources