Skip to content

Skill to improve commit history and make PR reviews easier #158

Open
umair-ably wants to merge 1 commit intomainfrom
clean-commits-skill
Open

Skill to improve commit history and make PR reviews easier #158
umair-ably wants to merge 1 commit intomainfrom
clean-commits-skill

Conversation

@umair-ably
Copy link
Contributor

@umair-ably umair-ably commented Mar 9, 2026

New skill to help clean up commit history. Useful for those long back and forth agent assisted sessions

Summary by CodeRabbit

  • Documentation
    • Added clean-commits skill documentation defining a structured 5-phase workflow (Analyze, Plan, Execute, Verify, Push) for reorganizing feature branch commits into logical, clean history while preserving the final codebase state.

@vercel
Copy link

vercel bot commented Mar 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cli-web-cli Ready Ready Preview, Comment Mar 9, 2026 5:09pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

Walkthrough

A new documentation file introduces the clean-commits skill, which defines a five-phase workflow (Analyze, Plan, Execute, Verify, Push) for rewriting git history into clean, logical commits while preserving the final tree state.

Changes

Cohort / File(s) Summary
Clean-Commits Skill Documentation
.claude/skills/clean-commits/SKILL.md
New skill definition documenting a structured five-phase workflow for rewriting git history: Analyze (identify base and context), Plan (propose logical grouping), Execute (rebuild commits), Verify (ensure tree equivalence), and Push (force-push with approval). Includes rules for backup creation, approval gates, and enforced conventions.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A hop, skip, and commit so clean,
Five phases now, a workflow serene,
From messy to tidy, the history gleams,
With backups and checks, fulfilling our dreams! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: introducing a skill to improve commit history and make PR reviews easier, which aligns with the SKILL.md documentation that defines a clean-commits workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch clean-commits-skill

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.claude/skills/clean-commits/SKILL.md (1)

14-21: Consider parsing the JSON output or clarifying the intent.

Line 17 uses gh pr view --json baseRefName but doesn't show how to extract the value. If the intent is just to check whether a PR exists (using exit code), the comment could clarify that. Otherwise, consider showing the complete command to extract and use the base ref name.

💡 Example of parsing the JSON output
-   # Check if the branch tracks a remote with a PR target
-   gh pr view --json baseRefName 2>/dev/null
+   # Try to get the base branch from the PR
+   BASE_REF=$(gh pr view --json baseRefName -q .baseRefName 2>/dev/null)
+   BASE_COMMIT=$(git rev-parse "origin/$BASE_REF" 2>/dev/null)
    # Fall back to merge-base with main/master
