Skip to content
Home
Dotfiles: Managing Developer Configurations

Dotfiles: Managing Developer Configurations

Developer Tools Developer Tools 8 min read 1508 words Beginner ExcellentWiki Editorial Team

Dotfiles are configuration files that start with a dot (.bashrc, .vimrc, .gitconfig, .tmux.conf). Managing them well means you can set up a new machine in minutes and keep configurations synchronized across all your environments.

Why Manage Dotfiles

Without dotfile management, every new machine requires:

  • Recreating aliases, environment variables, and shell prompts
  • Remembering which tools you use and how they are configured
  • Manually copying files, inevitably missing some

A dotfiles repository solves this by putting all configuration in version control with a single bootstrap command.

Git-Based Dotfiles

The most common approach: a Git repository in your home directory.

Bare Repository Method

# Create a bare repository in a hidden directory
git init --bare $HOME/.dotfiles

# Create an alias to manage it
alias dotfiles='git --git-dir=$HOME/.dotfiles --work-tree=$HOME'

# Add files
dotfiles add .bashrc .vimrc .tmux.conf .config/nvim/init.lua
dotfiles commit -m "Initial dotfiles"
dotfiles remote add origin git@github.com:username/dotfiles.git
dotfiles push -u origin main

On a new machine:

# Clone into a bare repo
git clone --bare git@github.com:username/dotfiles.git $HOME/.dotfiles

# Checkout without overwriting existing files
git --git-dir=$HOME/.dotfiles --work-tree=$HOME checkout

# If there are conflicts, back up and retry
mkdir -p .config-backup
git --git-dir=$HOME/.dotfiles --work-tree=$HOME checkout 2>&1 | \
  grep -E "^\s+" | awk "{print $1}" | xargs -I{} sh -c 'mkdir -p .config-backup/$(dirname {}) && mv {} .config-backup/{}'
git --git-dir=$HOME/.dotfiles --work-tree=$HOME checkout

The bare repository method is clean. It keeps files in their natural locations and does not require symlinks or wrapper scripts.

Symlink Method

An alternative is storing dotfiles in a dedicated directory and symlinking them:

mkdir ~/dotfiles
mv ~/.bashrc ~/dotfiles/bashrc
ln -s ~/dotfiles/bashrc ~/.bashrc

Tools like GNU Stow automate this:

# ~/dotfiles/bash/.bashrc
# ~/dotfiles/git/.gitconfig
# ~/dotfiles/tmux/.tmux.conf

# Create all symlinks at once
cd ~/dotfiles
stow bash git tmux

Stow treats each subdirectory as a package and creates symlinks while respecting the directory structure. Running stow bash creates ~/.bashrc~/dotfiles/bash/.bashrc.

Comparison: Bare Repo vs Symlinks

MethodProsCons
Bare repoFiles stay in natural locations, no symlink maintenanceRequires alias setup, accidental git add risk
Symlinks with StowClean separation, easy to understandSymlinks can break, must remember to restow

Essential Dotfiles to Manage

Shell Configuration

# ~/.bashrc — common aliases and functions
alias ll='ls -la'
alias g='git'
alias gst='git status'
alias gc='git commit'
alias gp='git push'
alias ..='cd ..'
alias ...='cd ../..'

# Export common environment variables
export EDITOR=vim
export VISUAL=vim
export HISTSIZE=50000
export HISTFILESIZE=50000

# Colorize grep output
alias grep='grep --color=auto'
# ~/.zshrc — common for zsh users
# If using Oh My Zsh
ZSH_THEME="agnoster"
plugins=(git docker kubectl autojump)
source $ZSH/oh-my-zsh.sh

# Or with starship prompt
eval "$(starship init zsh)"

Git Configuration

; ~/.gitconfig
[user]
    name = Your Name
    email = you@example.com
[core]
    editor = vim
    autocrlf = input
[alias]
    st = status
    ci = commit
    co = checkout
    br = branch
    lg = log --oneline --graph --decorate --all
    amend = commit --amend --no-edit
    undo = reset --soft HEAD~1
[init]
    defaultBranch = main
[color]
    ui = auto

Editor Configuration

-- ~/.config/nvim/init.lua — minimal Neovim config
local opt = vim.opt

opt.number = true
opt.relativenumber = true
opt.tabstop = 2
opt.shiftwidth = 2
opt.expandtab = true
opt.mouse = "a"
opt.clipboard = "unnamedplus"
opt.termguicolors = true

-- Key mappings
vim.g.mapleader = " "
vim.keymap.set("n", "<leader>w", ":w<CR>")
vim.keymap.set("n", "<leader>q", ":q<CR>")

SSH Configuration

# ~/.ssh/config
Host *
    ServerAliveInterval 60
    AddKeysToAgent yes
    UseKeychain yes

Host myserver
    HostName 192.168.1.100
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_work

Bootstrap Script

A bootstrap script automates setup on a new machine:

#!/bin/bash
# bootstrap.sh — run on a fresh machine

set -e

DOTFILES_REPO="git@github.com:username/dotfiles.git"

echo "Cloning dotfiles..."
git clone --bare $DOTFILES_REPO $HOME/.dotfiles
alias dotfiles='git --git-dir=$HOME/.dotfiles --work-tree=$HOME'
dotfiles checkout

echo "Installing packages..."
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
  sudo apt update
  sudo apt install -y vim tmux git curl build-essential
elif [[ "$OSTYPE" == "darwin"* ]]; then
  /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  brew install vim tmux git
fi

