GitHub controls reference¶
Golden-path controls validated on WU repos (e.g. wiresuncrossed/hoen-assessment).
Use with diagnostic-prompt.md.
Concepts¶
| Mechanism | Purpose |
|---|---|
| Rulesets | Modern replacement for branch protection; org or repo scoped |
| Branch protection (legacy API) | May 404 when rulesets-only — use rulesets API |
| Repo merge settings | Which merge buttons appear on PRs |
| Merge method ruleset rule | Restrict PR merges to rebase / squash / merge commit |
| Push rulesets | Block pushes by file size, path, etc. |
Stacking: org rulesets + repo rulesets both apply. Repo settings must allow any merge method the ruleset requires.
Ghost branches and squash¶
Squash merge creates one new commit on main. The PR branch tip is not an
ancestor of that commit → GitHub shows "1 commit ahead" on stale branches.
Rebase merge replays commits onto main so branch tips become ancestors
(when branch is updated). Auto-delete head branches removes stale refs.
Scan commands¶
Install gh first if needed — see gh-cli-install.md
(Windows, Git Bash, macOS, Linux/WSL).
Single repo¶
OWNER=wiresuncrossed
REPO=hoen-assessment
gh repo view "$OWNER/$REPO" \
--json name,defaultBranchRef,mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed,deleteBranchOnMerge
gh api "repos/$OWNER/$REPO/rulesets" \
--jq '.[] | {id, name, source_type, enforcement, target}'
# Detail for each ruleset ID
gh api "repos/$OWNER/$REPO/rulesets/16769475" \
--jq '{name, enforcement, conditions, rules}'
All org repos (summary loop)¶
ORG=wiresuncrossed
gh repo list "$ORG" --limit 200 --json name,isArchived \
--jq '.[] | select(.isArchived == false) | .name' | while read -r repo; do
echo "## $repo"
gh repo view "$ORG/$repo" \
--json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed,deleteBranchOnMerge \
--jq .
gh api "repos/$ORG/$repo/rulesets" --jq '.[].name' 2>/dev/null || echo "(none)"
echo
done
Org rulesets (requires org admin scope)¶
Golden-path — repo settings only¶
Pilot on one repo before org rollout:
gh repo edit "$OWNER/$REPO" \
--enable-merge-commit=false \
--enable-squash-merge=false \
--enable-rebase-merge=true \
--delete-branch-on-merge=true \
--allow-update-branch
Verify:
gh repo view "$OWNER/$REPO" \
--json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed,deleteBranchOnMerge
Golden-path — rulesets (UI)¶
Create at Settings → Rules → Rulesets → New branch ruleset (repo) or Organization settings → Rules → Rulesets (org).
Protect Main (branch ruleset)¶
| Rule | Setting |
|---|---|
| Target | Default branch / refs/heads/main |
| Restrict deletions | On |
| Block force pushes | On (non_fast_forward) |
| Require linear history | On |
Rebase merge only (branch ruleset)¶
Add rule: Pull request merge method → allow Rebase only.
Requires repo: allow_rebase_merge=true, squash and merge commit disabled.
No large files (push ruleset)¶
| Setting | Example |
|---|---|
| Target | Push |
| Max file size | 3 MB |
| Enforcement | Active |
Org-level example name: No large files (>3mb).
UI audit mode (no gh)¶
Ask the user for screenshots or values from:
- Settings → Rules → Rulesets — list names, enforcement, targets, rule types
- Settings → General → Pull Requests — merge commit / squash / rebase toggles; auto-delete head branches
- Settings → General — default branch name
- Branches page — behind/ahead on stale feature branches (ghost-branch check)
Remediation — large file already in git¶
- Move artifact to R2 / release asset / LFS
- Update docs to link or download instructions (not a raw blob in repo)
- Remove from tree; add path to
.gitignore - Rewrite feature branch history:
# Prefer git-filter-repo (install separately)
git filter-repo --path "path/to/large.zip" --invert-paths --force
# Or filter-branch (built-in, slower)
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f \
--index-filter 'git rm --cached --ignore-unmatch "path/to/large.zip"' \
-- BRANCH_NAME
git push --force-with-lease origin BRANCH_NAME— user approval required- Rewriting
mainrequires org admin and team coordination