Skip to content

Safety fixes and installer - #1

Merged
skunkworker merged 3 commits into
masterfrom
safety-fixes-and-installer
Aug 14, 2026
Merged

Safety fixes and installer#1
skunkworker merged 3 commits into
masterfrom
safety-fixes-and-installer

Conversation

@skunkworker

Copy link
Copy Markdown
Owner

No description provided.

skunkworker and others added 3 commits August 12, 2026 23:39
Gone branches are always deleted with -D, so a gone branch holding work
that never reached the default branch was silently discardable. Each one
is now measured with `git cherry` (which recognizes cherry-picked,
rebased, and individually squashed commits as integrated); branches with
unique commits are left unselected by `p` and flagged on the
confirmation screen.

Also:
- resolve the default branch across all configured remotes, origin
  first, so forks whose only remote is `upstream` still get merge info
- truncate on cell width rather than byte count, fixing alignment for
  wide and multi-byte characters
- align the tracking column
- add MIT license, .gitignore, and docs/improvements.md

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
install.sh builds the binary and installs it to a user bin directory:
the first usable of ~/.local/bin or ~/bin, falling back to
/usr/local/bin via sudo, overridable with --bindir or $BINDIR. It builds
into a tempdir so the checkout stays clean, and warns when the target is
not on PATH.

POSIX sh (shellcheck-clean, verified under dash, bash 3.2, and zsh):
signal traps exit rather than resuming, CDPATH cannot redirect the cd to
the repo root, a relative --bindir resolves against the caller's cwd,
and an unset HOME does not trip set -u.

CI runs the installer's no-sudo path on both matrix OSes so it cannot
rot. Makefile BINDIR becomes ?= so `make clean BINDIR=...` can reach
what install.sh wrote.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A branch with no upstream was deleted with -d and failed at run time with
nothing having warned about it. Every safety indicator derived from the
ahead count, which git leaves at 0 for such a branch because it reports
no tracking info for one.

safeDeletable() now mirrors git's actual rule: a resolvable upstream is
the sole criterion, and HEAD is consulted only when there is no upstream
to ask. This is a precedence rather than an either-or -- git refuses a
branch that is ahead of its upstream even when HEAD already contains it.
Every branch the rule would refuse is measured with `git cherry`, so the
confirm screen states what a force delete would discard.

Also:
- the force prompt reports the measured count instead of the ahead
  count, which was 0 for exactly the branches reaching it without an
  upstream, leaving the prompt with nothing to show
- an armed remote delete is deferred when the local delete is refused,
  rather than removing the last copy of commits that still exist only
  locally; a successful force retry then honours the arming
- only an "not fully merged" refusal is offered as force-retryable. A
  branch held by another worktree fails identically under -D, so the
  retry could not have worked and mislabelled the cause. runGit pins
  LC_ALL=C so gettext cannot translate the string out from under it
- risk is measured lazily for the current selection. Measuring every
  unmergeable branch on load cost 1.1s of startup on a 61-branch repo;
  gone branches stay eager, since `p` consults the count to decide what
  it may auto-select

Tests cover each shape that decides the outcome, checking safeDeletable
against what `git branch -d` really does rather than against an
assumption about it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@skunkworker
skunkworker merged commit 3f47768 into master Aug 14, 2026
2 checks passed
@skunkworker
skunkworker deleted the safety-fixes-and-installer branch August 14, 2026 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant