Files
dotfiles/git/install.sh
T
noconnorandClaude Opus 5 098b1e377f git+zsh: stop tab-completion producing branch deletes that fail
`git push origin --delete <TAB>` completes to `origin/foo`, but `origin/foo` is
a LOCAL remote-tracking name — the ref on the server is just `foo`. So the
command zsh completes for you is the one git rejects, and it rejects it with
"remote ref does not exist", which reads as "that branch is gone" rather than
"you named it wrong".

The second half is worse, because it makes the first half look intermittent:
without pruning, `git branch -r` and the completion keep offering branches that
were deleted on the server weeks ago. Then some completions fail because the
branch is genuinely gone and others fail because of the prefix, with identical
error text.

Two fixes, one per cause:

- `fetch.prune = true` globally, so stale remote-tracking refs are dropped on
  every fetch/pull and dead branches stop being offered at all.
- `grmb`, which takes either form, prunes first, and reports per-branch rather
  than aborting the batch. `grmb origin/foo` and `grmb foo` both work.

Named grmb rather than the more obvious gbd because oh-my-zsh's git plugin
already binds gbd to `git branch --delete`. Aliases resolve before functions,
so the collision would not have errored — it would have silently tried to
delete a LOCAL branch when the whole point is the remote one. Caught by
`type gbd` after installing; check any new g* helper the same way.

grmb deliberately does not wrap `git push` itself — intercepting a git
subcommand to rewrite its arguments is the kind of thing that works until it
silently does the wrong thing to a refspec someone meant literally.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 14:58:22 -04:00

34 lines
1.4 KiB
Bash
Executable File

#!/usr/bin/env sh
# git/install.sh — configure git identity + HTTPS credential storage.
# Idempotent: safe to re-run.
set -eu
say() { printf '%s\n' "$*" >&2; }
GIT_NAME="Nic O'Connor"
GIT_EMAIL="nic.oconnor@gmail.com"
git config --global user.name "$GIT_NAME"
git config --global user.email "$GIT_EMAIL"
say "git identity: $GIT_NAME <$GIT_EMAIL>"
# Auto-prune stale remote-tracking refs on every fetch/pull.
#
# Without this, `git branch -r` keeps listing branches that were deleted on the
# server, and zsh's git completion happily offers them — so you tab-complete a
# branch name into `git push origin --delete` and get "remote ref does not
# exist" for something that was already gone. The prefix makes it worse: the
# completion offers `origin/foo`, but the ref on the server is just `foo`, so
# even a live branch fails unless you strip it by hand. See the `gbd` helper in
# zsh/zshrc (the grmb helper) for that half.
git config --global fetch.prune true
say "fetch.prune = true (stale remote-tracking refs cleaned on every fetch)"
# Plaintext credential cache in $HOME (survives container/VM rebuilds that
# wipe everything outside $HOME). Git creates ~/.git-credentials with 0600
# the first time a credential is saved.
git config --global credential.helper store
say "credential.helper = store (~/.git-credentials, created on first auth)"
say "Done. On the next HTTPS push/pull to a new host, git prompts once and caches the credential in ~/.git-credentials."