From 00a502a8add77c64f9af639e60832d79c75d85bb Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sun, 30 Nov 2025 08:40:41 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 13 ++ README.md | 3 + plugin.lock.json | 49 ++++++ skills/clean-gone-branches/SKILL.md | 106 +++++++++++++ skills/squash-commits/SKILL.md | 236 ++++++++++++++++++++++++++++ 5 files changed, 407 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 plugin.lock.json create mode 100644 skills/clean-gone-branches/SKILL.md create mode 100644 skills/squash-commits/SKILL.md diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..9e9dbc8 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,13 @@ +{ + "name": "git-workflow", + "description": " git workflow with simple commands for committing, squashing commits and creating merge / pull request", + "version": "1.0.0", + "author": { + "name": "Marc Weinberger", + "url": "https://github.com/mixomat" + }, + "skills": [ + "./skills/squash-commits", + "./skills/clean-gone-branches" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..816433b --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# git-workflow + + git workflow with simple commands for committing, squashing commits and creating merge / pull request diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..7e16eae --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,49 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:mixomat/claude-plugins:plugins/git-workflow", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "8f6562d6be69d9b3bc5b13496a799e6554e1dfb8", + "treeHash": "15ef0b31debcdbc864d4c72c1e595ee188b9ce2af37447ad7b05734e62378aa7", + "generatedAt": "2025-11-28T10:27:07.261560Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "git-workflow", + "description": " git workflow with simple commands for committing, squashing commits and creating merge / pull request", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "090a8f497f260bcd9c750df823fa1e984af71eef89f52fd4d19f68454ffca6df" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "983409ca675dc08f1723424931a6a86cfe3fb57354815b60ba99e907986ae7cc" + }, + { + "path": "skills/clean-gone-branches/SKILL.md", + "sha256": "c8c39cba40b4bbcef43cbb81059e682fcb2e7311e12fca54359e49d0e2b469c2" + }, + { + "path": "skills/squash-commits/SKILL.md", + "sha256": "1a50b1f85f3dc120113361fbe2286db8cc1bc8d19e0d8e97e6b2a37dabbb76c7" + } + ], + "dirSha256": "15ef0b31debcdbc864d4c72c1e595ee188b9ce2af37447ad7b05734e62378aa7" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/clean-gone-branches/SKILL.md b/skills/clean-gone-branches/SKILL.md new file mode 100644 index 0000000..1d446cf --- /dev/null +++ b/skills/clean-gone-branches/SKILL.md @@ -0,0 +1,106 @@ +--- +name: clean-gone-branches +description: Clean up local git branches marked as [gone] (deleted on remote but still exist locally). Use when the user wants to clean up stale branches, remove gone branches, or delete branches that no longer exist on remote. +allowed-tools: Bash +--- + +# Clean Gone Branches + +Automatically clean up all local git branches that have been deleted from the remote repository (marked as `[gone]`). + +## Instructions + +### Step 1 - List Branches to Identify [gone] Status + +Execute this command to see all local branches and their status: + +```bash +git branch -v +``` + +**What to look for:** +- Branches marked with `[gone]` have been deleted from the remote +- Branches with a `+` prefix have associated worktrees and will be skipped (must be cleaned up manually) +- Branches without a `+` prefix can be safely deleted +- If no branches show `[gone]`, inform the user that no cleanup is needed and STOP + +### Step 2 - Delete [gone] Branches (Skip Those with Worktrees) + +Execute this command to clean up [gone] branches without worktrees: + +```bash +git branch -v | grep '\[gone\]' | while read line; do + if [[ $line =~ ^[+] ]]; then + branch=$(echo "$line" | awk '{print $1}' | sed 's/^+//') + echo "Skipping $branch (has worktree - remove worktree first)" + else + branch=$(echo "$line" | sed 's/^[* ]//' | awk '{print $1}') + echo "Deleting branch: $branch" + git branch -D "$branch" + fi +done +``` + +**What this does:** +1. Finds all branches marked as `[gone]` +2. For each branch: + - If it has a `+` prefix (worktree exists), skip it and warn the user + - Otherwise, delete the branch using `-D` (force delete) +3. Provides clear feedback about which branches were deleted and which were skipped + +### Step 3 - Report Results + +After execution, inform the user: +- How many branches were deleted +- How many branches were skipped (with worktrees) +- If any branches were skipped, suggest they need manual worktree cleanup +- Confirmation that cleanup is complete + +If no branches were marked as `[gone]`, report that no cleanup was needed. + +## Important Rules + +- **DO NOT** attempt to delete branches with worktrees - skip them and warn the user +- Use `git branch -D` (force delete) because [gone] branches are already merged/deleted remotely +- Show clear feedback for each operation (deleted vs skipped) +- Inform users that skipped branches require manual worktree cleanup first + +## Expected Output + +**Example with branches to clean:** +``` +Deleting branch: fix/obsolete-fix +Skipping feature/old-feature (has worktree - remove worktree first) +Deleting branch: chore/cleanup-task + +Cleanup complete: +- Deleted 2 branches marked as [gone] +- Skipped 1 branch with worktree + +Note: Branches with worktrees must be cleaned up manually using 'git worktree remove' before the branch can be deleted. +``` + +**Example with no cleanup needed:** +``` +No branches marked as [gone] found. Your local repository is already clean. +``` + +**Example with only worktree branches:** +``` +Skipping feature/old-feature (has worktree - remove worktree first) +Skipping fix/another-branch (has worktree - remove worktree first) + +Cleanup complete: +- Deleted 0 branches marked as [gone] +- Skipped 2 branches with worktrees + +Note: Branches with worktrees must be cleaned up manually using 'git worktree remove' before the branch can be deleted. +``` + +## Error Handling + +If any command fails: +- Show the error message to the user +- Explain what went wrong +- Continue processing other branches if possible +- Report which branches were successfully cleaned and which failed diff --git a/skills/squash-commits/SKILL.md b/skills/squash-commits/SKILL.md new file mode 100644 index 0000000..f67a3cb --- /dev/null +++ b/skills/squash-commits/SKILL.md @@ -0,0 +1,236 @@ +--- +name: squash-commits +description: Squash all commits in a feature branch into a single commit with an AI-generated summary message. Use when the user wants to clean up their git history before merging, combine multiple commits, or create a single commit from a feature branch. +allowed-tools: Bash, AskUserQuestion +--- + +# Squash Git Commits + +Squash all commits in a feature branch into a single commit with a well-structured, AI-generated commit message. + +## Instructions + +### Step 1 - Safety Checks + +First, perform these safety checks: + +1. **Check for uncommitted changes:** + ```bash + git status + ``` + - If there are uncommitted changes, inform the user and STOP + - Suggest they commit or stash changes before proceeding + +2. **Get current branch name:** + ```bash + git branch --show-current + ``` + - Store this for later use + +3. **Create backup branch:** + ```bash + git branch backup/-$(date +%Y%m%d-%H%M%S) + ``` + - Inform the user that a backup branch has been created for safety + +### Step 2 - Detect Base Branch + +Auto-detect the base branch by checking which exists (in priority order): +1. `main` +2. `master` +3. `develop` + +Check each with: +```bash +git rev-parse --verify 2>/dev/null +``` + +If none exist, ask the user to specify the base branch. + +### Step 3 - Determine Commit Type from Branch Name + +Parse the current branch name to determine the commit type prefix: + +**Priority 1: JIRA Ticket Pattern** +- Pattern: `/` or `/-description` +- Examples: `feature/TVFUS-12345`, `fix/JIRA-999-bug-fix` +- Regex pattern: `^(feature|chore|fix)/([A-Z]+-\d+)` +- **Commit type:** Use the ticket number (e.g., `TVFUS-12345:`) + +**Priority 2: Branch Prefix Mapping** +- `feature/` → `feat:` +- `chore/` → `chore:` +- `fix/` → `fix:` + +**Fallback:** +- If no pattern matches, ask the user what commit type to use + +### Step 4 - Analyze Changes + +Gather comprehensive information about all changes: + +1. **Get commit history:** + ```bash + git log ..HEAD --oneline + git log ..HEAD --format="%B" + ``` + +2. **Get code changes:** + ```bash + git diff ...HEAD --stat + git diff ...HEAD + ``` + +3. **Analyze the changes:** + - Review both commit messages AND the actual code diff + - Identify **functional changes** (what the code does differently) + - Focus on: + - User-facing changes + - New features or capabilities + - Bug fixes and their impact + - Refactoring and improvements + - Configuration or dependency changes + - **DO NOT** just list commit messages - synthesize the actual functional impact + +### Step 5 - Generate Commit Message + +Create a commit message in this **exact format**: + +``` +: A brief summary line of the change + +- functional change 1 +- functional change 2 +- functional change 3 +``` + +**Guidelines:** + +- **First line (summary):** + - Concise summary (ideally under 72 characters) + - Captures the overall purpose of the changes + - Use imperative mood (e.g., "Add feature" not "Added feature") + +- **Blank line:** Required separator between summary and body + +- **Body (bullet points):** + - Each bullet describes ONE functional change + - Describe WHAT changed functionally, not implementation details + - Focus on user-visible or behavioral changes + - Be concise but descriptive + - Use imperative mood and present tense + +**Example:** +``` +feat: Add user profile management + +- Add user profile page with editable fields +- Implement avatar upload functionality +- Add email verification workflow +- Include profile deletion with confirmation dialog +``` + +**Example with JIRA ticket:** +``` +TVFUS-12345: Implement shopping cart feature + +- Add cart UI with item list and quantity controls +- Implement cart persistence across sessions +- Add checkout button with price calculation +- Include empty cart state with call-to-action +``` + +### Step 6 - Present for Approval by User + +Show the user: +- The generated commit message (in a code block for easy review) +- Number of commits that will be squashed +- The base branch being used +- Reminder that a backup branch was created + +Use the AskUserQuestion tool to present choices to proceed: + +Question: Proceed with this commit message? + +1. Yes +3. Edit the message? (if yes, ask for the edited version) +2. No, cancel + +**DO NOT** proceed without the confirmation by the user. + +### Step 7 - Execute Squash (Only After Approval by User) + +Once the user approves the commit message: + +1. **Perform the squash:** + ```bash + git reset --soft + git commit -m "" + ``` + + Note: Use a heredoc for multi-line messages: + ```bash + git commit -m "$(cat <<'EOF' + + EOF + )" + ``` + +2. **Verify success:** + ```bash + git log --oneline -5 + ``` + +3. **Inform the user:** + - Squash completed successfully + - Show the new commit hash and message + - Ask the user if the backup branch should be deleted now + +## Important Rules + +- **DO NOT** push to remote automatically - let the user decide +- **DO NOT** proceed if there are uncommitted changes +- **ALWAYS** create a backup branch before squashing +- **ALWAYS** wait for user approval before executing the squash +- **ALWAYS** use heredoc format for multi-line commit messages +- Focus on **functional changes** in the commit body, not implementation details + +## Error Handling + +If any command fails: +- Show the error message to the user +- Explain what went wrong in plain language +- Suggest recovery steps +- **DO NOT** proceed with the squash if there are errors +- Remind them that the backup branch exists if they need to recover + +## Examples + +### Example 1: Feature branch with JIRA ticket +``` +Branch: feature/TVFUS-12345-user-auth +Base: main +Commits: 8 + +Generated message: +TVFUS-12345: Add user authentication system + +- Add login and registration forms +- Implement JWT-based authentication +- Add password reset functionality +- Include session management with auto-refresh +``` + +### Example 2: Simple fix branch +``` +Branch: fix/navbar-mobile +Base: main +Commits: 3 + +Generated message: +fix: Resolve navigation menu issues on mobile + +- Fix hamburger menu not closing after selection +- Correct menu positioning on small screens +- Add smooth scroll behavior to anchor links +```