-   git merge-base HEAD main 2>/dev/null || git merge-base HEAD master
+   [[ -z "$BASE_COMMIT" ]] && BASE_COMMIT=$(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/clean-commits/SKILL.md around lines 14 - 21, Clarify whether
the intent of the gh call is just to test for a PR (exit code) or to actually
obtain the base ref name; if you need the base ref use gh pr view --json
baseRefName and parse the JSON output (e.g., use gh's -q/JQ or jq to extract
.baseRefName) and assign that value for the subsequent merge-base logic,
otherwise update the comment to state that gh pr view --json baseRefName is used
only for its exit status and fall back to git merge-base HEAD main || git
merge-base HEAD master; reference the invocation gh pr view --json baseRefName
and the fallback git merge-base commands in the clarification.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/clean-commits/SKILL.md:
- Around line 142-152: Update the fenced code block that shows the backup branch
cleanup in "Phase 5: Push" so it includes the language specifier "bash"; locate
the block containing the literal line "git branch -d ${BRANCH}-backup  # when
you're happy with the result" and change the opening fence to specify bash
(e.g., ```bash) to satisfy MD040 and markdownlint-cli2.
- Around line 52-61: The fenced code block under the "**Present the plan to the
user as a table:**" section is missing a language tag causing MD040; update the
opening fence for the sample table to include a language specifier (for example
change "```" to "```text" or "```markdown") so the example table is properly
recognized by markdownlint and rendered correctly.

---

Nitpick comments:
In @.claude/skills/clean-commits/SKILL.md:
- Around line 14-21: Clarify whether the intent of the gh call is just to test
for a PR (exit code) or to actually obtain the base ref name; if you need the
base ref use gh pr view --json baseRefName and parse the JSON output (e.g., use
gh's -q/JQ or jq to extract .baseRefName) and assign that value for the
subsequent merge-base logic, otherwise update the comment to state that gh pr
view --json baseRefName is used only for its exit status and fall back to git
merge-base HEAD main || git merge-base HEAD master; reference the invocation gh
pr view --json baseRefName and the fallback git merge-base commands in the
clarification.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1263136d-3207-4c27-9a09-31b873b278a3

📥 Commits

Reviewing files that changed from the base of the PR and between 8333bed and e0293f8.

📒 Files selected for processing (1)
  • .claude/skills/clean-commits/SKILL.md

Comment on lines +52 to +61
**Present the plan to the user as a table:**
```
| # | Commit message | Files | Purpose |
|---|---------------|-------|---------|
| 1 | [PREFIX] Add X utility | 1 | Core utility function |
| 2 | [PREFIX] Add Y to base command | 3 | Framework methods |
| 3 | [PREFIX] Migrate commands to use X | ~80 | Mechanical — same pattern everywhere |
| ...
```

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to the fenced code block.

The code block showing the example table should specify a language (e.g., markdown or text) for proper rendering and to satisfy markdown linting rules.

📝 Proposed fix
 **Present the plan to the user as a table:**
-```
+```text
 | # | Commit message | Files | Purpose |

As per coding guidelines, static analysis tool markdownlint-cli2 reports: "Fenced code blocks should have a language specified (MD040)".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**Present the plan to the user as a table:**
```
| # | Commit message | Files | Purpose |
|---|---------------|-------|---------|
| 1 | [PREFIX] Add X utility | 1 | Core utility function |
| 2 | [PREFIX] Add Y to base command | 3 | Framework methods |
| 3 | [PREFIX] Migrate commands to use X | ~80 | Mechanical — same pattern everywhere |
| ...
```
**Present the plan to the user as a table:**
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 53-53: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/clean-commits/SKILL.md around lines 52 - 61, The fenced code
block under the "**Present the plan to the user as a table:**" section is
missing a language tag causing MD040; update the opening fence for the sample
table to include a language specifier (for example change "```" to "```text" or
"```markdown") so the example table is properly recognized by markdownlint and
rendered correctly.

Comment on lines +142 to +152
### Phase 5: Push

Ask the user if they want to force push. Only after explicit approval:
```bash
git push --force-with-lease origin "$BRANCH"
```

Remind the user the backup branch is available locally:
```
git branch -d ${BRANCH}-backup # when you're happy with the result
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to the fenced code block.

The code block showing the backup branch cleanup command should specify bash as the language for proper rendering and to satisfy markdown linting rules.

📝 Proposed fix
 Remind the user the backup branch is available locally:
-```
+```bash
 git branch -d ${BRANCH}-backup  # when you're happy with the result
</details>

As per coding guidelines, static analysis tool markdownlint-cli2 reports: "Fenced code blocks should have a language specified (MD040)".

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.21.0)</summary>

[warning] 150-150: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @.claude/skills/clean-commits/SKILL.md around lines 142 - 152, Update the
fenced code block that shows the backup branch cleanup in "Phase 5: Push" so it
includes the language specifier "bash"; locate the block containing the literal
line "git branch -d ${BRANCH}-backup # when you're happy with the result" and
change the opening fence to specify bash (e.g., ```bash) to satisfy MD040 and
markdownlint-cli2.


</details>

<!-- fingerprinting:phantom:triton:puma -->

<!-- This is an auto-generated comment by CodeRabbit -->

@paddybyers
Copy link
Member

Why is this in this repo?

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Claude “clean-commits” skill document to guide users through rewriting messy feature-branch history into a small set of logical, reviewer-friendly commits while preserving the final tree state.

Changes:

  • Introduces a 5-phase workflow (Analyze → Plan → Execute → Verify → Push) for commit history cleanup.
  • Documents safety practices (backup branch, user approval gates, diff verification, force-with-lease).
  • Provides command examples and a suggested commit-grouping rubric for reviewable history.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +25
# Check if the branch tracks a remote with a PR target
gh pr view --json baseRefName 2>/dev/null
# Fall back to merge-base with main/master
git merge-base HEAD main 2>/dev/null || git merge-base HEAD master
```
Only care about commits between the base and HEAD. Ignore commits that are already on the base branch.

2. **Read the history.** For each commit on this branch:
```bash
git log <base>..HEAD --reverse --format="%h %s" --stat
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “Detect the base” section runs gh pr view --json baseRefName but doesn’t show how to extract the branch name (or compute the merge-base from it). As written it just prints JSON and isn’t actionable for determining <base>. Consider using --jq to extract .baseRefName and then running git merge-base HEAD <baseRefName> (or document the exact next step).

Suggested change
# Check if the branch tracks a remote with a PR target
gh pr view --json baseRefName 2>/dev/null
# Fall back to merge-base with main/master
git merge-base HEAD main 2>/dev/null || git merge-base HEAD master
```
Only care about commits between the base and HEAD. Ignore commits that are already on the base branch.
2. **Read the history.** For each commit on this branch:
```bash
git log <base>..HEAD --reverse --format="%h %s" --stat
# Try to detect the PR's base branch (e.g., main) and compute the merge-base
BASE_BRANCH="$(gh pr view --json baseRefName --jq '.baseRefName' 2>/dev/null || echo '')"
if [ -n "$BASE_BRANCH" ]; then
BASE_COMMIT="$(git merge-base HEAD "$BASE_BRANCH")"
else
# Fall back to merge-base with main/master
BASE_COMMIT="$(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master)"
fi
echo "Using base commit: $BASE_COMMIT"

Only care about commits between the base and HEAD. Ignore commits that are already on the base branch.

  1. Read the history. For each commit on this branch:
    git log "$BASE_COMMIT"..HEAD --reverse --format="%h %s" --stat

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +43
| Priority | Category | Why separate |
|----------|----------|-------------|
| 1 | Infrastructure / utilities | Small, foundational — reviewer needs to understand these first |
| 2 | Base class / framework changes | The API that other code depends on |
| 3 | Mechanical migrations | Same pattern across many files — reviewer can skim. Note file count in the plan |
| 4 | Behavioral / logic changes | The interesting stuff — small diffs that deserve careful review |
| 5 | Test infrastructure + test updates | Tests grouped together, after the code they test |
| 6 | E2e / integration test fixes | Different environment, different review |
| 7 | Documentation | Docs last so reviewer sees the spec after the code |
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table under “Common groupings” uses || at the start of each row, which renders as an extra empty column (and may not render as a table in some Markdown parsers). Use standard Markdown table syntax with single leading pipes (or no leading pipe) so it renders consistently.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +105
git diff --name-only <base> <final> -- src/some/path/ | \
grep -v 'special-file' | \
while IFS= read -r f; do git checkout <final> -- "$f"; done
SCRIPT
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the checkout script example, placeholders switch between <base>/<final> and earlier variables like BASE_COMMIT / ORIGINAL_HEAD. This inconsistency makes the steps harder to follow and easier to copy/paste incorrectly. Consider using the same placeholder names throughout (or reference the variables already introduced).

Copilot uses AI. Check for mistakes.

1. **Diff check — this is non-negotiable.** The final tree MUST match the original:
```bash
git diff "$BRANCH" "${BRANCH}-backup" -- <relevant paths>
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phase 4 says the diff check is “non-negotiable” and that the final tree MUST match, but the suggested command scopes the diff to <relevant paths>, which could miss discrepancies elsewhere. To guarantee identical tree state, run an unscoped diff (or explicitly state that it must be run without a pathspec).

Suggested change
git diff "$BRANCH" "${BRANCH}-backup" -- <relevant paths>
git diff "$BRANCH" "${BRANCH}-backup"

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants