Post

Dotfiles Setup

Dotfiles setup cheatsheet

Dotfiles Setup

Overview

video grab from Youtube

Setup

1. Create the bare repository (it lives hidden in your home)

1
2
cd ~                                   # make sure you're in $HOME
git init --bare .dotfiles

2. Create a shell alias

you can use a normal-looking config command instead of typing the long –git-dir and –work-tree every time.

For zsh (~/.zshrc):

1
2
echo 'alias dotfiles="/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME"' >> ~/.zshrc
source ~/.zshrc

3. Tell Git to hide untracked files by default

(This is very important — otherwise config status will show hundreds/thousands of untracked files every time.)

1
dotfiles config --local status.showUntrackedFiles no

4. Create a .gitignore right away - Optional

1
2
mkdir -p ~/.config/dotfiles
nvim ~/.config/dotfiles/ignore

ignore content

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Home clutter
Downloads/
Desktop/
Documents/
Music/
Pictures/
Videos/

# Cache / state
.cache/
.local/share/
.local/state/

# SSH private material (never commit)
.ssh/id_*
.ssh/known_hosts

# GPG
.gnupg/

# Language tooling
.npm/
.cargo/
.rustup/
.go/
.gradle/
.maven/

# Neovim junk
.config/nvim/.luarc.json
.config/nvim/.cache/

# OS / editor
.DS_Store
Thumbs.db

5. Tell the bare repo to use this ignore file

1
dotfiles config core.excludesFile ~/.config/dotfiles/ignore

6. Create setup.sh

1
nvim ~/.config/dotfiles/setup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env bash
set -e

DOTFILES_DIR="$HOME/.dotfiles"
CONFIG_DIR="$HOME/.config"

echo "[*] Setting up dotfiles environment..."

# --- Git alias -------------------------------------------------
if ! grep -q "alias dotfiles=" "$HOME/.zshrc" 2>/dev/null; then
  echo "alias dotfiles='/usr/bin/git --git-dir=$DOTFILES_DIR --work-tree=$HOME'" >> "$HOME/.zshrc"
fi

if ! grep -q "alias dotfiles=" "$HOME/.bashrc" 2>/dev/null; then
  echo "alias dotfiles='/usr/bin/git --git-dir=$DOTFILES_DIR --work-tree=$HOME'" >> "$HOME/.bashrc"
fi

# --- Git config ------------------------------------------------
/usr/bin/git --git-dir="$DOTFILES_DIR" --work-tree="$HOME" \
  config --local status.showUntrackedFiles no

/usr/bin/git --git-dir="$DOTFILES_DIR" --work-tree="$HOME" \
  config core.excludesFile "$CONFIG_DIR/dotfiles/ignore"

# --- Ensure directories ---------------------------------------
mkdir -p \
  "$CONFIG_DIR/zsh" \
  "$CONFIG_DIR/bash" \
  "$CONFIG_DIR/fish" \
  "$CONFIG_DIR/nvim" \
  "$CONFIG_DIR/wezterm" \
  "$CONFIG_DIR/tmux" \
  "$CONFIG_DIR/dotfiles"

echo "[+] Dotfiles setup complete"
1
chmod +x ~/.config/dotfiles/setup.sh

7. Add dotfiles to Git

1
2
3
4
5
6
7
8
9
10
dotfiles add .zshrc
dotfiles add .bashrc
dotfiles add .config/dotfiles
dotfiles add .config/zsh
dotfiles add .config/bash
dotfiles add .config/fish
dotfiles add .config/nvim
dotfiles add .config/wezterm
dotfiles add .config/tmux
dotfiles add .config/starship

Check:

1
dotfiles status

Then commit:

1
dotfiles commit -m "Initial dotfiles"

8. Push to GitHub

1
2
dotfiles remote add origin git@github.com:YOURUSERNAME/.dotfiles.git
dotfiles push -u origin main

Restoring Dotfiles on new system

Create restore.sh

1
nvim ~/.config/dotfiles/restore.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env bash
set -e

REPO_URL="git@github.com:USERNAME/.dotfiles.git"
DOTFILES_DIR="$HOME/.dotfiles"
CONFIG_DIR="$HOME/.config"
BACKUP_DIR="$HOME/.dotfiles-backup-$(date +%Y%m%d-%H%M%S)"

echo "[*] Restoring dotfiles..."

# --- Clone bare repo if missing -------------------------------
if [ ! -d "$DOTFILES_DIR" ]; then
  echo "[*] Cloning bare dotfiles repo..."
  git clone --bare "$REPO_URL" "$DOTFILES_DIR"
else
  echo "[*] Dotfiles repo already exists"
fi

# --- Temporary alias ------------------------------------------
alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'

# --- Git config ------------------------------------------------
dotfiles config --local status.showUntrackedFiles no
dotfiles config core.excludesFile "$CONFIG_DIR/dotfiles/ignore"

