From eb823fccdfe8a361c6fd0aaf7c3d6200247a1324 Mon Sep 17 00:00:00 2001 From: Patryk Matuszak Date: Wed, 20 May 2026 10:13:11 +0200 Subject: [PATCH] Agent Skill: Small commits / good git history --- .claude-plugin/marketplace.json | 32 ++- .../git-commits/.claude-plugin/plugin.json | 8 + plugins/git-commits/README.md | 45 ++++ .../git-commits/skills/small-commits/SKILL.md | 228 ++++++++++++++++++ 4 files changed, 300 insertions(+), 13 deletions(-) create mode 100644 plugins/git-commits/.claude-plugin/plugin.json create mode 100644 plugins/git-commits/README.md create mode 100644 plugins/git-commits/skills/small-commits/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index b4c88466..d06fc99d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -12,6 +12,12 @@ "description": "Adversarial hypothesis reviewer — systematically attacks theories and root cause analyses to find weaknesses before they find you", "version": "1.0.0" }, + { + "name": "edge-ic", + "source": "./plugins/edge-ic", + "description": "Individual contributor workflow automation for TODO management, status reporting, and Jira updates", + "version": "1.2.0" + }, { "name": "edge-ocp-ci", "source": "./plugins/edge-ocp-ci", @@ -24,6 +30,12 @@ "description": "Agents, skills, and workflows relevant to scrum process management for the OpenShift Edge Team", "version": "1.0.0" }, + { + "name": "git-commits", + "source": "./plugins/git-commits", + "description": "Structured commit workflow — small, logical commits that tell a coherent implementation story", + "version": "1.0.0" + }, { "name": "github", "source": "./plugins/github", @@ -70,7 +82,7 @@ "name": "microshift-release", "source": "./plugins/microshift-release", "description": "Set of tools to perform MicroShift Release Testing activities", - "version": "1.0.0" + "version": "1.1.0" }, { "name": "pr-review", @@ -78,6 +90,12 @@ "description": "PR lifecycle toolkit — vet findings, triage CodeRabbit reviews, filter noise, and autonomous yolo-agent for CI monitoring and auto-fixes", "version": "2.0.1" }, + { + "name": "skills-review", + "source": "./plugins/skills-review", + "description": "Lint SKILL.md files for quality, correctness, and adherence to skill guidelines", + "version": "1.0.0" + }, { "name": "threat-model", "source": "./plugins/threat-model", @@ -89,18 +107,6 @@ "source": "./plugins/two-node", "description": "Two-node topology (TNA/TNF) workflow automation — RHEL verification, Jira integration, and more", "version": "1.1.0" - }, - { - "name": "edge-ic", - "source": "./plugins/edge-ic", - "description": "Individual contributor workflow automation for TODO management, status reporting, and Jira updates", - "version": "1.2.0" - }, - { - "name": "skills-review", - "source": "./plugins/skills-review", - "description": "Lint SKILL.md files for quality, correctness, and adherence to skill guidelines", - "version": "1.0.0" } ] } diff --git a/plugins/git-commits/.claude-plugin/plugin.json b/plugins/git-commits/.claude-plugin/plugin.json new file mode 100644 index 00000000..cd599484 --- /dev/null +++ b/plugins/git-commits/.claude-plugin/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "git-commits", + "description": "Structured commit workflow — small, logical commits that tell a coherent implementation story", + "version": "1.0.0", + "author": { "name": "pmatuszak" }, + "homepage": "https://github.com/openshift-eng/edge-tooling", + "license": "Apache-2.0" +} diff --git a/plugins/git-commits/README.md b/plugins/git-commits/README.md new file mode 100644 index 00000000..672586e6 --- /dev/null +++ b/plugins/git-commits/README.md @@ -0,0 +1,45 @@ +# git-commits + +Structured commit workflow — teaches Claude to create small, logical git +commits that tell a coherent implementation story instead of committing +entire files at once. + +## Installation + +```text +/plugin marketplace add openshift-eng/edge-tooling +/plugin install git-commits +``` + +## Usage + +Invoke explicitly: + +```text +/small-commits +``` + +Or trigger automatically by mentioning: + +- "create small commits" +- "clean git history" +- "commit this in small logical pieces" +- "make good commits" + +## What It Does + +- Analyzes pending changes and groups them into logical commits +- Stages specific hunks (not whole files) when a file contains changes + for multiple logical commits, using the patch-file technique +- Uses `git commit --fixup=` when a change belongs to an earlier commit +- Offers to run `git rebase --autosquash` to fold fixups at the end +- Produces a git log that reads like a coherent implementation story + +## Requirements + +- Git repository with uncommitted changes +- Category: `util` + +## Author + +pmatuszak diff --git a/plugins/git-commits/skills/small-commits/SKILL.md b/plugins/git-commits/skills/small-commits/SKILL.md new file mode 100644 index 00000000..22099bae --- /dev/null +++ b/plugins/git-commits/skills/small-commits/SKILL.md @@ -0,0 +1,228 @@ +--- +name: small-commits +description: "Create small, well-structured git commits that tell a coherent implementation story. Use when the user says: small commits, clean commits, good git history, logical commits, commit in small pieces, split commits, atomic commits, granular commits, structured commits, commit story, clean history. Not for PR creation." +user-invocable: true +allowed-tools: Bash, Read, Write +--- + +# small-commits + +Structure uncommitted changes into small, logical git commits. Each +commit represents one coherent idea — a single function, a config +change, a test, a refactor step. The git log reads like a story of +how the implementation was built. + +## Prerequisites + +Run `git status` to confirm there are uncommitted changes. If the +current branch is `main` or `master`, warn the user and ask to confirm +before proceeding. + +## Steps + +### 1. Survey the Changes + +Run in parallel: + +```bash +git status +git diff --stat +git diff --cached --stat +git log --oneline -10 +``` + +Read the full diff to understand what changed: + +```bash +git diff +git diff --cached +``` + +For untracked files, read their contents with the Read tool. + +### 2. Plan the Commit Sequence + +Group changes into logical commits. Each commit must be: + +- **One idea**: a function, a fix, a config change, a test, a rename +- **Buildable**: the repo is not broken after this commit +- **Ordered**: dependencies come first (add utility before the code + that calls it) + +Present the plan to the user: + +```text +## Proposed Commit Plan + +1. Add helper function `parseConfig` in utils.go +2. Refactor `main()` to use `parseConfig` +3. Add unit tests for `parseConfig` +4. Update README with new config format +``` + +Wait for the user to confirm or adjust before proceeding. + +### 3. Stage and Commit Each Piece + +For each planned commit, stage ONLY the changes that belong to it. + +**Case A — Entire file belongs to this commit:** + +```bash +git add path/to/file.go path/to/other.go +``` + +**Case B — File has changes spanning multiple commits:** + +Use the patch-file technique to stage specific hunks: + +1. Generate the diff: + + ```bash + git diff path/to/file.go > /tmp/full.patch + ``` + +2. Read the patch. Identify hunk boundaries — lines starting with + `@@`. Each hunk header looks like: + `@@ -start,count +start,count @@ context` + +3. Write a partial patch containing ONLY the hunks for this commit. + The partial patch MUST include: + - The diff header lines (`diff --git a/... b/...`, `index ...`, + `--- a/...`, `+++ b/...`) + - Only the `@@` hunk(s) that belong to this commit + +4. Apply the partial patch to the index: + + ```bash + git apply --cached /tmp/partial.patch + ``` + +5. Verify what got staged: + + ```bash + git diff --cached path/to/file.go + ``` + +6. If the staged diff does not match expectations, unstage and retry: + + ```bash + git reset HEAD path/to/file.go + ``` + +**Case C — New untracked file:** + +```bash +git add path/to/new-file.go +``` + +**Committing:** + +After staging, create the commit. Follow the user's existing commit +message conventions. Check `git log --oneline -5` for style reference. + +Commit message rules: +- Subject line: imperative mood, max 72 chars, no trailing period +- Body (optional): explain WHY, not WHAT — the diff shows what + +### 4. Handle Fixups to Earlier Commits + +If while working through the plan you find a change that logically +belongs to an earlier commit on the branch, use fixup: + +1. Find the target commit: + + ```bash + git log --oneline -20 + ``` + +2. Create a fixup commit: + + ```bash + git add + git commit --fixup= + ``` + + This creates a NEW commit with the message `fixup! `. + It gets folded into the target during autosquash. + +### 5. Final Autosquash (optional) + +After all commits are made, if fixup commits exist on the branch, +offer to fold them: + +```text +There are N fixup commits. Run `git rebase --autosquash` to fold them +into their targets? +``` + +If the user confirms: + +```bash +GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash +``` + +Where `` is the earliest commit that should be included in +the rebase. Determine it from `git log --oneline` — look for the +oldest fixup target. `GIT_SEQUENCE_EDITOR=true` makes the interactive +rebase non-interactive by accepting the auto-generated sequence as-is. + +PR branches are personal and force-pushable — do not warn about +rewriting history on non-main branches. This follows the standard +rebase-and-force-push workflow used in Kubernetes and similar projects. + +### 6. Show the Result + +```bash +git log --oneline +``` + +## Gotchas + +- **Do not use `git add -i` or `git add -p`**: The interactive flag is + blocked. Always use the patch-file approach from Step 3 Case B. + +- **Do not use `git commit --amend`**: Use `git commit --fixup=` + instead. It creates a new commit that gets folded during autosquash. + +- **Partial patches must preserve the diff header**: When splitting a + diff, always include the full `diff --git a/... b/...`, `index ...`, + `--- a/...`, `+++ b/...` header block. Without it, `git apply` + rejects the patch. + +- **Already-staged changes**: Check `git diff --cached --stat` first. + If the user has already staged changes, incorporate them into the + commit plan. + +- **Binary files**: `git diff` does not produce patches for binary + files. Stage them with `git add ` — they cannot be split. + +- **Merge conflicts in rebase**: If autosquash hits a conflict, stop + and tell the user. Do not attempt automatic conflict resolution + during rebase. + +## Examples + +**User**: "I've made a bunch of changes, can you create small commits?" + +Runs `git diff --stat`, identifies 5 changed files spanning 3 logical +changes, presents a 3-commit plan, stages and commits each piece, +shows the final log. + +**User**: "Small commits please" (mid-conversation after making changes) + +Auto-invokes this skill, surveys changes, proposes a commit plan, asks +for confirmation, executes. + +**User**: `/small-commits` + +Explicit invocation — same workflow. + +## Notes + +- **Side effects**: Creates git commits on the current branch and + optionally rewrites local history via rebase. Confirms the commit + plan before executing and confirms before any rebase. +- **No push**: Never pushes to a remote. +- **PR branches are personal**: Rewriting history on non-main branches + is expected. Do not warn about force-push implications.