agentleFS
openshiftopenshift/hypershift/skills/restructure-commits/SKILL.md

restructure-commits

Skill551 starsChanged 6 months agoApache-2.0View on GitHub

Restructure branch commits into logical component-based commits for HyperShift PRs

  • Deletes or force-pushes
  • Commits and pushes

The file

We split this skill into the rules it gives an agent

8 rules. About 0 are common, 2 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Commit groups in this order and skip groups with no changes:

    line 23
  2. Very specific:

    Only test/, api//*_test.go, and CRD envtest suites go to E2E.

    line 48
  3. Very specific:

    If the remote branch has commits that are not in local HEAD (review suggestions, "Update branch", a collaborator's push), stop and ask the …

    line 81
  4. Very specific:

    Finish background work: Wait for running generators, formatters, make update, or tests that write files.

    line 84
  5. Very specific:

    Handle existing work explicitly: If git status --porcelain --untracked-files=all is not empty, stop and ask whether to commit it to the …

    line 85
  6. Distinctive:

    Never use git reset --hard, git checkout -- ., git clean, or drop stashes or branches.

    line 88
  7. Very specific:

    Read and follow skills/git-commit-format/SKILL.md directly (harnesses with native skill support may load it as the git-commit-format skill).

    line 148
  8. Very specific:

    Use the group's prefix from the table.

    line 151

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Restructure Commits by Component

Rewrite a feature branch into one commit per architectural group (API, Dependencies, Vendor, CLI, HO, CPO, E2E, Docs, Tooling) without changing the branch's final file content.

This is the canonical, model-neutral procedure. Any coding agent or human can follow it with git, python3 (standard library only), make, and optionally gh. All paths are relative to the repository root.

When to Use

  • The user asks to "redo", "restructure", "squash by component", or "organize" commits
  • Preparing a branch for PR review, or cleaning history after addressing review comments

Ownership

ownership.json maps every path to a group; commit_layout.py applies it. Both the file and the table below are generated by generate_ownership.py (make ownership-rules, also run by make update); never edit them by hand. Commit groups in this order and skip groups with no changes:

<!-- BEGIN GENERATED: python3 skills/restructure-commits/generate_ownership.py -->
OrderGroupCommit prefixAllowed <type>Owns
1API<type>(api)feat, fix, build, refactorAPI types, markers, and the api/ module definition (api/go.mod and api/go.sum stay together)
2Dependenciesbuild(deps)fixedRoot, tools, and workspace module definitions; never mixed with generated vendor trees
3Vendorchore(api)fixedGenerated output: vendor trees, clients, zz_generated files, generated CRD manifests, and other files marked as generated
4CLI<type>(cli)feat, fix, refactor, testhypershift and hcp CLIs, with their tests, testdata, and fixtures
5HO<type>(hypershift-operator)feat, fix, refactor, perf, testhypershift-operator binaries and Go code shared by binaries of more than one group
6CPO<type>(control-plane-operator)feat, fix, refactor, perf, testcontrol-plane-operator binaries and the Go code only they use, such as control plane sidecars
7E2Etest(e2e)fixedE2E, integration, and envtest suites, including API validation tests
8DocsdocsfixedUser and contributor documentation and agent guidance files
9Tooling<type>(<scope>)build, ci, chore, docsEverything else: build system, CI configuration, scripts, container builds, helper modules, AI agent tooling
<!-- END GENERATED -->
  • Derived, not curated. Each binary built by make build belongs to the group in the generator's policy, and other top-level Go directories follow the binaries that import them (several groups: HO; none: Tooling). Files marked as generated, Makefile output directories, and vendor trees go to Vendor; hand-written files inside them keep their component's group.
  • First match wins. Specific exceptions are listed before broad directories; ownership.json lists the rules in precedence order with the reason for each.
  • Modules vs generated trees: api/go.mod and api/go.sum stay in API; root, tools, and workspace module files go in Dependencies; every vendor tree goes in Vendor. A commit must never mix module definitions with vendor output.
  • Tests and fixtures: component tests, testdata/, and zz_fixture_* files stay with their owning component. Only test/, api/**/*_test.go, and CRD envtest suites go to E2E.
  • No silent defaults: an unclassified path blocks the rewrite. Run make ownership-rules, which gives every path in the checkout a group, and commit the result before the snapshot. If a derived group is wrong, agree the right one with the user and change the generator's policy (see Maintenance).
  • Several consecutive commits in the same group are allowed; groups must never interleave or appear out of order.

Procedure

TOOL=skills/restructure-commits/commit_layout.py

1. Preflight (read-only except for the backup branch)

  1. Resolve the real target. Determine the PR base repository and branch, for example from gh pr view --json url,baseRefName; ask the user when there is no PR. Pick the remote whose URL points at that base repository and the remote that hosts the PR branch. Do not assume remote names, do not assume main (release branches are valid targets), and do not rebase unless the user asks for it.

    BRANCH=$(git symbolic-ref --short HEAD)
    TARGET_REMOTE=<remote for the PR base repository>
    TARGET_BRANCH=<PR base branch, e.g. main or release-4.18>
    PUSH_REMOTE=<remote that hosts $BRANCH>
    git fetch "$TARGET_REMOTE" "refs/heads/$TARGET_BRANCH"
    MERGE_BASE=$(git merge-base FETCH_HEAD HEAD)
    PUSHED_SHA=$(git ls-remote "$PUSH_REMOTE" "refs/heads/$BRANCH" | cut -f1)   # empty if never pushed
    if [ -n "$PUSHED_SHA" ]; then
      git fetch "$PUSH_REMOTE" "refs/heads/$BRANCH"
      git merge-base --is-ancestor "$PUSHED_SHA" HEAD || echo "STOP: remote $BRANCH has commits not in HEAD"
    fi

    If the remote branch has commits that are not in local HEAD (review suggestions, "Update branch", a collaborator's push), stop and ask the user to integrate them first; the rewrite would otherwise discard them.

  2. Finish background work. Wait for running generators, formatters, make update, or tests that write files.
  3. Handle existing work explicitly. If git status --porcelain --untracked-files=all is not empty, stop and ask whether to commit it to the branch first, stash it with git stash push --include-untracked -m "restructure-commits: preserved work" (restore it at the end), or abort. Never use git reset --hard, git checkout -- ., git clean, or drop stashes or branches.
  4. Record the snapshot and create a backup branch. Report these values to the user.

    ORIG_HEAD_SHA=$(git rev-parse HEAD)
    ORIG_TREE=$(git rev-parse "HEAD^{tree}")
    BACKUP="backup/restructure/$BRANCH-$(date +%Y%m%d%H%M%S)"
    git branch "$BACKUP" "$ORIG_HEAD_SHA"
  5. Show the complete plan. Resolve every unclassified path, then present the file-to-commit plan with the proposed commit subjects and get the user's approval before rewriting.

    python3 "$TOOL" plan --base "$MERGE_BASE" --head "$ORIG_HEAD_SHA"

2. Rewrite history (lossless)

git reset --soft "$MERGE_BASE" && git reset -q   # index = merge base; working tree still equals $ORIG_TREE

For each non-empty group, in table order:

python3 "$TOOL" stage --base "$MERGE_BASE" --head "$ORIG_HEAD_SHA" --group <GROUP>
git commit -s   # message rules below

stage copies exactly that group's paths (including deletions and paths with spaces) from the snapshot into the index and fails if anything else is staged.

3. Verify (required before declaring completion)

python3 "$TOOL" verify --base "$MERGE_BASE" --head HEAD --expect-tree "$ORIG_TREE"
make run-gitlint PULL_BASE_SHA="$MERGE_BASE" PULL_PULL_SHA=HEAD   # message syntax only, not file grouping
git status --porcelain --untracked-files=all                        # must be empty

make verify-commit-layout BASE="$MERGE_BASE" EXPECT_TREE="$ORIG_TREE" is equivalent to the first command. Without make, run gitlint --commits "$MERGE_BASE..HEAD" instead. The layout check verifies that every commit in the range touches a single group, that groups are in order, and that no path is unclassified, and confirms the final tree equals the snapshot. If it fails, do not push: fix the commits and re-run, or show git diff "$ORIG_TREE" HEAD and, with the user's agreement, return to the snapshot with git reset --keep "$BACKUP". Restore any stash from preflight with git stash pop.

4. Push (only after explicit user confirmation)

git push --force-with-lease="refs/heads/$BRANCH:$PUSHED_SHA" "$PUSH_REMOTE" "HEAD:refs/heads/$BRANCH"

The lease protects against remote updates made after preflight (earlier ones were checked in preflight). If it is rejected, stop and ask. Keep $BACKUP until the user agrees to delete it.

Commit Messages

Read and follow skills/git-commit-format/SKILL.md directly (harnesses with native skill support may load it as the git-commit-format skill). Validate with gitlint as shown above.

  • Use the group's prefix from the table. Where it contains <type>, pick the allowed type that describes the change (feat new behavior, fix bug fix, build dependency or build change, refactor restructuring or removal, perf performance, test test or fixture-only change); for Tooling also choose a fitting scope such as ci(envtest). Fixed prefixes are used as-is; Docs is docs: without a scope.
  • Subject: imperative mood, describes the purpose (for example build(deps): bump Kubernetes dependencies to 1.37).
  • Body: what changed and why, bullets for distinct changes; title at most 120 and body lines at most 140 characters.

Maintenance

  • Change ownership: edit the POLICY section of generate_ownership.py (groups, binary groups, conventions), then run make ownership-rules and make test-commit-layout. Because make update regenerates the rules, make verify fails when a PR leaves ownership.json or this table stale.
  • Practice or demonstrate: python3 skills/restructure-commits/sample_branch.py <empty-dir> builds a repository whose branch reproduces the PR #9568 module/vendor mistake; follow this procedure in <empty-dir>/work.
  • Enforcement scope: the layout check is a required gate of this workflow only; it is not enforced repository-wide by pre-push hooks or CI. Gitlint remains the repository-wide message check. The tool's own tests run in the path-filtered Unit Tests (Restructure Commits) GitHub workflow.
  • Adapters: harness-specific entry points (.claude/skills/restructure-commits/SKILL.md, .cursor/rules/restructure-commits.mdc) only point here. Replace personal copies (such as a user-installed restructure-hypershift-commits skill) with a pointer to this file instead of maintaining separate rules.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.