Hacker News new | ask | show | jobs
by tdfirth 1867 days ago
I've been using this bare repository approach for a while. I forget where I first saw it, I'm pretty sure it was on HN but it was not this project. I do like it, but I have a few minor issues.

The first is that I have a habit of running `git add .` when I'm working on source code, and as a result I have accidentally added my entire home directory to the bare repo more than once... Easy enough to undo but a bit inconvenient. `dotfiles add -u` is the safe option, or just be explicit about which files you are staging.

The second issue is the 'branch per machine' approach, which I do use. I have two machines I use regularly, and a third occasionally. There are some bits of config (e.g. for vim) that are shared across all the machines, while other bits are not. If I use one machine for a while, then I end up with lots commits that I need to cherry pick when I next use another machine. Depending on how long it has been, this can be a bit of a faff.

Finally, because there is no clear mainline branch, you have to pick commits to/from any of the branches. If you are undisciplined like me, then this will leave you with a 'three way ahead and behind' scenario at some point.

Anyway, I like the approach overall. If anyone has a suggestion to ease those pain points I'm all ears.

4 comments

I, too, saw this approach on HN first – here: https://news.ycombinator.com/item?id=11071754

I combined the bare repo approach with a per-machine custom branch approach described in https://www.anishathalye.com/2014/08/03/managing-your-dotfil...

The idea is that you have the shared configuration in one repo, and at the end of each config file, you include a local version. The local versions live in a separate repository and use a separate branch for each machine.

For example, at the end of .bashrc, you'd have

    if [[ -r $HOME/.bashrc_local ]]; then
        . "$HOME/.bashrc_local"
    fi
and so on, for each config file. My general dotfiles repo is public here, if you want to take a look how I did it for the tools I use: https://github.com/bewuethr/dotfiles

This still isn't ideal. For example, I use Git submodules for Vim plugins in the shared repo – but maybe I don't need all of that on my Raspberry pi. I feel like at some point, a config file based solution could be better; or using a tool such as https://yadm.io/, which is using bare repos under the hood.

I do that too, with a function in my .profile that I can call in the `dotfiles/local` [1]. That lets me "advise" the global version of the file with before:

    cat ~/dotfiles/local/profile
    SETUP=goes.here
    load-global-config "$BASH_SOURCE"
after:

    cat ~/dotfiles/local/profile
    load-global-config "$BASH_SOURCE"
    MODIFY=${EXISTING:settings}
    OVERWRITE=options
    OTHER=things.too
and "around":

    cat ~/dotfiles/local/profile
    echo "BEFORE"
    load-global-config "$BASH_SOURCE"
    echo "AND AFTER"
The nice thing about keeping local dotfiles in a separate directory is that you can `.gitignore` it for your "public" dotfiles repository, but still keep the local dotfiles under source control easily.

[1]: https://github.com/svieira/dotfiles/blob/4b7e948b698b623a498...

Yes that comment is where I first saw it, thanks for reminding me.

Thanks for those pointers and the link to your dotfiles too. I will check that out and maybe steal a couple of ideas!!

I use a normal dotfiles repository with an install script that symlinks files out. My solution for multi-machine is that the install script just checks for a file suffixed by -$HOSTNAME to link instead:

    install() {
        SRC=$DOTFILES/$1
        if [ -e "$SRC-$HOSTNAME" ]; then
            SRC="$SRC-$HOSTNAME"
        fi
        echo "installing $SRC -> $2"
        mkdir -p $(dirname "$2")
        ln -sf "$SRC" "$2"
    }
    install vim ~/.vim
    install bashrc ~/.bashrc
    install gitconfig ~/.gitconfig
    # etc.
This is much simpler than messing around with branches since 99% of files are the same on different machines. Just add e.g. gitconfig-workpc to use a different git identity at work.

For some files I also support a +$HOSTNAME suffix that will append instead of override. In this case it assembles the destination file rather than creating a symlink. This is a bit annoying because you can't edit the destination file; you have to edit the originals and re-run the install script. But it's worth it in a few cases (e.g. i3 config) to reduce duplication.

Check out https://chezmoi.io/ - it solves all of these problems.
I have a `.gitignore` file with `*` in it to ignore all files, so I explicitly type `dotfiles add --force`.