docs(gitflow): manual-push mode — SETTINGS push discipline, gitflow skill rows, CHANGELOG

This commit is contained in:
bchanot
2026-10-06 18:03:35 +02:00
parent e6cccc1740
commit afd6073371
3 changed files with 28 additions and 10 deletions
+9
View File
@@ -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 <br>` 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).
+8 -4
View File
@@ -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/<br> 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/<br> left in place (manual push mode)" | Expected in manual-push mode, not a failure. Pass the printed `git push origin --delete <br>` to the user; never run it (manual mode: no push unless the user asks, and `push --delete` is denied by settings) |
| `start`/`finish` warning "<base> is behind origin/<base> 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
+11 -6
View File
@@ -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)