I use a system I call homegit to manage config files and scripts in my home directory on all my machines. The idea is simple: a Git repository rooted at ~ that I push to GitHub. I’ve used this system for 6 years and like it a lot. See below to set it up for yourself!

The core functionality comes from 3 lines in my ~/.bashrc:

homegit() {
    git --git-dir=$HOME/.homegit --work-tree=$HOME "$@"
}

This defines a command homegit that works like regular git except that it saves its state in ~/.homegit (as opposed to ~/.git). Having a special command helps avoid accidents, like thinking I’m in a project repo, running git clean -dfx, and deleting everything in my home. I also use git_prompt_info in my Zsh PS1 to show my current Git branch, and by using --git-dir=$HOME/.homegit I avoid seeing branch information all the time.

I also define this command:

homegit-private() {
    git --git-dir=$HOME/.homegit-private --work-tree=$HOME "$@"
}

homegit-private works just like homegit, with the same Git toplevel dir (!) The difference is that I push the contents to a private repo. This allows me to version things like my SSH config and easily keep it in sync across devices. It’s also where I put anything that isn’t the same between my home and work setups.

When I want to pull my dotfiles onto a new device, I run these commands:

git clone git@github.com:kerrickstaley/homedir
mv homedir/.git ~/.homegit
git --git-dir=$HOME/.homegit diff  # check that the next command won't overwrite anything
git --git-dir=$HOME/.homegit reset --hard HEAD

The last piece that helps with all this is the runningon command. This allows me to put conditional blocks in my rc files like this:

# Default to Gnu binaries on macOS.
if runningon macos; then
    export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH"  # coreutils
    export PATH="/opt/homebrew/opt/grep/libexec/gnubin:$PATH"       # grep
    export PATH="/opt/homebrew/opt/gnu-sed/libexec/gnubin:$PATH"    # sed
    export PATH="/opt/homebrew/opt/gnu-tar/libexec/gnubin:$PATH"    # tar
fi

That way, I can use the same rc files on both macOS and Linux, at both home and work.

If you want to use this system yourself, you just need to copy these 7 lines into your .bashrc or .zshrc, and copy the runningon script into your ~/bin and modify the list of hostnames.

Update 2023-11-25:

The vcs-home wiki page links to many other approaches to this idea.

To avoid messy git status output, I’ve run

homegit config status.showUntrackedFiles no

on all my machines as suggested in this HN post.