# --- Attempt checkout -----------------------------------------
echo "[*] Checking out dotfiles..."

if ! dotfiles checkout; then
  echo "[!] Conflicts detected — backing up existing files to:"
  echo "    $BACKUP_DIR"
  mkdir -p "$BACKUP_DIR"

  dotfiles checkout 2>&1 | grep -E "^\s+" | awk '{print $1}' | while read -r file; do
    mkdir -p "$BACKUP_DIR/$(dirname "$file")"
    mv "$HOME/$file" "$BACKUP_DIR/$file"
  done

  echo "[*] Retrying checkout..."
  dotfiles checkout
fi

# --- Pull latest changes --------------------------------------
dotfiles pull

# --- Ensure setup is applied ----------------------------------
if [ -x "$CONFIG_DIR/dotfiles/setup.sh" ]; then
  echo "[*] Running setup.sh..."
  bash "$CONFIG_DIR/dotfiles/setup.sh"
fi

echo "[+] Dotfiles restored successfully"

⚠️ IMPORTANT
Replace this line with your real repo:

1
REPO_URL="git@github.com:USERNAME/.dotfiles.git"
1
2
3
4
chmod +x ~/.config/dotfiles/restore.sh
dotfiles add ~/.config/dotfiles/restore.sh
dotfiles commit -m "Add restore.sh for safe dotfiles recovery"
dotfiles push

restore on a brand-new machine

Install Git:

1
2
sudo pacman -S git   # Arch
sudo apt install git # Debian/Kali/Ubuntu

Run restore:

1
bash ~/.config/dotfiles/restore.sh

Cheatsheet

📍 Repo facts

  • Git dir: ~/.dotfiles
  • Work tree: $HOME
  • Manager alias: dotfiles

    🔧 One-time setup (on first machine)

1
2
3
4
git init --bare ~/.dotfiles
alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles --work-tree=$HOME'
dotfiles config --local status.showUntrackedFiles no
dotfiles config core.excludesFile ~/.config/dotfiles/ignore

➕ Track files / configs

1
2
3
4
5
6
7
8
9
10
11
dotfiles add .zshrc
dotfiles add .bashrc
dotfiles add .tmux.conf

dotfiles add .config/zsh
dotfiles add .config/fish
dotfiles add .config/nvim
dotfiles add .config/wezterm
dotfiles add .config/tmux
dotfiles add .config/starship.toml
dotfiles add .config/dotfiles

📋 Status & diff

1
2
3
dotfiles status
dotfiles diff
dotfiles diff --staged

💾 Commit & push

1
2
dotfiles commit -m "message"
dotfiles push

First push only:

1
2
3
dotfiles remote add origin git@github.com:USERNAME/dotfiles.git
dotfiles branch -M main
dotfiles push -u origin main

⬇️ Pull updates

1
dotfiles pull
1
bash ~/.config/dotfiles/restore.sh

Manual restore (if needed):

1
2
3
git clone --bare git@github.com:USERNAME/dotfiles.git ~/.dotfiles
alias dotfiles='/usr/bingit --git-dir=$HOME/.dotfiles --work-tree=$HOME'
dotfiles checkout

⚠️ Fix checkout conflicts

1
2
3
mv ~/.zshrc ~/.zshrc.bak
mv ~/.bashrc ~/.bashrc.bak
dotfiles checkout

Or fully automated (preferred):

1
bash ~/.config/dotfiles/restore.sh

🧹 Stop tracking a file (keep it locally)

1
2
dotfiles rm --cached ~/.config/nvim/init.lua
dotfiles commit -m "Stop tracking nvim init"

🗑️ Remove from repo + system

1
2
dotfiles rm ~/.tmux.conf
dotfiles commit -m "Remove tmux config"

🔍 Show tracked files

1
dotfiles ls-tree -r --name-only HEAD

🔄 Rename / move a config

1
2
dotfiles mv .config/nvim/init.vim .config/nvim/init.lua
dotfiles commit -m "Rename nvim init"

🧪 Test without touching files

1
dotfiles checkout --dry-run

🔧 Run setup again (safe)

1
bash ~/.config/dotfiles/setup.sh

🧾 Common paths (quick reference)

1
2
3
4
5
~/.config/nvim/init.lua
~/.config/wezterm/wezterm.lua
~/.config/tmux/tmux.conf
~/.config/fish/config.fish
~/.config/starship/starship.toml

🏆 Golden rules

  • ❌ Never run git directly → always use dotfiles

  • ❌ Never delete ~/.dotfiles

  • ✅ Track only what you explicitly add

  • ✅ Use restore.sh on new machines

  • ✅ Keep secrets out (or encrypt)

This post is licensed under CC BY 4.0 by the author.