skip to content
Back

How I Set Up My Dotfiles for Sharing Across Multiple Machines

/ 3 min read

Updated:

My files live in two places:

  • Some in ~/.config directories (like nvim, alacritty)
  • Others directly in my home folder (like .gitconfig, .zshrc)

But I want to track all of them in git so I can have version control over them (and easily share them across multiple machines).

So I need to store them in a single place, but they have to be in separate directories as well.

There is actually a pretty simple way to do this.

A symlink.

  1. Store everything in a single git repository.
  2. Symlink each file or directory to where the apps expect them.

I will walk you through the initial setup and then how to add more configurations:

Setting Up the Repository

  1. I create the basic structure:
Terminal window
mkdir -p ~/dotfiles/home ~/dotfiles/config
cd ~/dotfiles
git init
  1. I add a simple README and gitignore:
Terminal window
echo "# My Dotfiles" > README.md
git add README.md
git commit -m "Initial commit"
# I ignore common junk files
cat > .gitignore << EOF
*.log
*.swp
*~
.DS_Store
.netrwhist
node_modules/
__pycache__/
*.pyc
EOF
git add .gitignore
git commit -m "Add gitignore file"

Adding My Existing Configs

For Git:

Terminal window
# Copy my current Git config
cp ~/.gitconfig ~/dotfiles/home/
# I might edit it to remove sensitive info
nano ~/dotfiles/home/.gitconfig
git add ~/dotfiles/home/.gitconfig
git commit -m "Add Git configuration"

For Neovim:

Terminal window
mkdir -p ~/dotfiles/config/nvim
cp -r ~/.config/nvim/* ~/dotfiles/config/nvim/
# I remove plugin folders and other large files
rm -rf ~/dotfiles/config/nvim/plugged
rm -rf ~/dotfiles/config/nvim/.git
git add ~/dotfiles/config/nvim
git commit -m "Add Neovim configuration"

My Installation Script

I create a script that sets up symlinks for me:

cat > ~/dotfiles/install.sh << 'EOF'
#!/bin/bash
# Set variables
DOTFILES_DIR="$HOME/dotfiles"
HOME_DIR="$HOME"
CONFIG_DIR="$HOME/.config"
DOTFILES_HOME_DIR="$DOTFILES_DIR/home"
DOTFILES_CONFIG_DIR="$DOTFILES_DIR/config"
# Create backup directory
BACKUP_DIR="$HOME/.dotfiles_backup/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
echo "Created backup directory at $BACKUP_DIR"
# Function to backup and create symlinks
link_file() {
local src="$1"
local dest="$2"
# Back up existing files
if [ -e "$dest" ] && [ ! -L "$dest" ]; then
echo "Backing up $dest to $BACKUP_DIR/"
mv "$dest" "$BACKUP_DIR/"
elif [ -L "$dest" ]; then
echo "Removing existing symlink $dest"
rm "$dest"
fi
# Create symlink
echo "Creating symlink $dest -> $src"
ln -sf "$src" "$dest"
}
# Link home directory dotfiles
echo "Linking home directory dotfiles..."
for file in "$DOTFILES_HOME_DIR"/.*; do
[ -f "$file" ] || continue
filename=$(basename "$file")
link_file "$file" "$HOME_DIR/$filename"
done
# Link .config directory files
echo "Linking .config directory files..."
mkdir -p "$CONFIG_DIR"
for dir in "$DOTFILES_CONFIG_DIR"/*; do
[ -d "$dir" ] || continue
dirname=$(basename "$dir")
link_file "$dir" "$CONFIG_DIR/$dirname"
done
echo "Dotfiles installation complete!"
EOF
chmod +x ~/dotfiles/install.sh
git add ~/dotfiles/install.sh
git commit -m "Add installation script"

Handling My Private Info

I should handle sensitive data like my email carefully:

  1. In my dotfiles version of .gitconfig, I add:
Terminal window
[include]
path = ~/.gitconfig.local
  1. I keep personal info separate:
Terminal window
# This file stays local, not in git
cat > ~/.gitconfig.local << EOF
[user]
name = My Name
email = my.email@example.com
EOF

To be honest, I completely forgot about my email in the .gitconfig file, so it’s still being tracked. But my email is leaked elsewhere anyhow :D

Using My Setup

When I make changes:

  1. I edit files in my ~/dotfiles repository
  2. Changes appear in both places because of the symlinks
  3. I commit the changes:
Terminal window
cd ~/dotfiles
git add .
git commit -m "Update configs"
git push

When I get a new machine:

  1. I clone my repository:
Terminal window
git clone https://github.com/myusername/dotfiles.git ~/dotfiles
  1. I run my script:
Terminal window
cd ~/dotfiles
./install.sh

That’s it! My entire environment follows me wherever I go.