Back to Resources Resource

Dotfiles Management - Reproducible Dev Environments

Version control your shell config, vim settings, git aliases, and more. Set up any new machine in minutes with your personalized environment.

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:

~/dotfiles (git repo) .bashrc .zshrc .gitconfig .vimrc .tmux.conf install.sh symlinks ~/ (home directory) .bashrc -> dotfiles/.bashrc .zshrc -> dotfiles/.zshrc .gitconfig -> ... .vimrc -> ... .tmux.conf -> ... Workflow 1. Clone repo 2. Run install.sh 3. Done! Edit dotfiles/ git commit git push Synced everywhere!

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. 1

    Create the Repo

    Run mkdir ~/dotfiles && cd ~/dotfiles && git init

  2. 2

    Copy Your Configs

    Move your existing dotfiles: cp ~/.zshrc ~/dotfiles/

  3. 3

    Create Symlinks

    Link back: ln -sf ~/dotfiles/.zshrc ~/.zshrc (or use stow)

  4. 4

    Write Install Script

    Create install.sh that automates steps 2-3 for new machines

  5. 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

Explore More Resources