echo "Installing Oh My Zsh..."
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

echo "Done! Restart your shell."

Secret Management

Never commit secrets (API keys, passwords, tokens) to a public dotfiles repository.

ApproachHow it works
.local filesSource a separate .bashrc.local file that is .gitignored
Environment filesUse .env files loaded at shell startup
Password managersUse op run (1Password CLI) or pass to inject secrets
Git-cryptEncrypt specific files in the repository
SOPSMozilla’s tool for encrypted config files
# ~/.bashrc — source a private local file
if [ -f ~/.bashrc.local ]; then
    source ~/.bashrc.local
fi

The .gitignore ensures .bashrc.local is never committed. Secrets stay local, and the main config references them conditionally.

Organization Strategies

StrategyProsCons
Single monolithic repoSimple, one command to cloneLarge, hard to navigate
Per-tool reposModular, share selectivelyMany repos to manage
Modular monorepoOne repo, separate directories, stow/install per toolRequires symlink tool
Framework (chezmoi)Built-in templating, encryption, diffLearning curve

chezmoi is the most popular dotfile manager. It allows per-machine templates, encrypted secrets, and a dry-run preview of changes. It applies configurations rather than symlinking, making it safe to adopt on existing systems without conflicts.

# chezmoi workflow
chezmoi init                # Initialize
chezmoi add ~/.bashrc      # Track a file
chezmoi edit ~/.bashrc     # Edit the managed version
chezmoi diff               # Preview changes
chezmoi apply              # Apply to home directory
chezmoi update             # Pull and apply latest

Per-Machine Configuration with Templates

chezmoi supports Go templates in managed files, allowing you to maintain a single dotfile repo across different operating systems and environments:

# ~/.local/share/chezmoi/.bashrc.tmpl
export EDITOR=vim
{{- if eq .chezmoi.os "darwin" }}
export PATH="/opt/homebrew/bin:$PATH"
{{- else if eq .chezmoi.os "linux" }}
export PATH="/usr/local/bin:$PATH"
{{- end }}

This pattern is invaluable when you maintain configurations across macOS, Linux, and WSL environments. Template conditions can check the OS, architecture, hostname, or any custom variable you define.

Maintenance and Evolution

Dotfiles are living documents. As you adopt new tools and workflows, your configurations should evolve. Schedule a quarterly review of your dotfiles to remove unused aliases, update tool versions, and consolidate configuration files. A clean dotfiles repository makes onboarding to new machines faster and reduces the cognitive overhead of maintaining muscle memory for commands you no longer use.

The key to dotfile management is simplicity. Start by tracking your most important configs (shell, git, editor), commit early, and add more as you identify files you configure on every machine.

FAQ

Should I commit my entire .ssh directory?

No. Never commit private keys. Only commit ~/.ssh/config and ~/.ssh/known_hosts (if needed). Always add id_rsa, id_ed25519, and *.key patterns to your .gitignore.

How do I handle different configurations for work and personal machines?

Use conditional logic in your shell config (if hostname matches work-*) or use chezmoi templates. Alternatively, create separate branches for work and personal configs.

What is the best dotfile management tool?

chezmoi is the most popular and feature-rich option. For a simpler approach, the bare Git repo method works well. YADM (Yet Another Dotfiles Manager) is a good middle ground with Git-like commands and built-in encryption support.

How do I keep my dotfiles in sync across machines?

Push to your remote repository after changes and pull on each machine. With chezmoi, run chezmoi update to pull and apply the latest changes. Set up a cron job or git hook to auto-sync if you find yourself forgetting.

Can I use dotfiles with Windows?

Yes. Windows Terminal, PowerShell profiles, and WSL configurations can all be managed as dotfiles. WSL configuration lives in ~/.wslconfig and Windows Terminal settings are typically stored in %APPDATA%\Microsoft\Windows Terminal\settings.json.

Dotfiles Strategy at Scale

Managing dotfiles across multiple machines requires a strategy that balances personalization with consistency. A bare Git repository (the --bare flag approach) tracks files without moving them into a separate directory, letting you version-control files in-place. Symlink-based tools like GNU Stow or yadm provide higher-level interfaces for organizing configs by program. For secrets management, store API keys and tokens in a separate encrypted file sourced by your shell config but excluded from version control with .gitignore. Environment-specific overrides let your shell detect whether it is on a work laptop, personal desktop, or SSH’d into a server and adjust configurations accordingly. The XDG Base Directory Specification (~/.config, ~/.local/share, ~/.cache) reduces home-directory clutter. Most modern tools (Git, VS Code, Neovim, i3, sway) already support XDG paths. Shell-agnostic configs work best: write common aliases and exports in a separate file that both .bashrc and .zshrc can source. Consider using chezmoi for dotfiles that need per-machine template expansion, such as different Git user.email values for work versus personal repos.

Bootstrapping and CI

A bootstrap script turns a new machine into a productive environment in minutes. It should install package managers (Homebrew, apt, winget), core packages (Git, curl, build tools), and programming language runtimes (via asdf, mise, or nvm). The script should be idempotent — running it multiple times produces the same result. Test dotfiles with GitHub Actions by spinning up a fresh VM, running the bootstrap script, and verifying that all tools initialize without errors. Document the bootstrap process in a README or BOOTSTRAP file inside the dotfiles repo.

For a comprehensive overview, read our article on Advanced Git Commands.

For a comprehensive overview, read our article on Chrome Devtools Guide.

Section: Developer Tools 1508 words 8 min read Beginner 756 articles in section Report inaccuracy Back to top