Skip to content

wip init step 8 reads every refused push as the PR-only ruleset: a checkout merely behind main is sent to an administrator #140

Open

Description

@brettheap

Found while building #64 (PR #139). This predates that PR, and step 8's push is outside its scope, so it is filed here and not fixed there.

What happens. When git push -q origin HEAD:main fails for any reason, step 8 of openRepoTools wip init dies with the same refusal: "the seed commit could not be pushed … THAT IS THE RULESET … An administrator excludes <target> from it". That push also fails for two reasons that have nothing to do with the ruleset:

  1. The checkout is behind origin's main and has nothing of its own. Another workstation pushed and this one fetched (or did not). Step 8's gate is local_head != remote_head, so it pushes an ANCESTOR of main to main, which is rejected as non-fast-forward. The person is sent to an administrator, and the message talks about "the seed commit" even though no seed was committed on this run.
  2. The remote is unreachable (network down, bad URL). Step 6a's could-not-ask arm, and step 8's before it, fall through to the push as the probe. The push then fails for the same reason the question did, and the refusal blames the ruleset.

Reproduced on main @ cbb5981 and on PR #139's branch with a scratch bare remote. The adopted checkout was clean, fetched, and ## main...origin/main [behind 1]:

REFUSED: the seed commit could not be pushed to opensoft/brettheap-wip's main.
    THAT IS THE RULESET, and it is the thing this push exists to find out: the
…
exit=2

A shape for the fix, for whoever takes it. Step 8 keeps git's own stderr (wip_quietly, the way the clone and the commit already do). It names a non-fast-forward as such: local_head is an ancestor of remote_head (git merge-base --is-ancestor), so there is nothing to push. In that case, "bring the checkout current" is the remedy and not an administrator, and whether a checkout that is only behind should push at all is part of the question. The ruleset sentence is kept for the case where the remote answered and rejected a fast-forward. PR #139 already refuses the unfetched variant of case 1 at step 6a, before a byte is written (the range cannot be listed). The fetched-and-behind variant passes 6a, because there is nothing ahead, and reaches this.

Lane: openRepoTools-1

Activity

  1. brettheap commented on Oct 6, 2026

    @brettheap
    ContributorAuthor

    Deferred under Brett Heap's close-out direction of 2026-10-06 (no new feature PRs until the existing openRepoTools PRs are landed for the triad migration). Lane openRepoTools-1 claimed this, a writer read the ground and designed the fix, and stopped before writing code; the claim is released and the design below is the handover.

    Design. In step 8 replace the bare git push -q origin HEAD:main >/dev/null 2>&1 with wip_quietly git -C "$checkout" push -q origin HEAD:main and classify $WIP_LAST_ERR: "non-fast-forward" / "fetch first" / "behind" → say the checkout is BEHIND and give git -C <checkout> pull --ff-only origin main, then re-run; "ruleset" / "rule" / "protected" / "not allowed" → keep today's administrator text including "THAT IS THE RULESET" (the suite's fake pre-receive hook prints "remote: refused by the PR-only ruleset", so "ruleset" must be in the pattern); anything else → git's words under "What it said:" and the plain re-run. Before the push, where remote_head is set and git merge-base --is-ancestor "$local_head" "$remote_head" holds, die with the pull remedy and never say "seed commit" — no second ls-remote is needed, because step 6a (#139) already read remote_head and refuses an unfetched one via rev-list.

    Tests. Existing test_a_remote_that_cannot_be_asked_skips_the_history_check_for_the_probe asserts "THAT IS THE RULESET" for an unreachable origin; under the classification that becomes the "What it said:" arm, so assert that step 8 was reached instead. New: BEHIND (a second clone pushes to main, this checkout git fetches, the pointer file is removed → the pull remedy, no administrator text, nothing pushed, no pointer file); RULESET (the existing hook or a "rule violations" message → administrator text); UNKNOWN (a hook printing something unrelated → git's words). README line ~196 ("a refused push is exit 2 naming the ruleset") must be reworded IN PLACE: the README is at its 486-line cap.

    Branch prepared (no commits): fix/wip-init-step7-guarded-writes-and-step8-refusal-words off main 2080f3d, local only. Shared with #105.

  2. brettheap commented on Oct 6, 2026

    @brettheap
    ContributorAuthor

    RELEASED — lane openRepoTools-1, session df82f553-7803-49c4-8ddf-3f9acdcb8ee0@Eagle, 2026-10-06T20:47:04Z, for #140 — deferred under Brett Heap's close-out direction of 2026-10-06; design posted on the issue; no code; no PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions