If you use more than one computer, you’ve probably dealt with setting up your shell, editor, and tools from scratch each time. I frequently found myself moving from a laptop to a desktop and updating something in a config file that I then had to rsync over after realizing it wasn’t there. A dotfiles repository solves this. Track your configuration files in Git, push them to a remote, and clone them wherever you need them.

Why Git?

You could sync your dotfiles with rsync or even a USB drive, but Git gives you version history on top of synchronization. If an update to your .bashrc breaks something, you can git diff against the last working version. And since the repository lives on a remote like GitHub, it doubles as a backup.

Setting Up the Repository

  1. Initialize a bare repository:

     $ cd "${HOME}"
     $ git init --bare --initial-branch=main "${HOME}/git/dotfiles"
    

    A bare repo has no working directory of its own; your home directory will be the working directory.

  2. I made an alias so I didn’t have to type the full git --git-dir=... --work-tree=... every time:

     $ alias dotfiles='git --git-dir="${HOME}/git/dotfiles" --work-tree="${HOME}"'
    

    Now you can run dotfiles status, dotfiles add .bashrc, dotfiles commit, and so on.

  3. Hide untracked files:

     $ dotfiles config --local status.showUntrackedFiles false
    

    Without this, dotfiles status will list everything in your home directory.

  4. Add a remote and push:

     $ dotfiles remote add origin git@example.com:user/dotfiles.git
     $ dotfiles push --set-upstream origin main
    

    Replace the URL with your own.

Tracking Files

Repo is up and configured, now what? Let’s add some initial items.

Start by adding your .bashrc.

$ dotfiles add .bashrc
$ dotfiles commit --message "Initial commit of .bashrc"
$ dotfiles push

Other common files worth tracking:

  • .vimrc
  • dirs under .config/

Cloning to a New System

The magic moment has arrived. Let’s put the repo on another machine.

  1. On your other machine, clone the repository with --separate-git-dir so the Git directory ends up in the right place:

     $ git clone --separate-git-dir="${HOME}/git/dotfiles" git@example.com:user/dotfiles.git dotfiles-tmp
    
  2. Then copy the files into your home directory and clean up:

     $ rsync --recursive --verbose --exclude '.git' dotfiles-tmp/ "${HOME}/"
     $ rm --recursive dotfiles-tmp
    
  3. I added the alias to my .bashrc so my other machine already has it, but I didn’t track the showUntrackedFiles config. Let’s add it.

     $ dotfiles config --local status.showUntrackedFiles false
    

And now both my laptop and desktop are in perfect sync.

Things to Watch Out For

  • Don’t commit secrets!
    • API keys, passwords, SSH private keys, none of these belong in a dotfiles repo. Add them to a .gitignore so they can’t slip in by accident. If you need to manage secrets across machines, use a dedicated tool like pass.
  • Expect merge conflicts.
    • If you change the same file on two machines without pulling first, you’ll need to resolve conflicts. This is just normal Git workflow, but worth keeping in mind.

Resources