A Dotfiles Repository: Keep Your Mac Config Files in Git and Sync Them Everywhere
Put your config files in one Git repository, then either symlink them into your home folder or check them out there directly. You get history, a backup, and a way to rebuild a Mac in minutes. Need to change just one file today? Our guide to how to edit config files and dotfiles quickly on Mac and iOS is the shorter read. This page is about keeping the whole set in sync.
Quick answer
There are three workable layouts, and the right one depends on how many files you manage:
- Plain repo plus symlinks: best for a handful of files. Simple, manual.
- GNU Stow: best for many files. One command links or unlinks a whole group.
- Bare repository: best if you dislike symlinks. Your home folder is the working tree.
Start with the smallest one that works. Switching later is cheap, because the files stay the same plain text.
What belongs in a dotfiles repository
GitHub's documentation defines dotfiles as files and folders on Unix-like systems starting with a period that control how applications and shells are configured, and says you can store and manage them in a repository. On a Mac that usually means:
- Shell setup:
.zshrc,.zprofile - Git setup:
.gitconfig, a global ignore file - Editor and tool settings:
.vimrc, files under.config - Your SSH config file, the host aliases only
Commit what you would be comfortable reading aloud. Never commit private keys, tokens, or shell history. If a config needs a secret, have the tracked file include an untracked local file and list that file in .gitignore. For anything sensitive that must be stored, see our notes on encrypting plain-text files on a Mac.
One more habit: read a script before you run it. GitHub's page warns that dotfiles can run arbitrary scripts, so review any install script before you use a dotfiles repository, including your own from two years ago.
Option 1: a plain repository plus symlinks
Create a folder, move a file in, and link it back:
mkdir ~/dotfiles && cd ~/dotfiles
git init
mv ~/.zshrc ~/dotfiles/zshrc
ln -s ~/dotfiles/zshrc ~/.zshrc
git add zshrc && git commit -m "Add zshrc"The shell still reads ~/.zshrc, which is now a link to the file in the repository. Repeat for each file, and collect the ln -s lines in a small install.sh so a new Mac needs one command.
The cost is upkeep. Every new file means another move, another link, another script line. One typo and a link points at nothing.
Option 2: GNU Stow
GNU Stow is a symlink farm manager. Each package lives in its own directory, and Stow links the contents into a target. By default the target is the parent of the stow directory, so with ~/dotfiles as the stow directory, the target is your home folder.
Lay out one folder per tool, mirroring where files should land:
~/dotfiles/
zsh/.zshrc
git/.gitconfig
vim/.vimrcPreview first, then apply:
cd ~/dotfiles
stow -n -v zsh git vim # simulate, change nothing
stow zsh git vimThe -n flag makes Stow change nothing, and with -v it shows what would happen. A few behaviors worth knowing, all from the manual:
- Stow checks for conflicts before it touches anything. If a real file already sits where a link should go, it stops without modifying the filesystem.
- It never deletes anything it does not own, so
stow -D vimremoves the links but leaves the package in your repository. stow -R zshrestows a package, which prunes links that are now obsolete.--dotfilesturns adot-prefix into a period, so a file nameddot-zshrcis linked as.zshrc. Handy if you don't like hidden files in your repository.--adoptmoves an existing conflicting file into the package. The manual warns that this changes your stow directory, and suggests comparing the result withgit diffand keeping or discarding it.
Option 3: a bare repository with your home folder as the work tree
This layout has no symlinks. Git keeps its data in one directory and treats your home folder as the working tree. Git's documentation describes a bare repository as a directory, normally named with a .git suffix, with no checked-out copy of the files. The --git-dir and --work-tree options, documented on the git page, let you point Git at that directory and at your home folder.
git init --bare $HOME/.dotfiles.git
alias dot='git --git-dir=$HOME/.dotfiles.git --work-tree=$HOME'
dot config status.showUntrackedFiles no
dot add ~/.zshrc ~/.gitconfig
dot commit -m "Add zshrc and gitconfig"That showUntrackedFiles line matters. Without it, dot status lists everything else in your home folder. The git status documentation describes this setting and the catch: with untracked files hidden, you have to remember to dot add new files yourself.
Put the alias in your .zshrc so it survives a new shell. Because Git is looking at your whole home folder, a careless dot add . is the main risk here. Add files by name.
Setting up a new Mac from the repository
For Stow, install Git and Stow (Homebrew has both), clone the repository, and run the same commands:
git clone https://github.com/you/dotfiles.git ~/dotfiles
cd ~/dotfiles && stow -n -v zsh git vim && stow zsh git vimFor the bare layout, clone with --bare and check out into your home folder:
git clone --bare https://github.com/you/dotfiles.git $HOME/.dotfiles.git
alias dot='git --git-dir=$HOME/.dotfiles.git --work-tree=$HOME'
dot checkout
dot config status.showUntrackedFiles noA fresh Mac often already has a default .zshrc. Both tools refuse to overwrite it, so move the old file aside first, then run the command again. For settings that differ per machine, such as a work email in .gitconfig, include a local file that is not tracked.
Doing this with Carets
A dotfiles repository is plain text, which is the format Carets is built around. Carets is a native editor for iPhone, iPad, and Mac, so your shell, Git, and tool config open next to your notes and code in the same app, organized into files, projects, and tags. Keep a dotfiles project with your key files and a note of the commands from this page.
Syntax highlighting earns its keep on config and shell files: a stray quote or a misplaced export stands out before you commit it. Your files stay plain text, so they work with Git, Stow, or whichever layout you pick. Once your files are tracked, you can version-control your notes with Git the same way.
Get Carets for iPhone, iPad, and Mac on the App Store.
Frequently Asked Questions
Should my dotfiles repository be public or private?
Private is the safe default. Even without secrets, config files reveal host names, usernames, and habits. Make it public only after you have read every file and moved anything sensitive out.
Do I need Stow or a bare repository, or are plain symlinks enough?
Plain symlinks are enough for a handful of files. Stow helps when you have many files and want to install or remove groups of them in one command. A bare repository suits you if you want no symlinks at all.
How do I keep secrets out of a dotfiles repository?
Keep tokens and keys in files that are never tracked, and have your tracked config include them, for example through a local override file listed in .gitignore. Review git status before each commit.
How do I set up a new Mac from my dotfiles?
Install Git, clone the repository, and run your install step: stow for each package, or dot checkout for the bare layout. If a tool complains about an existing file, move that file aside and run the command again.