From 549e67670074c82ca9303a647a5c68cf5529959f Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 10 May 2026 12:59:07 -0500 Subject: docs(commits): add Step 0 pre-flight reconcile and pre-push check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The publish flow had no fetch step before commit, PR creation, or push. Long sessions or multi-machine work could land local commits on a stale base, producing non-fast-forward push failures that you have to unwind under publish-step pressure. Step 0 fetches all remotes and checks the current branch against its upstream before Step 1's code review. If the branch is behind, the rule branches on tree state and divergence shape: clean fast-forward, surface dirty-tree behind, or surface a true divergence and ask before rebasing or merging. The Step 0 wording covers the new-branch case (no upstream → skip the divergence check, the first push sets it). The Pre-push reconcile bullet in Merge Strategy handles the smaller window between Step 0 and the actual push. Reviewing and drafting can take several minutes; another machine or teammate can push during that window. One more fetch immediately before push is cheaper than recovering after a failed push. --- claude-rules/commits.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/claude-rules/commits.md b/claude-rules/commits.md index 84f408b..754c53f 100644 --- a/claude-rules/commits.md +++ b/claude-rules/commits.md @@ -218,9 +218,52 @@ problem belong out. Same conciseness pressure as commit-message bodies. Commits and PRs are team-visible, permanent, and hard to amend once shared (especially after push or after a reviewer has replied). Before executing `git commit` or `gh pr create`, the change must pass a local code review -*and* the message must be reviewed by the user. The flow has two steps, in +*and* the message must be reviewed by the user. The flow has three steps, in order. +### Step 0: pre-flight reconcile (mandatory) + +Before reviewing the diff, fetch from the remote and reconcile against the +upstream of the current branch. Reconciliation can change the working state +when a rebase brings in upstream commits that touch staged files, and that +would invalidate Step 1's review. Handling drift first means the review and +the commit message describe the post-reconcile state. + +1. Fetch all remotes: + + git fetch --all --prune + +2. If the current branch has no upstream (new branch, never pushed), skip + to Step 1 — there's nothing to reconcile against, and the first push + sets the upstream. + +3. Otherwise, check divergence against `@{u}`: + + git rev-list --left-right --count @{u}...HEAD + + Output is `\t`. Decide based on the pair: + + - **0 behind, anything ahead** — no-op. Continue to Step 1. + - **Behind only, clean tree** — fast-forward: `git merge --ff-only @{u}`. + - **Behind only, dirty tree** — surface to the user. Don't auto-stash or + auto-merge. Offer to commit or stash first, or skip the reconcile and + proceed knowing the push may need attention later. + - **Diverged (behind AND ahead)** — surface to the user. Ask whether to + rebase the local commits onto upstream (default for feature branches), + merge the upstream branch in (rare; preserves both lines), or skip and + proceed with the divergence. Don't auto-rebase. + +4. **PR flow only.** Also fetch the base branch (usually `main`) and check + whether the feature branch's base is behind. Surface this informationally; + don't auto-rebase the feature branch without asking. The "X commits + behind base" badge on the PR is a follow-up decision, not a reason to + block publish. + +The startup workflow's `git fetch --all --prune` doesn't substitute for +Step 0. Upstream can advance during a long session, especially across +machines or with teammates pushing in parallel. Run Step 0 every time the +publish flow starts. + ### Step 1: local code review (mandatory) Run the `review-code` skill against the change: @@ -406,6 +449,13 @@ independent gate. confirmation before `git push`, `gh pr merge`, or any equivalent. The Review and Publish flow above approves the *content*; merge strategy is a separate decision that needs its own confirmation. +- *Pre-push reconcile.* Right before `git push`, do one more + `git fetch ` and verify the local branch is still + ahead-only against its upstream. If something landed between Step 0 and + push (review and draft together can take several minutes, and another + machine or teammate may push in that window), surface and resolve before + the push command runs. Catching drift here is cheaper than recovering + from a failed non-fast-forward push under publish-step pressure. - Override the squash default only when there's a concrete reason: a clean per-commit review history the user has explicitly asked for, a multi-commit semantic narrative the team values, etc. Squash is the -- cgit v1.2.3