diff --git a/CHANGELOG.md b/CHANGELOG.md index a521455..1956865 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ Format follows [Keep a Changelog](https://keepachangelog.com/) and this project ## [Unreleased] +### Added +- **Manual-push mode**: `git config gitflow.autopush false` (human-set) now stops every push the gitflow lib makes, not only the post-commit / post-merge hooks. `gitflow start` and `finish` branch, commit and merge locally and push nothing; `gitflow delete` leaves the `origin/` copy in place and prints `git push origin --delete
` for the user to run. `hooks/unpushed-guard.sh` stays silent at turn end in this mode and opens each session with one `ℹ manual push mode:` line counting the commits no remote holds across every local branch; an unparseable `gitflow.autopush` value is named and treated as auto. Skills that push on their own do not honour the mode yet. Tests: `lib/gitflow-test.sh` T18m block, `lib/tests/unpushed-guard.test.sh` T10-T16. + +### Changed +- `gitflow start` and `finish` warn on stderr when a base is behind origin and cannot fast-forward, instead of a silent `git pull --ff-only || true` (T18l, T18n). + +### Fixed +- `gitflow delete` (and `finish`) land on the base that contains the branch and drop the branch's upstream before `git branch -d`, so a branch whose upstream lags (manual-push mode) is deleted instead of refused by git (T18k). + ## [2.0.0] — 2026-10-06 Upgrading from 1.x: see [MIGRATION.md](./MIGRATION.md#upgrading-an-existing-machine-to-200). diff --git a/skills/gitflow/SKILL.md b/skills/gitflow/SKILL.md index b5df56e..fd0bdd9 100644 --- a/skills/gitflow/SKILL.md +++ b/skills/gitflow/SKILL.md @@ -54,10 +54,12 @@ bash ~/.claude/lib/gitflow.sh protected-base [br] # rc 0 on main/develop — the `main`/`develop` (rc 6) and any branch not merged into develop or main (rc 5), and keeps the branch. The `origin/` copy is removed right after, once ITS tip passes the same check; a remote tip holding commits the bases lack is -kept, loudly (T24). Hand `git branch -d` is denied — with an auto-pushed -upstream it checks the wrong thing (T22a). A `reference-transaction` hook -vetoes any deletion or rename of `main`/`develop` at the ref layer, in every -repo. +kept, loudly (T24). In manual-push mode (`git config gitflow.autopush +false`, human-set) nothing is pushed: `start` and `finish` stay local, and +the `origin/` copy is left in place (T18i-T18k). Hand `git branch -d` is +denied — with an auto-pushed upstream it checks the wrong thing (T22a). A +`reference-transaction` hook vetoes any deletion or rename of +`main`/`develop` at the ref layer, in every repo. ## The finish gate — merge ONLY on an explicit human signal @@ -107,6 +109,8 @@ stays human-gated. | `delete`/`finish` rc=5 — branch not merged into develop or main | The branch still holds unmerged work: KEEP it, report it, never fall back to `git branch -d`/`-D`. Merge first (human gate), then re-run | | `delete` rc=6 — protected base | `main`/`develop` are never deleted. Stop; the request itself is the defect to report | | `delete`/`finish` warning "remote copy KEPT" or "NOT removed" | Non-fatal BY CONTRACT (remote cleanup is best-effort). KEPT = origin/
has a tip the bases lack: fetch, look, merge or leave it — never `git push --delete` by hand. NOT removed = origin unreachable or refused: report the printed command to the user | +| `delete`/`finish` warning "origin/
left in place (manual push mode)" | Expected in manual-push mode, not a failure. Pass the printed `git push origin --delete
` to the user; never run it (manual mode: no push unless the user asks, and `push --delete` is denied by settings) | +| `start`/`finish` warning " is behind origin/ by N and cannot fast-forward" | Non-fatal BY CONTRACT: the branch is still created and the merge still runs on the local base. The base has diverged from origin: report it to the user, who reconciles (`git pull`, then push). Never rebase or force-push a base | ## Common Mistakes diff --git a/templates/settings/SETTINGS.md b/templates/settings/SETTINGS.md index dadeaf8..1ce8b61 100644 --- a/templates/settings/SETTINGS.md +++ b/templates/settings/SETTINGS.md @@ -167,12 +167,17 @@ fourth hook, `reference-transaction`, vetoes any deletion or rename of reach every repo two ways: `make link` generates `githooks/` from the lib and sets git's global `core.hooksPath` to `~/.claude/githooks` (a repo's own local `core.hooksPath` wins, by git's rules), and `hooks/session-start.sh` -refreshes a repo's `.githooks/` when it lags the lib. Per-repo opt-outs for -a foreign clone: `git config gitflow.protect false` (branch model) and -`git config gitflow.autopush false` (push); `GITFLOW_NO_PUSH=1` for one -command in a throwaway repo. `make doctor` checks the global setting and -the generated dir. `hooks/unpushed-guard.sh` reports a branch ahead of its -upstream at session start and at each turn end. +refreshes a repo's `.githooks/` when it lags the lib. Per-repo opt-outs, set +by a human: `git config gitflow.protect false` (branch model, foreign clone) +and `git config gitflow.autopush false` (manual-push mode: the hooks, +`start` and `finish` push nothing, and `delete` leaves the `origin/` copy in +place, printing the command to remove it by hand); `GITFLOW_NO_PUSH=1` for +one command in a throwaway repo. `start` and `finish` warn when a base is +behind origin and cannot fast-forward. `make doctor` checks the global +setting and the generated dir. `hooks/unpushed-guard.sh` reports a branch +ahead of its upstream at session start and at each turn end; in manual-push +mode it stays silent at turn end and gives one `ℹ manual push mode:` line at +session start, counting unpushed commits across every local branch. ## managed-settings.json (enterprise)