chore(workflow): branch-and-PR working method + ADR-number reservation (ADR-0059)
Adopt a trackable working method now the repo is public: - PRs onto a protected main; --no-ff merge commits; one worktree per branch. - Reserve-first ADR numbering: scripts/adr-reserve.sh claims the next number atomically against main (push = compare-and-swap; ledger docs/adr/RESERVATIONS.log), so a number is stable from creation. - Worktree helpers scripts/wt-new.sh + wt-clean.sh. - Local-origin test harnesses (reserve 10/10, worktrees 7/7, shellcheck clean). Record the decision in ADR-0059, supersede ADR-0000's placeholder-until-merge numbering default, and add the lean CONTRIBUTING.md sections + CLAUDE.md operational rules.
This commit is contained in:
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# wt-new.sh — start a branch in its own git worktree.
|
||||
#
|
||||
# WHY: every branch is developed in an isolated worktree, never by switching
|
||||
# the primary checkout (two shells in one checkout is how you clobber work).
|
||||
# This creates the branch off an up-to-date `main` and a sibling worktree
|
||||
# named to match the repo's existing convention:
|
||||
#
|
||||
# <parent>/<repo>-worktree-<last-segment-of-branch>
|
||||
# e.g. feat/clause-concept-hints -> ../rdbms-playground-worktree-clause-concept-hints
|
||||
#
|
||||
# USAGE
|
||||
# scripts/wt-new.sh <branch>
|
||||
# scripts/wt-new.sh feat/clause-concept-hints
|
||||
#
|
||||
# Prints the new worktree path; cd there to start working.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
log() { printf ' wt-new: %s\n' "$*" >&2; }
|
||||
die() { printf 'wt-new: ERROR: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[ $# -eq 1 ] || die "usage: wt-new.sh <branch> (e.g. feat/my-thing)"
|
||||
branch="$1"
|
||||
|
||||
# Conventional prefixes keep branch names aligned with commit types.
|
||||
case "$branch" in
|
||||
feat/*|fix/*|docs/*|chore/*|refactor/*|test/*|ci/*) : ;;
|
||||
*) die "branch should start with feat/ fix/ docs/ chore/ refactor/ test/ ci/ (got: $branch)" ;;
|
||||
esac
|
||||
|
||||
git rev-parse --git-dir >/dev/null 2>&1 || die "not inside a git repo"
|
||||
|
||||
# Sibling-of-the-primary-checkout location, matching existing worktrees.
|
||||
main_wt="$(git worktree list --porcelain | awk '/^worktree /{print $2; exit}')"
|
||||
parent="$(dirname "$main_wt")"
|
||||
repo="$(basename "$main_wt")"
|
||||
seg="${branch##*/}"
|
||||
target="$parent/${repo}-worktree-${seg}"
|
||||
|
||||
[ -e "$target" ] && die "worktree path already exists: $target"
|
||||
git show-ref --verify --quiet "refs/heads/$branch" \
|
||||
&& die "branch already exists: $branch (use 'git worktree add' to attach a worktree to it)"
|
||||
|
||||
log "fetching origin/main"
|
||||
git fetch --quiet origin main || die "git fetch origin main failed"
|
||||
|
||||
log "creating branch '$branch' + worktree at $target"
|
||||
git worktree add --quiet -b "$branch" "$target" origin/main \
|
||||
|| die "git worktree add failed"
|
||||
|
||||
log "ready — cd into it:"
|
||||
echo "$target"
|
||||
Reference in New Issue
Block a user