From 583bbaa5335d08b2bb05cc15e456aa475b18aac4 Mon Sep 17 00:00:00 2001 From: Jonny Barnes Date: Sun, 9 Aug 2026 09:57:19 +0100 Subject: [PATCH] Move git identity to an included ~/.gitconfig.local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ~/.extra ran five `git config --global` writes on every shell startup, to re-assert identity and signing after bootstrap.sh copies gitconfig over ~/.gitconfig. The dark-mode-notify agent fires on wake/unlock and runs `pkill -usr1 zsh`, so every shell re-sources .zshrc — and therefore .extra — simultaneously. `git config` locks with O_EXCL and has no retry or timeout for config files, so the concurrent writes raced and printed: error: could not lock config file /Users/jonny/.gitconfig: File exists Identity and signing now live in an untracked ~/.gitconfig.local, included last from gitconfig so it wins over anything above. bootstrap.sh seeds it from gitconfig.local.template only when absent, so re-runs never clobber the real signing key. No git writes happen on shell startup at all now. Verified: fully-resolved config is unchanged apart from the new include.path; author and committer both resolve from config with no GIT_* env vars set; existing commits still verify. 12 concurrent sources of .extra are silent, where the old version produced 27 lock errors. Co-Authored-By: Claude Opus 5 (1M context) --- bootstrap.sh | 11 ++++++++++- gitconfig | 6 ++++++ gitconfig.local.template | 23 +++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 gitconfig.local.template diff --git a/bootstrap.sh b/bootstrap.sh index 61f3a61..a2cf98f 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -48,10 +48,19 @@ test -L $HOME/.config/nvim/lsp/phpactor.lua || ln -f -s $BASEDIR/neovim/lsp/phpa test -d $HOME/.claude || mkdir $HOME/.claude ln -f -s $BASEDIR/claude/statusline.isaacaudet.sh $HOME/.claude/statusline.sh -# .gitconfig gets edited by .extra so we won't symlink it, but copy it +# Copy rather than symlink, so an ad-hoc `git config --global` writes to $HOME +# and not into the repo. echo "For compatibility we shall copy the global gitconfig" cp $BASEDIR/gitconfig $HOME/.gitconfig +# Identity and signing live in ~/.gitconfig.local, which the above includes. +# It is per-machine and untracked, so seed it from the template. Never +# overwrite an existing one: it holds the real signing key. +test -e $HOME/.gitconfig.local || { + echo "Seeding ~/.gitconfig.local from template — fill in your identity" + cp $BASEDIR/gitconfig.local.template $HOME/.gitconfig.local +} + # Copy the progs into the local bin dir rsync -av --chmod=+x $BASEDIR/bin/ $HOME/.local/bin/ diff --git a/gitconfig b/gitconfig index 8f4a064..440297a 100644 --- a/gitconfig +++ b/gitconfig @@ -87,3 +87,9 @@ autoSquash = true autoStash = true updateRefs = true + +# Machine-local identity and signing config. Untracked, and included last so +# it wins over anything above. Keeps `bootstrap.sh`'s copy of this file +# non-destructive without needing to re-apply values on every shell startup. +[include] + path = ~/.gitconfig.local diff --git a/gitconfig.local.template b/gitconfig.local.template new file mode 100644 index 0000000..c570566 --- /dev/null +++ b/gitconfig.local.template @@ -0,0 +1,23 @@ +# Machine-local git config, included from the end of ~/.gitconfig. +# +# This file is NOT tracked in the dotfiles repo — it is per-machine, and holds +# the identity and signing key. bootstrap.sh copies this template into place +# only if ~/.gitconfig.local does not already exist, so your real values are +# never clobbered by a re-run. +# +# Uncomment and fill these in on a new machine. Do not skip this: git will not +# refuse to commit. It auto-derives an identity from your username and hostname +# (e.g. jonny@Jonnys-MacBook.local), prints a "configured automatically" +# warning, exits 0, and does no signing at all. + +#[user] +# name = Your Name +# email = you@example.com +# signingkey = ssh-ed25519 AAAA... + +#[commit] +# gpgsign = true + +# Path to the signing program, if signing SSH-style via a password manager. +#[gpg "ssh"] +# program = /Applications/1Password.app/Contents/MacOS/op-ssh-sign