
Gitworkflow
- 2 installs
- 1 repo stars
- Updated July 30, 2026
- aojdevstudio/agentic-utilities
Gitworkflow is a Claude Code skill that automates Git Flow branching, commits, pull requests, CI monitoring, auto-merge, and issue routing.
About
Gitworkflow is a Claude Code skill that runs a full Git workflow: conventional commits, Git Flow branching, pull requests, CI monitoring with auto-merge, submodule handling, releases, and issue analysis/routing. A developer uses it to commit, open PRs, wait for CI, and merge without manual polling. It detects the repo shape (develop vs default branch) and adapts branch targeting and PR requirements accordingly.
- Repo-aware branch targeting with Git Flow (develop vs default branch)
- Creates a PR, polls CI checks, then auto-merges with squash when clear
- Routes and labels issues across worktrees plus submodule-aware commits
Gitworkflow by the numbers
- 2 all-time installs (skills.sh)
- Ranked #497 of 733 Git & Pull Requests skills by installs in the Skillselion catalog
- Data as of Jul 31, 2026 (Skillselion catalog sync)
gitworkflow capabilities & compatibility
- Capabilities
- gitworkflow · code review · ci cd
- Works with
- github
- Use cases
- ci cd · code review · project management
What gitworkflow says it does
Smart Git workflow engine with submodule detection, hook-aware commit strategies
Auto-merges with squash when all clear
npx skills add https://github.com/aojdevstudio/agentic-utilities --skill gitworkflowAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 1 |
| Last updated | July 30, 2026 |
| Repository | aojdevstudio/agentic-utilities ↗ |
What it does
Run a Git Flow workflow with CI monitoring, auto-merge, submodule handling, and issue routing across worktrees.
Who is it for?
Developers who want an agent to commit, open a PR, watch CI, and merge with repo-correct branch targeting.
Skip if: Repos where manual review gates must block automated merges.
When should I use this skill?
The user says commit, create branch, open PR, monitor CI, merge PR, create release, or analyze issues.
What you get
A committed, PR'd, CI-verified, and auto-merged change with repo-correct branch targeting.
- conventional commit
- feature branch
- pull request
By the numbers
- 8 workflows (Commit, Branch, Release, PullRequest, CIMerge, Submodule, IssueAnalysis, DeployWorkflow)
- waits 240s for automated reviews to settle
Files
GitWorkflow
Smart Git workflow engine with submodule detection, hook-aware commit strategies, repo-aware branch targeting, CI monitoring & auto-merge, issue analysis/routing, deploy-workflow isolation, and changelog awareness.
Changelog Tool (GATED)
Every commit and release workflow uses the changelog CLI tool (~/.local/bin/changelog) for repo awareness.
changelog --auto --dry-run # Preview unreleased changes (used after every commit)
changelog VERSION --auto # Generate CHANGELOG.md entry (used in releases)
changelog VERSION --auto --force # Non-interactive changelog generationSource: ~/Projects/desktop-commander/scripts/changelog/
This is mandatory — the user needs visibility into what's changing across repos. There is no skip flag. A gate with an escape hatch isn't a gate.
Repository Adaptation Rules
Before running Branch, PullRequest, CIMerge, or Release workflows, detect the repo shape:
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name' 2>/dev/null || git remote show origin | sed -n '/HEAD branch/s/.*: //p')
if git show-ref --verify --quiet refs/heads/develop || git ls-remote --exit-code --heads origin develop >/dev/null 2>&1; then
INTEGRATION_BRANCH=develop
else
INTEGRATION_BRANCH="$DEFAULT_BRANCH"
fiRules:
- If
developexists, use Git Flow normally. - If
developdoes not exist, treat the repodefaultBranchas the integration branch too. - Feature branches PR into
INTEGRATION_BRANCH. - Release and hotfix branches PR into
DEFAULT_BRANCH. - If the repo has
.github/PULL_REQUEST_TEMPLATE.md, use it as the starting shape for the PR body. - If the repo has an issue-link check or contributing docs that require issue closure keywords, the PR body must contain a real closing reference like
Closes #123,Fixes #123, orResolves #123, or explicitly markNo issue requiredwhen the repo allows that path. - Never leave placeholders like
Closes #,#ISSUE_NUM, or a bare#123in prose and assume GitHub will auto-close the issue.
This matters for repos like Keepfolio, which now fail PR checks unless the PR body contains a valid closing keyword or an explicit No issue required marker.
Workflow Routing
When executing a workflow, output this notification directly:
Running the **WorkflowName** workflow from the **GitWorkflow** skill...| Workflow | Trigger | File |
|---|---|---|
| Commit | "commit", "commit changes", "make a commit" | workflows/Commit.md |
| Branch | "create branch", "start feature", "finish branch" | workflows/Branch.md |
| Release | "create release", "bump version", "tag release" | workflows/Release.md |
| PullRequest | "create PR", "open pull request", "submit PR" | workflows/PullRequest.md |
| CIMerge | "merge PR", "check CI", "wait for checks", "is CI passing", "monitor CI", "auto-merge" | workflows/CIMerge.md |
| Submodule | "add submodule", "add repo as submodule", "submodule add/update/remove" | workflows/Submodule.md |
| IssueAnalysis | --issue-analysis, "analyze issues", "label issues", "route issues across worktrees", "plan the cut", "who should work on what" | workflows/IssueAnalysis.md |
| DeployWorkflow | "deploy workflow", "push workflow to main", "merge workflow only", "deploy gh action" | workflows/DeployWorkflow.md |
Examples
Example 1: Smart commit with submodule handling
User: "commit my changes"
→ Invokes Commit workflow
→ Detects dirty submodules, commits them first
→ Analyzes hooks to choose strategy (PARALLEL/COORDINATED/HYBRID)
→ Runs pre-commit validation
→ Generates conventional commit message with emoji
→ Executes commitExample 2: Create and manage a feature branch
User: "create a feature branch for user authentication"
→ Invokes Branch workflow
→ Detects repo default/integration branch
→ Creates feature/user-authentication branch from develop when present, otherwise from the repo default branch
→ Pushes to remote with trackingExample 3: Create PR, monitor CI, and auto-merge
User: "create a PR and merge it when CI passes"
→ Invokes PullRequest workflow
→ Detects target branch from repo shape + current branch type
→ Reads PR template / issue-link requirements when present
→ Creates PR with a valid closing keyword or marks no-issue-required when allowed
→ Continues to CIMerge workflow
→ Polls CI checks (GitHub Actions, CodeRabbit, GitGuardian, repo-specific metadata checks)
→ Waits 240s for automated reviews to settle (minimum 4 minutes)
→ Checks review decision (changes requested? approved? none?)
→ Auto-merges with squash when all clearExample 4: Create a release with version bump
User: "create a release for version 2.0.0"
→ Invokes Release workflow
→ Analyzes commits to confirm MAJOR bump is appropriate
→ Creates release/v2.0.0 branch from develop when present, otherwise from the default branch
→ Updates version files
→ Generates changelog from conventional commits
→ Pushes release branch for testingExample 5: Route issues across coding-agent worktrees toward a beta cut
User: "/git-workflow --issue-analysis --apply"
→ Invokes IssueAnalysis workflow
→ Detects worktrees (claude / codex / pi) and in-flight PRs
→ Asks for the cut sentence (north-star check)
→ Splits backlog into <cut>-blocker vs post-<cut>
→ Assigns issues to agents by warm context + file boundary
→ Creates labels: agent:<name>, <cut>-blocker, post-<cut>
→ Edits all open issues with appropriate labels
→ Prints routing table + ASCII route map + per-agent gh cheat-lineExample 6: Deploy a GitHub Actions workflow from a feature branch without merging the feature
User: "deploy this workflow to main, but don't merge my feature branch yet"
→ Invokes DeployWorkflow workflow
→ Stashes uncommitted changes on the current feature branch
→ Creates an isolated branch from origin/main
→ Cherry-picks or checks out only the workflow files
→ Commits, pushes, opens PR, merges with squash
→ Returns to the feature branch and restores the stash
→ Workflow is live on main; feature branch remains untouched---
Quick Reference: Commit Messages
Use Conventional Commits with emoji prefixes:
<emoji> <type>(<scope>): <description>
[optional body]
Co-Authored-By: AOJDevStudioCommon Types:
- ✨
feat- New feature - 🐛
fix- Bug fix - 📝
docs- Documentation - 💄
style- Formatting/style - ♻️
refactor- Code refactoring - ✅
test- Tests - 🔧
chore- Tooling, configuration
Reference: See ${PAI_DIR}/ai-docs/templates/emoji-commit-ref.yaml for 50+ emoji mappings
---
Quick Reference: Branch Commands
Detect Base Branches
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name' 2>/dev/null || git remote show origin | sed -n '/HEAD branch/s/.*: //p')
if git show-ref --verify --quiet refs/heads/develop || git ls-remote --exit-code --heads origin develop >/dev/null 2>&1; then
INTEGRATION_BRANCH=develop
else
INTEGRATION_BRANCH="$DEFAULT_BRANCH"
fiFeature Branch
# Start
git checkout "$INTEGRATION_BRANCH" && git pull origin "$INTEGRATION_BRANCH"
git checkout -b feature/descriptive-name
git push -u origin feature/descriptive-name
# Finish (preferred: open a PR into $INTEGRATION_BRANCH)Release Branch
# Start
git checkout "$INTEGRATION_BRANCH" && git checkout -b release/vX.Y.Z
git commit -am "🔖 release: bump version to X.Y.Z"
git push -u origin release/vX.Y.Z
# Finish (merge to default branch, then back-merge to develop only when develop exists)Hotfix Branch
# Start (from repo default branch)
git checkout "$DEFAULT_BRANCH" && git checkout -b hotfix/descriptive-name
git push -u origin hotfix/descriptive-name
# Finish (merge to default branch, then back-merge to develop only when develop exists)---
Commit Strategy Detection
The Commit workflow automatically detects the optimal strategy based on pre-commit hooks:
| Hook Configuration | Strategy | Behavior |
|---|---|---|
| No formatting hooks | PARALLEL | Stage multiple commits independently |
| Formatting hooks (non-aggressive) | COORDINATED | Stage and commit sequentially |
| Aggressive formatting (prettier --write) | HYBRID | Stage all, let hook format, single commit |
---
Gotchas
lefthook installin postinstall crashes on Vercel (not a git repo). Fix:"postinstall": "lefthook install || true".- Always check postinstall scripts before first Vercel deploy.
- Always verify
NEXT_PUBLIC_SITE_URLenv var is set to the production URL, not localhost, on first deploy. - Do not assume every repo has
develop. Detect it. - Do not assume every PR can omit issue metadata. Inspect
.github/and contributing docs first.
Reusable Workflow Templates
Ready-to-copy GitHub Actions workflows stored in templates/:
| Template | Purpose | Files |
|---|---|---|
| Issue Auto-Labeler | Deterministic keyword-based issue labeling, AI-swap-in ready | templates/issue-labeler.yml + templates/labeler-config.json |
Drop both files into a repo's .github/ directory, customize labeler-config.json to match the repo's labels, and the workflow is live on the next push to the default branch.
Supplementary Resources
Detailed workflows, conflict resolution, error handling: Read: AGENT.md
Comprehensive emoji commit reference: Read: ${PAI_DIR}/ai-docs/templates/emoji-commit-ref.yaml
Git Workflow - Comprehensive Guide
This document provides detailed methodology for Git Flow branch management, conventional commits with emojis, and pull request creation.
Quick Reference: See SKILL.md for command cheatsheet.
Repository Adaptation Overrides
These overrides take precedence over legacy Git Flow examples below:
- Detect the repo
defaultBranchbefore branching or opening a PR. - If
developexists, use it as the integration branch. - If
developdoes not exist, treat the repodefaultBranchas the integration branch too. - When a repo has
.github/PULL_REQUEST_TEMPLATE.mdor a PR metadata check, PR bodies must include a real closing keyword likeCloses #123/Fixes #123/Resolves #123, or the repo's exactNo issue requiredmarker when allowed. - Never leave placeholders like
Closes #,#ISSUE_NUM, or a bare issue number and expect auto-close behavior.
For current operational behavior, prefer the workflow files in workflows/ over older static examples in this guide.
---
Table of Contents
1. Git Flow Overview 2. Branch Lifecycle Management 3. Commit Message Standards 4. Release Management 5. Conflict Resolution 6. Error Handling 7. Pull Request Workflows 8. Best Practices
---
Git Flow Overview
Branch Hierarchy
Git Flow maintains a structured branching model with distinct purposes:
main (production)
├── hotfix/* → merges back to main AND develop
│
develop (integration)
├── feature/* → merges back to develop
├── release/* → merges to main AND developProtected Branches:
main: Production-ready code only. Never commit directly.develop: Integration branch for features. Never commit directly.
Working Branches:
feature/*: New functionality (short-lived)release/*: Release preparation (short-lived)hotfix/*: Emergency production fixes (very short-lived)
When to Use Each Branch Type
Feature Branch (feature/descriptive-name):
- Adding new functionality
- Non-urgent improvements
- Experimental work that can be tested in develop
- Lifespan: Days to weeks
Release Branch (release/vX.Y.Z):
- Preparing for production deployment
- Version bumping and final testing
- Release notes and documentation updates
- Lifespan: Hours to days
Hotfix Branch (hotfix/descriptive-name):
- Critical production bugs
- Security vulnerabilities
- Data corruption issues
- Lifespan: Minutes to hours
---
Branch Lifecycle Management
Feature Branch Complete Workflow
1. Starting a Feature
# Step 1: Ensure develop is up to date
git checkout develop
git pull origin develop
# Step 2: Create and switch to feature branch
git checkout -b feature/user-profile-page
# Step 3: Push to remote and set up tracking
git push -u origin feature/user-profile-pagePre-creation validation:
- Confirm you're on
developbefore branching - Check no uncommitted changes:
git status - Verify develop is current:
git log origin/develop..develop(should be empty)
2. Working on a Feature
# Regular work cycle
git add <files>
git commit -m "$(cat <<'EOF'
✨ feat(profile): add user avatar upload
Implemented image upload with validation and S3 storage.
Co-Authored-By: AOJDevStudio
EOF
)"
# Push changes regularly
git push origin feature/user-profile-pageDuring development:
- Commit frequently with meaningful messages
- Keep commits atomic (one logical change per commit)
- Sync with develop periodically if feature takes more than a few days:
git checkout develop && git pull origin develop
git checkout feature/user-profile-page
git merge develop3. Finishing a Feature
# Step 1: Final sync with develop
git checkout develop
git pull origin develop
# Step 2: Merge feature (no fast-forward to preserve history)
git merge --no-ff feature/user-profile-page
# Step 3: Push to develop
git push origin develop
# Step 4: Clean up branches
git branch -d feature/user-profile-page # Delete local
git push origin --delete feature/user-profile-page # Delete remotePre-merge validation:
- All tests passing
- Code reviewed (if team process requires)
- No merge conflicts with develop
- Feature is complete (no partial merges)
---
Release Branch Complete Workflow
1. Starting a Release
# Step 1: Create release branch from develop
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0
# Step 2: Update version numbers
# Edit package.json, version files, etc.
# Example for Node.js:
npm version 1.2.0 --no-git-tag-version
# Step 3: Commit version bump
git commit -am "🔖 release: bump version to 1.2.0"
# Step 4: Push release branch
git push -u origin release/v1.2.02. Release Preparation
On the release branch, only accept:
- Bug fixes (no new features!)
- Documentation updates
- Version number adjustments
- Build configuration tweaks
# Example release preparation commit
git commit -m "$(cat <<'EOF'
🐛 fix(build): correct production environment variables
Fixed missing API endpoint configuration for production.
Co-Authored-By: AOJDevStudio
EOF
)"3. Finishing a Release
# Step 1: Merge to main (production)
git checkout main
git pull origin main
git merge --no-ff release/v1.2.0
# Step 2: Tag the release
git tag -a v1.2.0 -m "Release v1.2.0"
# Step 3: Push main with tags
git push origin main --tags
# Step 4: Merge back to develop (to include any release fixes)
git checkout develop
git pull origin develop
git merge --no-ff release/v1.2.0
# Step 5: Push develop
git push origin develop
# Step 6: Clean up release branch
git branch -d release/v1.2.0
git push origin --delete release/v1.2.0Critical checks before finishing:
- All release tests passed
- Changelog updated
- Documentation reflects new version
- No pending commits on release branch
- Stakeholder approval obtained
---
Hotfix Branch Complete Workflow
1. Starting a Hotfix
# Step 1: Branch from main (NOT develop)
git checkout main
git pull origin main
git checkout -b hotfix/critical-auth-bug
# Step 2: Push to remote
git push -u origin hotfix/critical-auth-bugHotfix urgency indicators:
- 🚨 Site down / Service unavailable
- 🔐 Security vulnerability discovered
- 💥 Data corruption or loss
- ⚠️ Critical feature broken in production
2. Implementing the Fix
# Make minimal changes to fix the issue
git add <fixed-files>
git commit -m "$(cat <<'EOF'
🐛 fix(auth): prevent null pointer exception on logout
Added null check before accessing user session object.
Fixes production error affecting 15% of users.
Co-Authored-By: AOJDevStudio
EOF
)"Hotfix principles:
- Minimal scope (fix only the immediate issue)
- No refactoring or improvements
- Test thoroughly before merging
- Document the issue and fix
3. Finishing a Hotfix
# Step 1: Bump patch version
git checkout hotfix/critical-auth-bug
# Update version (e.g., 1.2.0 → 1.2.1)
npm version patch --no-git-tag-version
git commit -am "🔖 hotfix: bump version to 1.2.1"
# Step 2: Merge to main
git checkout main
git merge --no-ff hotfix/critical-auth-bug
# Step 3: Tag the hotfix
git tag -a v1.2.1 -m "Hotfix v1.2.1 - Critical auth bug fix"
# Step 4: Push main with tags
git push origin main --tags
# Step 5: Merge to develop
git checkout develop
git merge --no-ff hotfix/critical-auth-bug
# Step 6: Push develop
git push origin develop
# Step 7: Clean up
git branch -d hotfix/critical-auth-bug
git push origin --delete hotfix/critical-auth-bug---
Commit Message Standards
Conventional Commits with Emoji Format
Every commit must follow this structure:
<emoji> <type>(<scope>): <subject>
[optional body]
[optional footer]
Co-Authored-By: AOJDevStudioDetailed Breakdown
Emoji: Visual indicator of commit type (see emoji-commit-ref.yaml)
Type: Category of change
feat- New featurefix- Bug fixdocs- Documentation onlystyle- Code style (formatting, missing semicolons, etc.)refactor- Code change that neither fixes bug nor adds featureperf- Performance improvementtest- Adding or updating testschore- Tooling, dependencies, configci- CI/CD changesbuild- Build system changesrevert- Revert previous commit
Scope: Component affected (optional but recommended)
- Examples:
auth,api,ui,database,config - Use parentheses:
feat(auth)
Subject: Brief description
- Imperative mood: "add feature" not "added feature"
- No capitalization of first letter
- No period at the end
- Max 72 characters
Body: Detailed explanation (optional)
- Wrap at 72 characters
- Explain what and why, not how
- Separate from subject with blank line
Footer: Metadata (optional)
- Breaking changes:
BREAKING CHANGE: description - Issue references:
Fixes #123,Closes #456 - Co-authorship (required):
Co-Authored-By: AOJDevStudio
Examples of Good Commits
# Simple feature
✨ feat(profile): add avatar upload functionality
# Bug fix with details
🐛 fix(api): handle null response from external service
Added defensive null checks and fallback to cached data
when external API returns unexpected null values.
Fixes #234
Co-Authored-By: AOJDevStudio
# Breaking change
💥 feat(auth)!: migrate to JWT from session-based auth
BREAKING CHANGE: All existing sessions will be invalidated.
Users must log in again after deployment.
Migration guide: docs/AUTH_MIGRATION.md
Co-Authored-By: AOJDevStudio
# Documentation update
📝 docs(readme): add installation instructions for Windows
# Performance improvement
⚡ perf(database): add index on user_id column
Reduces query time from 2.3s to 45ms for user lookups.
Co-Authored-By: AOJDevStudioEmoji Reference
Always reference: ${PAI_DIR}/ai-docs/templates/emoji-commit-ref.yaml
Common emojis quick reference:
- ✨
:sparkles:- New feature - 🐛
:bug:- Bug fix - 🔒
:lock:- Security fix - 📝
:memo:- Documentation - 🚀
:rocket:- Performance - ♻️
:recycle:- Refactoring - ✅
:white_check_mark:- Tests - 🔧
:wrench:- Configuration - 💄
:lipstick:- UI/styling - 🔖
:bookmark:- Release/version tags
---
Release Management
Semantic Versioning
Format: vMAJOR.MINOR.PATCH (e.g., v1.2.3)
Version Bump Rules:
MAJOR (v1.0.0 → v2.0.0):
- Breaking API changes
- Incompatible changes to public interfaces
- Removal of deprecated features
- Major architectural changes
- Indicators in commits:
BREAKING CHANGE:in footer
MINOR (v1.0.0 → v1.1.0):
- New features (backwards compatible)
- New functionality added
- Deprecations (but not removals)
- Indicators in commits:
feat:type
PATCH (v1.0.0 → v1.0.1):
- Bug fixes
- Security patches
- Performance improvements
- Documentation updates
- Indicators in commits:
fix:,perf:,docs:
Automatic Version Detection
Analyze commits since last release to suggest version bump:
# Get commits since last tag
git log $(git describe --tags --abbrev=0)..HEAD --oneline
# Look for:
# - "BREAKING CHANGE:" → MAJOR bump required
# - "feat:" → MINOR bump required
# - "fix:" / "perf:" → PATCH bump sufficientChangelog Generation
Generate changelog from conventional commits:
# List all features since last release
git log $(git describe --tags --abbrev=0)..HEAD --grep="^✨ feat" --oneline
# List all fixes
git log $(git describe --tags --abbrev=0)..HEAD --grep="^🐛 fix" --oneline
# Format into CHANGELOG.md:
## [vX.Y.Z] - YYYY-MM-DD
### Added
- New feature 1 (#PR_NUM)
- New feature 2 (#PR_NUM)
### Fixed
- Bug fix 1 (#PR_NUM)
- Bug fix 2 (#PR_NUM)
### Changed
- Refactoring 1 (#PR_NUM)---
Conflict Resolution
Detecting Conflicts
# Conflicts appear during merge
git merge feature/user-profile
# Output: CONFLICT (content): Merge conflict in src/app.js
# Check status
git status
# Shows:
# Unmerged paths:
# both modified: src/app.jsUnderstanding Conflict Markers
// Example conflict in code
<<<<<<< HEAD (current branch - develop)
function login(username, password) {
return authenticateUser(username, password);
}
=======
function login(email, password) {
return authenticateWithEmail(email, password);
}
>>>>>>> feature/email-login (incoming branch)Markers explained:
<<<<<<< HEAD- Your current branch's version=======- Separator>>>>>>> branch-name- Incoming branch's version
Resolution Process
Step 1: Identify all conflicting files
git status | grep "both modified"Step 2: Open each file and resolve conflicts
Choose one of:
- Keep current version (remove incoming changes)
- Keep incoming version (remove current changes)
- Combine both versions
- Write entirely new code
Step 3: Remove conflict markers
Ensure no <<<<<<<, =======, or >>>>>>> remain in file.
Step 4: Test the resolution
# Run tests to verify resolution didn't break functionality
npm test # or your test commandStep 5: Mark as resolved
git add src/app.js # Add each resolved fileStep 6: Complete the merge
git commit # Opens editor with merge commit message
# Or specify message:
git commit -m "🔀 merge: resolve conflicts in feature/email-login"Complex Conflict Strategies
Multiple conflicting files:
# Resolve one at a time, testing after each
git add resolved-file-1.js
npm test
git add resolved-file-2.js
npm test
git commitAccept all from one side:
# Keep current branch (ours)
git checkout --ours conflicting-file.js
git add conflicting-file.js
# Keep incoming branch (theirs)
git checkout --theirs conflicting-file.js
git add conflicting-file.jsAbort merge if needed:
git merge --abort # Returns to pre-merge state---
Error Handling
Common Git Flow Errors
1. Direct Push to Protected Branch
Error:
! [remote rejected] main -> main (protected branch hook declined)Solution:
❌ You attempted to push directly to a protected branch.
✅ Correct workflow:
1. Create a feature branch:
git checkout -b feature/your-change
2. Make your changes and commit
3. Push feature branch:
git push -u origin feature/your-change
4. Create a pull request to merge into main/develop2. Merge Conflicts
Error:
CONFLICT (content): Merge conflict in src/app.js
Automatic merge failed; fix conflicts and then commit the result.Solution:
⚠️ Merge conflicts detected in:
- src/app.js
- src/utils/auth.js
🔧 Steps to resolve:
1. Open each conflicting file
2. Look for conflict markers (<<<<<<<, =======, >>>>>>>)
3. Edit to resolve conflicts
4. Remove conflict markers
5. Test your changes
6. Stage resolved files: git add <file>
7. Complete merge: git commit3. Invalid Branch Name
Error: User creates branch without proper Git Flow prefix.
Detection:
git branch | grep -v "feature\|release\|hotfix\|main\|develop"Solution:
❌ Invalid branch name: "my-feature"
✅ Use Git Flow naming conventions:
- feature/descriptive-name (for new features)
- release/vX.Y.Z (for releases)
- hotfix/descriptive-name (for urgent fixes)
To rename your branch:
git branch -m feature/my-feature
git push -u origin feature/my-feature4. Forgotten Remote Tracking
Error:
fatal: The current branch feature/login has no upstream branch.Solution:
⚠️ Your branch isn't tracking a remote branch.
✅ Set up tracking:
git push -u origin feature/login
This enables:
- git push (without specifying remote)
- git pull (without specifying remote)
- Branch status in git status5. Dirty Working Directory
Error: Attempting to switch branches with uncommitted changes.
Solution:
❌ Cannot switch branches with uncommitted changes.
Choose one:
1. Commit your changes:
git add .
git commit -m "✨ feat: work in progress"
2. Stash your changes (temporary storage):
git stash
# Switch branches, then restore:
git stash pop
3. Discard your changes (⚠️ DESTRUCTIVE):
git reset --hard HEAD---
Pull Request Workflows
Creating a Pull Request
Using GitHub CLI (`gh`):
# Ensure branch is pushed
git push origin feature/user-profile
# Create PR with full details
gh pr create --title "Add user profile page" --body "$(cat <<'EOF'
## Summary
- Created new user profile page with avatar upload
- Implemented profile editing functionality
- Added profile settings management
## Type of Change
- [x] Feature
- [ ] Bug Fix
- [ ] Hotfix
- [ ] Release
## Test Plan
1. Navigate to /profile
2. Upload new avatar image
3. Edit profile information
4. Verify changes persist after page reload
## Related Issues
Closes #123
## Checklist
- [x] Tests passing locally
- [x] No merge conflicts with develop
- [x] Documentation updated in README.md
- [ ] Code reviewed by team member
## Screenshots
(Add if UI changes)
Co-Authored-By: AOJDevStudio
EOF
)"PR Body Template Sections
Summary:
- Bullet points of key changes
- High-level overview of what PR accomplishes
Type of Change:
- Checkbox indicating PR category
- Helps reviewers understand scope
Test Plan:
- Step-by-step testing instructions
- Expected outcomes for each step
- Edge cases to verify
Related Issues:
- Links to GitHub issues using
Closes #NUMorFixes #NUM - Automatically closes issues when PR merges
Checklist:
- Pre-merge verification items
- Ensures nothing is forgotten
Screenshots/Videos: (if applicable)
- Visual changes require visual proof
- Before/after comparisons helpful
PR Labels and Reviewers
# Add labels
gh pr edit --add-label "feature,needs-review"
# Request reviewers
gh pr edit --add-reviewer username1,username2
# Assign to yourself
gh pr edit --add-assignee @mePR Merge Strategies
Squash and Merge (recommended for features):
- Combines all commits into one
- Keeps main/develop history clean
- Use when: Many small WIP commits in feature
Merge Commit (recommended for releases):
- Preserves complete history
- Shows all individual commits
- Use when: Commits are already well-organized
Rebase and Merge (use with caution):
- Replays commits on top of base branch
- Linear history
- Use when: Very experienced with git
---
Best Practices
DO ✅
Before Creating Branches:
- Always pull latest from base branch
- Verify you're on correct base branch
- Check for uncommitted changes
During Development:
- Commit frequently with meaningful messages
- Use emoji commits consistently
- Write descriptive commit bodies for complex changes
- Test before committing
Before Merging:
- Run full test suite
- Resolve all merge conflicts
- Review your own changes (self-review)
- Update documentation if needed
After Merging:
- Delete feature/release/hotfix branches
- Verify merge succeeded in target branch
- Monitor for issues in integration
General:
- Keep feature branches short-lived (days, not weeks)
- One logical change per commit
- Write commit messages for future developers
- Reference issue numbers in commits
DON'T ❌
Never:
- Commit directly to main or develop
- Force push to shared branches (
git push -f) - Rewrite history on public branches
- Merge without running tests
- Create ambiguous branch names
- Leave branches undeleted after merging
- Commit sensitive data (keys, passwords, tokens)
- Merge partial/incomplete features
Avoid:
- Large multi-purpose commits
- Vague commit messages ("fix stuff", "updates")
- Merging without reviewing changes
- Working on multiple unrelated features in one branch
- Long-lived feature branches (merge frequently)
Code Review Guidelines
As Author:
- Keep PRs small and focused
- Provide context in PR description
- Respond to feedback promptly
- Don't take criticism personally
- Update PR based on feedback
As Reviewer:
- Review promptly (within 24 hours)
- Be constructive and specific
- Ask questions to understand intent
- Approve when satisfied, not perfect
- Focus on logic, not style (use linters for style)
---
Troubleshooting
"I committed to the wrong branch"
# Option 1: Move commit to correct branch
git checkout correct-branch
git cherry-pick <commit-hash>
git checkout wrong-branch
git reset --hard HEAD~1
# Option 2: Create new branch from current commit
git branch feature/new-branch
git reset --hard HEAD~1
git checkout feature/new-branch"I need to undo my last commit"
# Keep changes, undo commit
git reset --soft HEAD~1
# Discard changes and commit
git reset --hard HEAD~1"I pushed but need to undo"
# Create revert commit (safe for shared branches)
git revert <commit-hash>
git push
# Force push (⚠️ ONLY if you're sole developer)
git reset --hard HEAD~1
git push --force"My branch is behind develop"
# Update your feature branch with latest develop
git checkout feature/your-branch
git fetch origin
git merge origin/develop
# Or use rebase (cleaner history, but more complex)
git rebase origin/develop---
Workflow Decision Tree
START: Need to make changes?
│
├─ Is it a production emergency? → YES → Create hotfix branch from main
│ │
│ NO
│ ↓
├─ Is it a new feature? → YES → Create feature branch from develop
│ │
│ NO
│ ↓
├─ Is it a release? → YES → Create release branch from develop
│ │
│ NO → You might be on the wrong workflow!
│
└─ Complete work → Run tests → Merge per Git Flow rules → Delete branch---
Additional Resources
External Documentation:
Internal References:
- Emoji commit reference:
${PAI_DIR}/ai-docs/templates/emoji-commit-ref.yaml - Quick command cheatsheet:
SKILL.md
---
Last Updated: 2025-01-05
# Issue Auto-Labeler
# Drop this into .github/workflows/ and create .github/labeler-config.json
# Triggers on issue open/edit. Deterministic keyword-based classification.
# Structured for future AI swap-in (see inline comments).
name: Issue Auto-Labeler
on:
issues:
types: [opened, edited]
permissions:
issues: write
contents: read
jobs:
# ═══════════════════════════════════════════════════════════════════════════════
# Job 1: Deterministic keyword-based classification
# ═══════════════════════════════════════════════════════════════════════════════
#
# To swap in AI classification later:
# 1. Add a new job (e.g., `ai-classify`) that runs in parallel.
# 2. That job calls an LLM API (OpenAI, Anthropic, etc.) with the issue
# title + body + the label taxonomy from labeler-config.json.
# 3. The LLM returns a JSON array of suggested labels.
# 4. In the `apply-labels` job below, merge `needs.keyword-labels.outputs.labels`
# with `needs.ai-classify.outputs.labels` before calling the GitHub API.
# 5. Add a `workflow_dispatch` input to toggle between keyword / AI / both.
#
keyword-labels:
runs-on: ubuntu-latest
outputs:
labels: ${{ steps.classify.outputs.labels }}
steps:
- uses: actions/checkout@v4
- name: Classify issue via keywords
id: classify
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const issue = context.payload.issue;
const text = `${issue.title}\n${issue.body || ''}`;
const config = JSON.parse(fs.readFileSync('.github/labeler-config.json', 'utf8'));
const settings = config.settings || {};
const wholeWord = settings.wholeWord ?? true;
const caseInsensitive = settings.caseInsensitive ?? true;
const maxLabels = settings.maxLabels ?? 3;
const scores = new Map();
for (const rule of config.labels) {
let score = 0;
for (const kw of rule.keywords) {
const escaped = kw.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const pattern = wholeWord ? `\\b${escaped}\\b` : escaped;
const flags = caseInsensitive ? 'gi' : 'g';
const matches = text.match(new RegExp(pattern, flags));
if (matches) score += matches.length;
}
if (score > 0) scores.set(rule.name, score);
}
const sorted = [...scores.entries()]
.sort((a, b) => b[1] - a[1])
.slice(0, maxLabels)
.map(([name]) => name);
console.log('Matched labels:', sorted);
core.setOutput('labels', JSON.stringify(sorted));
# ═══════════════════════════════════════════════════════════════════════════════
# Job 2: Apply labels to the issue
# ═══════════════════════════════════════════════════════════════════════════════
apply-labels:
runs-on: ubuntu-latest
needs: keyword-labels
if: needs.keyword-labels.outputs.labels != '[]'
steps:
- name: Add labels
uses: actions/github-script@v7
with:
script: |
const labels = JSON.parse('${{ needs.keyword-labels.outputs.labels }}');
if (labels.length === 0) return;
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels,
});
console.log(`Applied labels: ${labels.join(', ')}`);
{
"_comment": "Deterministic keyword rules for issue auto-labeling. Customize labels and keywords per repo. For AI swap-in later, an LLM job can read this same JSON as its taxonomy.",
"labels": [
{
"name": "bug",
"keywords": [
"bug",
"crash",
"error",
"fail",
"broken",
"not working",
"exception",
"stack trace",
"regression",
"fix"
]
},
{
"name": "enhancement",
"keywords": ["feature", "request", "add", "support", "implement", "would be nice", "improve", "upgrade"]
},
{
"name": "documentation",
"keywords": ["docs", "readme", "documentation", "guide", "tutorial", "wiki", "explain"]
},
{
"name": "security",
"keywords": ["security", "vulnerability", "auth", "xss", "injection", "exploit", "sanitize", "credential", "leak"]
},
{
"name": "performance",
"keywords": ["performance", "slow", "latency", "bottleneck", "optimize", "memory leak", "cache", "speed"]
},
{
"name": "infrastructure",
"keywords": ["ci", "cd", "build", "workflow", "action", "deploy", "terraform", "docker", "environment", "repo"]
},
{
"name": "dependencies",
"keywords": ["dependency", "dependencies", "bump", "update", "upgrade", "npm", "pip", "cargo", "gem", "outdated"]
},
{
"name": "tests",
"keywords": ["test", "testing", "spec", "coverage", "jest", "vitest", "pytest", "unit test", "e2e", "integration"]
}
],
"settings": {
"wholeWord": true,
"caseInsensitive": true,
"maxLabels": 3,
"excludedLabels": ["duplicate", "good first issue", "help wanted", "invalid", "wontfix", "question"]
}
}
Branch Workflow
Create and manage feature, release, and hotfix branches with repo-aware base branch detection.
Variables
BRANCH_TYPE: {{feature|release|hotfix}}
BRANCH_NAME: $ARGUMENTS
ACTION: {{start|finish}}
DEFAULT_BRANCH: detected from GitHub / origin HEAD
INTEGRATION_BRANCH: develop when present, otherwise DEFAULT_BRANCHDetect repo branches first:
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name' 2>/dev/null || git remote show origin | sed -n '/HEAD branch/s/.*: //p')
if git show-ref --verify --quiet refs/heads/develop || git ls-remote --exit-code --heads origin develop >/dev/null 2>&1; then
INTEGRATION_BRANCH=develop
else
INTEGRATION_BRANCH="$DEFAULT_BRANCH"
fiWorkflow
Start a Branch
Feature Branch (from INTEGRATION_BRANCH)
# Step 1: Ensure the integration branch is up to date
git checkout "$INTEGRATION_BRANCH"
git pull origin "$INTEGRATION_BRANCH"
# Step 2: Create and switch to feature branch
git checkout -b feature/BRANCH_NAME
# Step 3: Push to remote and set up tracking
git push -u origin feature/BRANCH_NAMEPre-creation validation:
- [ ] Check no uncommitted changes:
git status - [ ] Verify
INTEGRATION_BRANCHis current:git log origin/$INTEGRATION_BRANCH..$INTEGRATION_BRANCH(should be empty) - [ ] Confirm the repo uses
developbefore hard-codingdevelop
Release Branch (from INTEGRATION_BRANCH)
# Step 1: Create release branch from integration branch
git checkout "$INTEGRATION_BRANCH"
git pull origin "$INTEGRATION_BRANCH"
git checkout -b release/vX.Y.Z
# Step 2: Update version numbers
# Edit package.json, version files, etc.
# Step 3: Commit version bump
git commit -am "🔖 release: bump version to X.Y.Z"
# Step 4: Push release branch
git push -u origin release/vX.Y.ZHotfix Branch (from DEFAULT_BRANCH)
# Step 1: Branch from repo default branch
git checkout "$DEFAULT_BRANCH"
git pull origin "$DEFAULT_BRANCH"
git checkout -b hotfix/BRANCH_NAME
# Step 2: Push to remote
git push -u origin hotfix/BRANCH_NAMEHotfix urgency indicators:
- 🚨 Site down / Service unavailable
- 🔐 Security vulnerability discovered
- 💥 Data corruption or loss
- ⚠️ Critical feature broken in production
---
Finish a Branch
Finish Feature
Preferred path for shared repos:
1. Run the PullRequest workflow and target INTEGRATION_BRANCH. 2. After the PR merges, sync and clean up:
git checkout "$INTEGRATION_BRANCH"
git pull origin "$INTEGRATION_BRANCH"
git branch -d feature/BRANCH_NAME
git push origin --delete feature/BRANCH_NAMEOnly do a direct local merge when the user explicitly wants a non-PR flow and the target branch is not protected.
Finish Release
# Step 1: Merge to default branch
git checkout "$DEFAULT_BRANCH"
git pull origin "$DEFAULT_BRANCH"
git merge --no-ff release/vX.Y.Z
# Step 2: Tag the release
git tag -a vX.Y.Z -m "Release vX.Y.Z"
# Step 3: Push default branch with tags
git push origin "$DEFAULT_BRANCH" --tags
# Step 4: Back-merge to develop only when develop exists and differs from default
if [ "$INTEGRATION_BRANCH" != "$DEFAULT_BRANCH" ]; then
git checkout "$INTEGRATION_BRANCH"
git pull origin "$INTEGRATION_BRANCH"
git merge --no-ff release/vX.Y.Z
git push origin "$INTEGRATION_BRANCH"
fi
# Step 5: Clean up release branch
git branch -d release/vX.Y.Z
git push origin --delete release/vX.Y.ZFinish Hotfix
# Step 1: Bump patch version
git checkout hotfix/BRANCH_NAME
# Update version (e.g., 1.2.0 → 1.2.1)
git commit -am "🔖 hotfix: bump version to X.Y.Z"
# Step 2: Merge to default branch
git checkout "$DEFAULT_BRANCH"
git pull origin "$DEFAULT_BRANCH"
git merge --no-ff hotfix/BRANCH_NAME
# Step 3: Tag the hotfix
git tag -a vX.Y.Z -m "Hotfix vX.Y.Z - BRANCH_NAME"
# Step 4: Push default branch with tags
git push origin "$DEFAULT_BRANCH" --tags
# Step 5: Back-merge to develop only when develop exists and differs from default
if [ "$INTEGRATION_BRANCH" != "$DEFAULT_BRANCH" ]; then
git checkout "$INTEGRATION_BRANCH"
git pull origin "$INTEGRATION_BRANCH"
git merge --no-ff hotfix/BRANCH_NAME
git push origin "$INTEGRATION_BRANCH"
fi
# Step 6: Clean up
git branch -d hotfix/BRANCH_NAME
git push origin --delete hotfix/BRANCH_NAME---
Branch Validation Rules
Valid branch names:
- ✅
feature/user-authentication - ✅
release/v1.2.0 - ✅
hotfix/security-patch
Invalid branch names:
- ❌
my-new-feature(no prefix) - ❌
fix-bug(wrong prefix for this workflow)
Branch sources:
- Features → branch from
INTEGRATION_BRANCH - Releases → branch from
INTEGRATION_BRANCH - Hotfixes → branch from
DEFAULT_BRANCH
Merge targets:
- Features → PR to
INTEGRATION_BRANCH - Releases → merge/PR to
DEFAULT_BRANCH, then back-merge todeveloponly when it exists - Hotfixes → merge/PR to
DEFAULT_BRANCH, then back-merge todeveloponly when it exists
---
Pre-Merge Checklist
Before finishing any branch:
- [ ] No uncommitted changes
- [ ] Tests passing
- [ ] No merge conflicts
- [ ] Remote is up to date
- [ ] Correct target branch for this repo shape
- [ ] If using a PR workflow, issue-link / PR-template requirements are satisfied
CI Monitor & Auto-Merge Workflow
Monitor CI checks, wait for automated reviews to settle, repair PR metadata failures when possible, and merge PRs when all gates pass.
When to Use
- After creating a PR (automatically offered by the PullRequest workflow)
- When a user says "merge my PR", "check CI", "is CI passing", "wait for checks"
- When resuming a previously-created PR that was waiting on CI or review
- Any time a PR exists and needs to get from "open" to "merged"
Variables
PR_NUMBER: from PullRequest workflow output, or detected from current branch
BRANCH: current git branch or specified branch
MAX_CI_WAIT: 15 minutes (default)
MAX_FIX_ATTEMPTS: 3
SETTLE_WAIT: 240 seconds (for automated reviewers to post after checks pass; minimum 4 minutes)Workflow
Phase 1: Detect PR State
If PR_NUMBER is not provided, detect it:
BRANCH=$(git branch --show-current)
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number -q '.[0].number')If no PR found, stop: "No open PR found for branch $BRANCH. Create one first with /GitWorkflow PR."
Gather current state:
# CI status
gh pr checks "$PR_NUMBER"
# Review / metadata state
gh pr view "$PR_NUMBER" --json reviewDecision,body,baseRefName,url,closingIssuesReferences
# PR merge state
gh pr view "$PR_NUMBER" --json mergedAt -q '.mergedAt'Route based on state:
| State | Action |
|---|---|
| Already merged | Report "PR already merged." Stop. |
PR issue link or similar metadata check failed | Go to Phase 2D (repair PR metadata) |
| CI passing, review approved | Go to Phase 4 (merge) |
| CI passing, changes requested | Go to Phase 3 (address feedback) |
| CI passing, no review decision | Go to Phase 2B (review settlement) |
| CI pending/running | Go to Phase 2A (monitor CI) |
| CI failed | Go to Phase 2C (fix CI) |
---
Phase 2A: Monitor CI
CI takes time to queue after a push. Do not panic if the first poll returns empty.
sleep 15Poll every 30 seconds, up to MAX_CI_WAIT:
ELAPSED=0
while [ "$ELAPSED" -lt 900 ]; do
ACTIONS=$(gh run list --branch "$BRANCH" --limit 1 --json status,conclusion 2>/dev/null)
CHECKS=$(gh pr checks "$PR_NUMBER" 2>&1)
# Parse results: all pass, metadata failure, any fail, or still pending
# ...
sleep 30
ELAPSED=$((ELAPSED + 30))
doneImportant:
- Poll both
gh run listandgh pr checks. - Repo-specific checks may exist outside Actions runs.
- If a metadata check such as
PR issue linkfails, route to Phase 2D instead of treating it like a code/test failure.
If CI passes → proceed to Phase 2B. If CI fails → proceed to Phase 2C.
---
Phase 2B: Review Settlement
Automated reviewers (CodeRabbit, Codex, GitGuardian) analyze PRs asynchronously after CI passes.
Step 1 — Wait for all PR checks to complete:
SETTLE_ELAPSED=0
while [ "$SETTLE_ELAPSED" -lt 180 ]; do
PENDING=$(gh pr checks "$PR_NUMBER" --json state -q '[.[] | select(.state == "PENDING")] | length' 2>/dev/null)
[ "${PENDING:-0}" -eq 0 ] && break
sleep 30
SETTLE_ELAPSED=$((SETTLE_ELAPSED + 30))
doneStep 2 — Wait for automated reviews to post:
sleep 240Mandatory minimum: 240 seconds. Automated reviewers (Codex, CodeRabbit, GitGuardian) often post 60–180 seconds after checks complete. Merging before this window risks missing actionable feedback. The previous 90-second window was too short in practice.
Step 3 — Check for review feedback:
REVIEW_DECISION=$(gh pr view "$PR_NUMBER" --json reviewDecision -q '.reviewDecision')reviewDecision | Action |
|---|---|
CHANGES_REQUESTED | Go to Phase 3 |
APPROVED | Go to Phase 4 |
"" (empty) | Go to Phase 4 if all checks are green |
Also check for substantive review comments even without a formal decision:
gh pr view "$PR_NUMBER" --json reviews --jq '.reviews[] | select(.state == "COMMENTED" or .state == "CHANGES_REQUESTED") | {author: .author.login, state: .state}'If automated reviewers left actionable comments, address them before merging.
---
Phase 2C: Fix CI Failures
When CI fails, do not guess — read the actual logs.
RUN_ID=$(gh run list --branch "$BRANCH" --limit 1 --json databaseId,conclusion -q '.[] | select(.conclusion == "failure") | .databaseId')
gh run view "$RUN_ID" --log-failedAttempt to fix the issue. After fixing:
git add . && git commit -m "fix: address CI failure" && git pushReturn to Phase 2A to re-monitor. Maximum MAX_FIX_ATTEMPTS (3) before stopping with an error report.
---
Phase 2D: Repair PR Metadata Failures
Use this when a repo-specific PR check fails because the PR body is missing valid issue metadata.
Inspect the PR body and parsed closing links:
gh pr view "$PR_NUMBER" --json body,closingIssuesReferences,baseRefName,urlCommon failure mode:
- body contains
Closes #or#123in prose, - body uses the wrong template section,
- or the repo expects
- [x] No issue required ...and the box is still unchecked.
Repair path:
1. If the PR should close an issue, update the body with a real closing line such as Closes #123. 2. If the repo allows a no-issue path and this PR qualifies, check the exact template box text. 3. Edit the PR body in place:
gh pr edit "$PR_NUMBER" --body-file /tmp/pr-body.md4. Wait for the edited event to rerun checks, then return to Phase 2A.
Do not continue toward merge while the metadata check is failing.
If there is no issue number and the repo does not allow a no-issue path, stop and report that the PR cannot merge until the issue linkage problem is fixed.
---
Phase 3: Address Review Feedback
Read all review comments:
gh pr view "$PR_NUMBER" --json reviews --jq '.reviews[]'Address each piece of feedback. After pushing fixes, return to Phase 2A.
Maximum 5 review cycles before stopping.
---
Phase 4: Merge
All checks pass and no blocking reviews. Attempt merge:
Step 1 — Try direct merge:
gh pr merge "$PR_NUMBER" --squash --delete-branchIf exit code 0 → done. Report success.
Step 2 — If merge blocked (review required):
gh pr review "$PR_NUMBER" --approve --body "Self-approved: CI passing, all checks verified."
gh pr merge "$PR_NUMBER" --squash --delete-branchIf exit code 0 → done. Report success.
Step 3 — If self-approve fails (branch protection):
This is the legitimate pause point.
⏸️ PR #<NUMBER> requires external review approval.
CI is passing. All automated checks clear.
URL: <PR_URL>
Resume with: /GitWorkflow merge---
Report
## PR Merged ✅
**PR:** #PR_NUMBER
**Branch:** BRANCH
**Merge:** Squash merge
**CI:** All checks passing
**Reviews:** [summary of review state]
**URL:** <PR_URL>---
Error Handling
| Error | Action |
|---|---|
| No PR found for branch | Prompt user to create PR first |
| CI not detected after 5 minutes | Report and stop |
| PR metadata / issue-link check failing | Repair body or stop with exact missing requirement |
| CI fails 3 times | Report failure logs, stop |
| Review rejected 5 times | Report "fundamental disagreement", stop |
| Merge conflicts | Attempt rebase, or report and stop |
| Branch protection blocks merge | Report PR URL, suggest manual review |
---
Merge Strategy Selection
| Branch Type | Default Strategy | Rationale |
|---|---|---|
feature/* | --squash | Clean single commit on target branch |
release/* | --merge | Preserve release commit history |
hotfix/* | --squash | Minimal footprint for emergency fix |
Commit Workflow
Smart commit workflow with submodule awareness, hook-aware strategy detection, conventional commit messages, and auto-push to remote.
Default behavior: Commits are automatically pushed to the remote repository. Use --no-push flag to skip pushing.
Variables
COMMIT_OPTIONS: $ARGUMENTS
STRATEGY_MODE: auto-detected
NO_VERIFY: {{if contains COMMIT_OPTIONS "--no-verify"}}true{{else}}false{{endif}}
NO_SUBMODULES: {{if contains COMMIT_OPTIONS "--no-submodules"}}true{{else}}false{{endif}}
NO_PUSH: {{if contains COMMIT_OPTIONS "--no-push"}}true{{else}}false{{endif}}
CUSTOM_MESSAGE: {{extract message from COMMIT_OPTIONS}}Workflow
Phase 0: Submodule Detection & Processing
Skip if `NO_SUBMODULES` is true.
1. Check if .gitmodules file exists in the repository root 2. If submodules exist, run git submodule status to detect dirty submodules
- Look for
+prefix (submodule has new commits) orMin status - Also check
git status --porcelainformodified: <submodule> (modified content)
3. For each dirty submodule: a. Display: "📦 Found dirty submodule: <submodule-name> - processing first..." b. cd into the submodule directory c. Run git status --porcelain inside the submodule d. If uncommitted changes exist:
- Auto-stage with
git add . - Analyze changes for appropriate commit message
- Commit with conventional message + emoji
- Auto-push submodule to remote:
git push
e. Return to parent directory 4. After all submodules processed, continue with parent repo workflow
Submodule Status Indicators
| Indicator | Meaning | Action |
|---|---|---|
+abc123 | Submodule has new commits not in parent | Commit parent to update pointer |
abc123 | Submodule is clean | No action needed |
-abc123 | Submodule not initialized | Run git submodule update --init |
(modified content) | Uncommitted changes in submodule | Commit submodule first |
(untracked content) | Untracked files in submodule | Stage and commit submodule first |
---
Phase 1: Parent Repository Analysis
5. Run git status --porcelain to analyze current repository state 6. Execute formatting hook analysis to determine optimal commit strategy:
Hook-Aware Strategy Detection
Analyze pre-commit hooks to determine commit strategy:
# Check for formatting hooks
cat .git/hooks/pre-commit 2>/dev/null | grep -E "(prettier|eslint|black|rustfmt)" || echo "no-formatting-hooks"
# Check for husky/lint-staged
cat package.json 2>/dev/null | grep -E "(husky|lint-staged)" || echo "no-husky"Strategy Selection:
| Hook Configuration | Strategy | Behavior |
|---|---|---|
| No formatting hooks | PARALLEL | Can stage multiple commits independently |
| Formatting hooks (non-aggressive) | COORDINATED | Stage and commit sequentially |
| Aggressive formatting (prettier --write) | HYBRID | Stage all, let hook format, single commit |
7. Check for --no-verify flag in COMMIT_OPTIONS, skip pre-commit checks if present
---
Phase 2: Pre-commit Validation
Skip if `NO_VERIFY` is true.
8. Run pre-commit validation (if applicable to project type):
- Node.js:
pnpm lint(or npm/yarn) - Python:
ruff check .orblack --check . - Rust:
cargo clippy
9. Validate .gitignore configuration:
- Check for common sensitive files (.env, credentials, etc.)
- Alert if sensitive files are staged
10. Check for large files (>1MB):
git diff --cached --name-only | xargs -I{} du -h {} 2>/dev/null | awk '$1 ~ /M|G/ {print}'---
Phase 3: Staging & Commit
11. Auto-stage files with git add . if no files currently staged 12. Execute git diff --staged --name-status to analyze staged changes 13. Analyze changes for atomic commit splitting opportunities:
- Group by feature/component
- Separate docs from code
- Separate tests from implementation
14. Generate conventional commit message:
Commit Message Format
<emoji> <type>(<scope>): <description>
[optional body - what and why]
Co-Authored-By: AOJDevStudioType Selection:
- Analyze changed files to determine type
- Use emoji reference from
${PAI_DIR}/ai-docs/templates/emoji-commit-ref.yaml
| Changed Files | Type | Emoji |
|---|---|---|
| New feature files | feat | ✨ |
| Bug fixes | fix | 🐛 |
| Documentation only | docs | 📝 |
| Test files only | test | ✅ |
| Config/tooling | chore | 🔧 |
| Refactoring | refactor | ♻️ |
| Performance | perf | ⚡ |
| Style/formatting | style | 💄 |
15. Execute commit:
git commit {{if NO_VERIFY}}--no-verify{{endif}} -m "$(cat <<'EOF'
<emoji> <type>(<scope>): <description>
<body if complex changes>
Co-Authored-By: AOJDevStudio
EOF
)"16. If CUSTOM_MESSAGE provided, use it instead of auto-generated:
git commit {{if NO_VERIFY}}--no-verify{{endif}} -m "CUSTOM_MESSAGE"17. Display commit summary:
git log --oneline -1
git diff --stat HEAD~1---
Phase 4: Auto-Push to Remote
Skip if `NO_PUSH` is true.
18. Check if remote tracking branch exists:
git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null19. If tracking branch exists, auto-push:
git push20. If no tracking branch, set upstream and push:
git push -u origin $(git rev-parse --abbrev-ref HEAD)21. Display push confirmation:
echo "✅ Pushed to remote: $(git rev-parse --abbrev-ref --symbolic-full-name @{u})"Default behavior: Push is ALWAYS performed automatically unless --no-push flag is provided. The workflow completes the full commit→push cycle without user confirmation.
---
Phase 5: Changelog Summary (GATED)
⚠️ This phase ALWAYS runs. There is no flag to skip it. Changelog awareness is non-negotiable.
22. Run changelog dry-run to show accumulated unreleased changes:
changelog --auto --dry-run 2>&123. If the command succeeds, display the output:
📋 Unreleased Changes (since last tag)
─────────────────────────────────────
[dry-run output]
💡 To update CHANGELOG.md: changelog <version> --auto
💡 To create a release: use /GitWorkflow release24. If no tags exist in the repo:
📋 No tags found — changelog will cover all commits.
💡 Create your first release: changelog 0.1.0 --auto25. If changelog command is not found:
⚠️ Changelog CLI not found at ~/.local/bin/changelogContinue (non-blocking).
Why this is gated: Without changelog awareness, you lose track of what's accumulating between releases. This summary costs ~1 second and provides critical repo context.
---
Flags
| Flag | Description |
|---|---|
--no-verify | Skip pre-commit hooks and validation |
--no-submodules | Skip submodule processing |
--no-push | Skip auto-push (commit only, do not push to remote) |
--message "..." or -m "..." | Use custom commit message |
---
Report
## Commit Complete
**Strategy:** STRATEGY_MODE (auto-detected)
**Submodules:** X submodules processed
**Files:** Y files committed
**Pushed:** ✅ origin/BRANCH_NAME (or ⏸️ Skipped with --no-push)
**Changelog:** 📋 Unreleased changes shown
**Commit:**
<git log --oneline -1>
**Stats:**
<git diff --stat HEAD~1>
**Remote:**
<git rev-parse --abbrev-ref --symbolic-full-name @{u}>---
Error Handling
| Error | Action |
|---|---|
| No staged changes | Auto-stage modified files, or warn if working tree clean |
| Pre-commit hook fails | Show error, abort commit (unless --no-verify) |
| Submodule push fails | Warn user, continue with parent commit |
| Large file detected | Warn user, suggest adding to .gitignore |
| Sensitive file staged | Block commit, show warning |
| Changelog tool not found | Warn user, continue (non-blocking) |
| Changelog dry-run fails | Warn user, continue (non-blocking) |
Deploy GitHub Actions Workflow
Deploy a .github/workflows/ file (or related config) to the default branch from an isolated branch, without merging an unrelated feature branch.
When to Use
- The user is on a feature branch with unrelated work and wants a workflow live on
mainnow - A workflow needs to be merged before the feature branch it was created on is ready
- Any situation where GitHub Actions files must land on the default branch independently
Variables
WORKFLOW_FILES: # space-separated paths under .github/ (e.g., ".github/workflows/foo.yml .github/labeler-config.json")
SOURCE_COMMIT: # commit hash on the current branch that contains the workflow files (optional)
ISOLATED_BRANCH: # name for the new branch (e.g., "feat/deploy-issue-labeler")Workflow
Phase 1: Prepare
Save the user's current branch and working state, then create a clean isolated branch from origin/defaultBranch:
ORIGINAL_BRANCH=$(git branch --show-current)
# Stash any uncommitted changes so we can switch branches safely
git stash push -m "wip: deploy-workflow stash"
# Create isolated branch from the latest remote default branch
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name' 2>/dev/null || git remote show origin | sed -n '/HEAD branch/s/.*: //p')
git fetch origin "$DEFAULT_BRANCH"
git checkout -b "$ISOLATED_BRANCH" "origin/$DEFAULT_BRANCH"Phase 2: Extract Workflow Files
Option A — Cherry-pick from existing commit
If the workflow files already exist in a commit on the feature branch:
git cherry-pick "$SOURCE_COMMIT" --no-commitOption B — Copy from working tree
If the files are in the working tree but not yet committed:
# Copy each file from the stashed/original working tree
git checkout "$ORIGINAL_BRANCH" -- $WORKFLOW_FILESPhase 3: Clean
Remove any unrelated files that came along (e.g., from a messy cherry-pick or branch state):
# Unstage anything not in WORKFLOW_FILES
git reset HEAD
# Re-stage only the workflow files
git add $WORKFLOW_FILES
# Discard everything else
git checkout -- .
git clean -fdVerify the commit contains only workflow files:
git diff --cached --name-onlyPhase 4: Commit and Push
git commit -m "feat(ci): deploy WORKFLOW_NAME
- Deployed from isolated branch to avoid merging unrelated feature work"
git push -u origin "$ISOLATED_BRANCH"Phase 5: Merge to Default Branch
Open a PR and wait for automated review feedback before merging. Even config-only changes can receive actionable review comments (e.g., stale label handling, YAML syntax, permission scopes).
gh pr create \
--base "$DEFAULT_BRANCH" \
--head "$ISOLATED_BRANCH" \
--title "feat(ci): deploy WORKFLOW_NAME" \
--body "Isolated deployment of GitHub Actions workflow."
PR_NUMBER=$(gh pr list --head "$ISOLATED_BRANCH" --json number -q '.[0].number')Wait for reviews:
sleep 240Mandatory minimum: 240 seconds. Automated reviewers (Codex, CodeRabbit, GitGuardian) often post 60–180 seconds after the PR is opened.
Check for review feedback before merging:
REVIEW_DECISION=$(gh pr view "$PR_NUMBER" --json reviewDecision -q '.reviewDecision')
COMMENTS=$(gh pr view "$PR_NUMBER" --json reviews --jq '.reviews[] | select(.state == "COMMENTED" or .state == "CHANGES_REQUESTED") | {author: .author.login, state: .state}')
echo "Review decision: $REVIEW_DECISION"
echo "Comments: $COMMENTS"If CHANGES_REQUESTED or substantive COMMENTED reviews exist, address them before merging. Otherwise:
gh pr merge "$PR_NUMBER" --squash --delete-branchPhase 6: Restore User State
Return to the original branch and restore working tree:
git checkout "$ORIGINAL_BRANCH"
git stash pop---
Validation Rules
- [ ] Only files under
.github/are in the final commit - [ ] The isolated branch is based on
origin/$DEFAULT_BRANCH, not the feature branch - [ ] Uncommitted changes on the original branch are preserved via stash
- [ ] The workflow file syntax is valid (optional: run
actionlintif available)
Error Handling
| Error | Action |
|---|---|
| Cherry-pick includes unrelated files | Reset, then git checkout ORIGINAL_BRANCH -- $WORKFLOW_FILES |
| Stash pop conflicts | Resolve manually; the stash remains available as stash@{0} |
| PR merge blocked by branch protection | Report PR URL and stop; user must merge manually |
| Workflow file has YAML syntax errors | Run actionlint or push a fix commit to the isolated branch |
IssueAnalysis Workflow
Pulls every open issue, identifies in-flight claims across worktrees, splits the backlog around a release cut (beta/mvp/v1/sprint-N), assigns issues to coding-agent worktrees, and applies a 5-label routing scheme so each agent can ask gh issue list --label "agent:<self>" and only see its lane.
Default behavior: Dry-run — emits the table and label plan but does not write. Pass --apply to actually create labels and edit issues.
Variables
ANALYSIS_OPTIONS: $ARGUMENTS
CUT_NAME: {{extract --cut from OPTIONS, default: "beta"}}
AGENTS: {{extract --agents=a,b,c from OPTIONS, default: detect from `git worktree list`}}
REPO: {{extract --repo from OPTIONS, default: derive from `git remote -v`}}
APPLY: {{if contains OPTIONS "--apply"}}true{{else}}false{{endif}}
SKIP_PROMPT: {{if contains OPTIONS "--yes"}}true{{else}}false{{endif}}Workflow
Phase 0: Discovery
Run in parallel — these are read-only:
1. git worktree list → enumerate sibling worktrees, infer agent names from path suffix (<repo>-claude → claude, <repo>-codex → codex, etc.). If only one worktree exists, ask the user for the agent list. 2. git branch --sort=-committerdate | head -20 → recently active branches across worktrees. 3. gh pr list --state open --json number,title,headRefName,author,createdAt → in-flight PRs. 4. gh issue list --state open --limit 100 --json number,title,labels,assignees,milestone,updatedAt → full open backlog. 5. For any issue without a clear claim, fetch its last comment to detect manual claims (gh issue view N --json comments,assignees).
Cross-reference results: every open PR + active non-main branch is a claim signal that ties an in-flight issue to a worktree. Record these as locked claims; the rest of the backlog is unclaimed.
Phase 1: Cut definition
Print the open backlog grouped by label. Ask the user (skip if --yes):
What defines <CUT_NAME> for this repo? Paste a 1-sentence north-star check.Example: "Beta = I open the app, the briefing tells me what changed, and the numbers are correct."
Use the answer as the cut filter. Walk each open issue and decide cut-blocker vs deferred based on whether resolving it is a precondition for the cut sentence to be true.
If the user provides no sentence, fall back to: anything labeled `bug` or on the critical path of an existing milestone is cut-blocker; everything else is deferred.
Phase 2: Categorize
Build the routing table with these columns:
| Column | Source |
|---|---|
| Issue # | gh issue list |
| Title (≤40 chars) | truncated |
| Agent | from claim signal OR file-boundary heuristic (next phase) |
| Round | 1 = in flight, 2 = ready next, 3 = soak-only |
| Label set | computed |
Phase 3: Assign unclaimed issues to agents
For each unclaimed cut-blocker, propose an agent based on:
1. Warm context — if an agent recently touched files in the same directory (last 10 commits on its branch), assign there. 2. File boundary disjointness — if two issues touch overlapping paths, do not put them in the same round across agents (would conflict at merge). 3. Triage history — if an issue already has a TDD plan written by a specific agent, that agent inherits it. 4. Load balancing — split remaining issues evenly across agents per round.
Surface the heuristic that drove each assignment in a (why) column when the choice isn't obvious.
Phase 4: Round ordering
- Round 1: in-flight PRs + their issues. No new work assigned to an agent until its R1 lands.
- Round 2: cut-blocker queue, one issue per agent, picked so file boundaries stay disjoint with R1.
- Round 3: bug-fix soak only. Once
<CUT_NAME>-blockerreturns 0 open, ship the cut tag.
Phase 5: Output
Print three blocks in order:
1. Routing table — issue → agent → round → labels (markdown table) 2. Route map — ASCII Gantt-style:
┌─ R1 ────────┐ ┌─ R2 ──────┐ ┌─ R3 ─────────┐
<a1> →│ <PR/issues>│ → │ <issue> │ → │ bug-fix only │
<a2> →│ <PR/issues>│ → │ <issue> │ → │ bug-fix only │ → CUT TAG
<a3> →│ <PR/issues>│ → │ <issue> │ → │ bug-fix only │
└────────────┘ └───────────┘ └──────────────┘3. Per-agent cheat-line, e.g.:
gh issue list --repo <REPO> --label "agent:claude,<CUT_NAME>-blocker" --state openPhase 6: Apply (only if APPLY=true)
1. Create the 5 labels (idempotent — gh label create errors if a label exists; ignore the error):
agent:<name>for each agent (cyan/orange/purple/green rotation)<CUT_NAME>-blocker(redDC2626)post-<CUT_NAME>(gray6B7280)
2. Apply labels to issues. Run as separate `gh issue edit` calls — do NOT pipe through a multi-line shell loop, because some PreToolUse safety hooks reject heredoc-style scripts. One call per issue keeps the audit trail clean.
3. Verify: print gh issue list --label "<CUT_NAME>-blocker" --state open --json number,title --jq length and confirm the count matches the table.
If APPLY=false, print the exact gh label create and gh issue edit commands the user would need to run, so they can paste-and-go.
Examples
Example 1: Default (dry-run, beta cut, auto-detect agents)
User: "/git-workflow --issue-analysis"
→ Detects worktrees: claude, codex, pi
→ Pulls 24 open issues, 2 open PRs
→ Asks for cut sentence; user answers
→ Prints routing table + route map + cheat-lines
→ Stops (no labels written)Example 2: Apply with custom cut name
User: "/git-workflow --issue-analysis --cut mvp --apply"
→ Creates labels: agent:claude, agent:codex, agent:pi, mvp-blocker, post-mvp
→ Edits 24 issues with appropriate labels
→ Verifies counts and prints final tableExample 3: Single-agent repo
User: "analyze the issues for this repo"
→ Only one worktree found, so prompts: "List your agents (comma-separated):"
→ User: "human"
→ Skips agent: labels (only one assignee), still creates cut-blocker / post-cut splitWhen to invoke this workflow
- User says: "analyze the issues", "route issues across worktrees", "label issues for the beta cut", "plan the cut", "who should work on what", "what's left for beta/mvp/v1".
- User passes flag:
--issue-analysisto GitWorkflow. - A new chunk of issues just landed (e.g. after
/to-issues) and the user wants them slotted into the existing cut plan — re-run with--applyto fill in only the new issues.
Gotchas
- Multi-line shell scripts can trip safety hooks. Apply labels with one
gh issue editper call. Do not chain with&+waitinside a heredoc. - `gh label create` is not idempotent. It errors on duplicate names. Wrap with
|| trueor check existing labels first viagh label list --json name --jq '.[].name'. - Worktree path → agent name assumes the convention
<repo>-<agent>. If a worktree path doesn't match, fall back to asking the user. - In-flight PR ≠ owned issues automatically. A single PR can bundle multiple issues. Read the PR body for
Closes #N/Fixes #Nreferences and tie those issues to the PR's worktree. - Cut name is parameterized; default is `beta`. Don't hard-code "beta" anywhere — use the
<CUT_NAME>template variable so the same workflow ships mvp / v1 / sprint-3 cuts unchanged. - Color rotation for >4 agents. Default palette covers 4: cyan
0EA5E9, orangeF97316, purpleA855F7, green10B981. Beyond that, the workflow asks the user for colors.
Pull Request Workflow
Create and manage pull requests with GitHub CLI, repo-aware target branch detection, and PR-template / issue-link compliance.
Variables
PR_TITLE: $ARGUMENTS or auto-generated
CURRENT_BRANCH: $(git branch --show-current)
DEFAULT_BRANCH: detected from GitHub / origin HEAD
INTEGRATION_BRANCH: develop when present, otherwise DEFAULT_BRANCH
TARGET_BRANCH: derived from branch type + repo shape
ISSUE_LINK: actual closing keyword line (e.g. Closes #123) or explicit no-issue-required markerWorkflow
1. Pre-PR Checks
CURRENT_BRANCH=$(git branch --show-current)
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name' 2>/dev/null || git remote show origin | sed -n '/HEAD branch/s/.*: //p')
if git show-ref --verify --quiet refs/heads/develop || git ls-remote --exit-code --heads origin develop >/dev/null 2>&1; then
INTEGRATION_BRANCH=develop
else
INTEGRATION_BRANCH="$DEFAULT_BRANCH"
fi
case "$CURRENT_BRANCH" in
feature/*) TARGET_BRANCH="$INTEGRATION_BRANCH" ;;
release/*|hotfix/*) TARGET_BRANCH="$DEFAULT_BRANCH" ;;
*) TARGET_BRANCH="$DEFAULT_BRANCH" ;;
esac
# Ensure branch is pushed
git push -u origin "$CURRENT_BRANCH"
# Check for unpushed commits
git log "origin/$CURRENT_BRANCH"..HEAD --oneline
# Check for merge conflicts with target
git fetch origin
git merge-base --is-ancestor "origin/$TARGET_BRANCH" HEAD || echo "May have conflicts"Stop if:
- the working tree is dirty in a way that would make the PR misleading,
- the branch obviously targets the wrong base branch,
- or the repo requires issue linkage and no valid issue path exists yet.
---
2. Detect Repo PR Requirements
Inspect the repo before generating the PR body:
TEMPLATE_FILE=""
for f in .github/PULL_REQUEST_TEMPLATE.md .github/pull_request_template.md; do
[ -f "$f" ] && TEMPLATE_FILE="$f" && break
done
rg -n "Closes #|Fixes #|Resolves #|No issue required|closing keyword|auto-close|issue link" \
.github CONTRIBUTING.md docs/CONTRIBUTING.md 2>/dev/null || trueRules:
- If
TEMPLATE_FILEexists, mirror its sections and wording. - If the repo has a metadata check like Keepfolio's
PR issue link, the PR body must contain either: - a real closing keyword:
Closes #123,Fixes #123, orResolves #123, or - an explicit no-issue marker exactly matching the repo template, such as
- [x] No issue required .... - Never leave placeholders like
Closes #,#ISSUE_NUM, orCloses #123 (if applicable)without replacing them.
---
3. Determine the Issue Link Strategy
Every PR must resolve "what GH issue does this address?" before creation. Work through this order and stop at the first hit — don't skip to "ask the user" without trying detection first.
Preferred order:
1. User-supplied — issue number the user gave you in the request. 2. Auto-detect from branch name — extract trailing/leading issue number:
ISSUE_NUM=$(echo "$CURRENT_BRANCH" | grep -oE '(^|[/_#-])([0-9]{1,6})([/_-]|$)' | grep -oE '[0-9]+' | head -1)3. Auto-detect from commit messages — scan for closing keywords already authored:
git log "origin/$TARGET_BRANCH"..HEAD --pretty=%B | grep -oE '(Fixes|Closes|Resolves|Refs) #[0-9]+' | head -14. Open issues assigned to user — fall back to listing for human pick:
gh issue list --assignee @me --state open --json number,title --limit 205. No-issue path — if the repo template allows No issue required and this is docs-only / dependency-only / housekeeping, mark that checkbox explicitly. Do not invent this path if the template doesn't offer it. 6. Stop and ask — if the repo requires an issue and none of the above resolves it, stop and tell the user to open or specify the issue first.
Validate the issue exists (steps 1–4) before using it:
gh issue view "$ISSUE_NUM" --json number,title,state >/dev/null 2>&1 \
|| { echo "Issue #$ISSUE_NUM not found in this repo — re-detect or ask user"; exit 1; }Sanity check after choosing:
printf '%s
' "$ISSUE_LINK"
# Must be one of:
# Closes #123
# Fixes #123
# Resolves #123
# Refs #123 (related, does not close)
# - [x] No issue required ... (only when template allows)---
4. Generate PR Content
Analyze commits to generate the summary:
# Get commits in this branch
git log "origin/$TARGET_BRANCH"..HEAD --oneline
# Get changed files
git diff "origin/$TARGET_BRANCH" --name-onlyBuild the PR body so it satisfies both the repo template and any issue-link checks.
Template for repos like Keepfolio:
## Summary
- Key change 1
- Key change 2
- Key change 3
## Linked issues
Closes #123
- [ ] No issue required (docs-only, dependency-only, or housekeeping)
## Verification
- bun run typecheck
- cd app && bun run testNo-issue-required variant:
## Summary
- Documentation cleanup
- No product behavior changed
## Linked issues
- [x] No issue required (docs-only, dependency-only, or housekeeping)
## Verification
- bun run lint---
5. Create Pull Request
Prefer --body-file over giant inline heredocs when repo templates matter.
cat >/tmp/pr-body.md <<'EOF'
## Summary
- Key change 1
- Key change 2
## Linked issues
Closes #123
- [ ] No issue required (docs-only, dependency-only, or housekeeping)
## Verification
- test command 1
- test command 2
EOF
gh pr create \
--base "$TARGET_BRANCH" \
--title "$PR_TITLE" \
--body-file /tmp/pr-body.md---
6. Verify PR Metadata Immediately
Do not assume GitHub parsed the body the way you intended.
gh pr view --json number,url,body,baseRefName,closingIssuesReferencesChecks:
- If
baseRefNameis wrong, fix the PR before doing anything else. - If the repo expects an issue-closing keyword and
closingIssuesReferencesis empty, the body is malformed or missing the real issue line — fix it immediately. - If using the no-issue-required path, make sure the checkbox is
[x], not[ ].
Fix in place when needed:
gh pr edit <PR_NUMBER> --body-file /tmp/pr-body.md---
7. Add Labels and Reviewers (Optional)
# Add labels
gh pr edit --add-label "feature,needs-review"
# Request reviewers
gh pr edit --add-reviewer username1,username2
# Assign to yourself
gh pr edit --add-assignee @me---
8. Continue to CI Monitoring (Default: Yes)
After creating the PR, automatically proceed to the CI Monitor & Merge workflow unless the user explicitly opts out. This is the natural continuation.
→ PR created. Monitoring CI and automated reviews...
→ Read: workflows/CIMerge.md and execute Phase 2AIf the user says "just create the PR" or "don't merge yet", stop here and report without continuing.
---
PR Body Guidance
Summary:
- Bullet points of key changes
- High-level overview of what the PR accomplishes
Linked issues:
- Use
Closes #NUM,Fixes #NUM, orResolves #NUMwhen tied to an issue - Use the repo's exact
No issue requiredcheckbox text when that path is allowed - Avoid placeholders
Verification:
- Concrete local commands actually run
- Keep it truthful and copy-pastable
Screenshots/Videos:
- Add when UI changes need visual proof
---
Merge Strategies
Squash and Merge (recommended for features):
- Combines all commits into one
- Keeps target branch history clean
- Use when: Many small WIP commits in feature branches
Merge Commit (recommended for releases):
- Preserves complete history
- Shows all individual commits
- Use when: Release commits are already well-organized
Rebase and Merge (use with caution):
- Replays commits on top of base branch
- Linear history
- Use when: Very experienced with git and repo policy allows it
---
Report (if stopping after PR creation)
## Pull Request Created
**Title:** PR_TITLE
**Branch:** CURRENT_BRANCH → TARGET_BRANCH
**URL:** [PR link from gh output]
**Issue Link:** ISSUE_LINK
**Summary:**
- X commits
- Y files changed
- Z insertions, W deletions
**Next Steps:**
- CI monitoring available: /GitWorkflow merge
- Or monitor manually at the PR URLRelease Workflow
Manage releases with semantic versioning and changelog generation.
Variables
VERSION: $ARGUMENTS (e.g., 1.2.0)
RELEASE_TYPE: {{major|minor|patch}} - auto-detected from commitsWorkflow
1. Determine Version Bump
Analyze commits since last release to suggest version bump:
# Get commits since last tag
git log $(git describe --tags --abbrev=0)..HEAD --onelineVersion Bump Rules:
| Commit Type | Version Bump | Example |
|---|---|---|
BREAKING CHANGE: in footer | MAJOR | v1.0.0 → v2.0.0 |
feat: commits | MINOR | v1.0.0 → v1.1.0 |
fix:, perf:, docs: | PATCH | v1.0.0 → v1.0.1 |
# Check for breaking changes
git log $(git describe --tags --abbrev=0)..HEAD | grep -i "BREAKING CHANGE"
# Check for features
git log $(git describe --tags --abbrev=0)..HEAD --grep="^✨ feat"
# Check for fixes
git log $(git describe --tags --abbrev=0)..HEAD --grep="^🐛 fix"---
2. Create Release Branch
# Create release branch from develop
git checkout develop
git pull origin develop
git checkout -b release/vVERSION---
3. Update Version Files
Update version in project files:
Node.js:
npm version VERSION --no-git-tag-version
# or
pnpm version VERSION --no-git-tag-versionPython:
# Update __version__ in __init__.py or pyproject.tomlRust:
# Update version in Cargo.tomlCommit version bump:
git commit -am "🔖 release: bump version to VERSION"---
4. Generate Changelog (MANDATORY — Uses changelog CLI)
⚠️ This step is GATED. You MUST use the `changelog` CLI tool. Do NOT manually construct changelogs.
Generate changelog from conventional commits using the automated tool:
# Preview what will be generated (dry-run first)
changelog VERSION --auto --dry-run
# Generate and update CHANGELOG.md (non-interactive for automation)
changelog VERSION --auto --forceThe changelog CLI tool (~/.local/bin/changelog) automatically:
- Analyzes all commits since the last git tag
- Groups by type: Added, Fixed, Changed, Deprecated, Removed, Security
- Detects breaking changes for MAJOR version bumps
- Extracts PR numbers from commit messages
- Creates backup of existing CHANGELOG.md
- Updates version comparison links at the bottom
- Follows Keep a Changelog format
If changelog tool is not available, fall back to manual generation:
# List all features since last release
git log $(git describe --tags --abbrev=0)..HEAD --grep="^✨ feat" --oneline
# List all fixes
git log $(git describe --tags --abbrev=0)..HEAD --grep="^🐛 fix" --oneline
# List breaking changes
git log $(git describe --tags --abbrev=0)..HEAD --grep="BREAKING CHANGE" --onelineCommit changelog:
git add CHANGELOG.md
git commit -m "📝 docs: update changelog for vVERSION"---
5. Push Release Branch
git push -u origin release/vVERSION---
6. Finalize Release
After testing and approval:
# Merge to main
git checkout main
git pull origin main
git merge --no-ff release/vVERSION
# Tag the release
git tag -a vVERSION -m "Release vVERSION"
# Push main with tags
git push origin main --tags
# Merge back to develop
git checkout develop
git pull origin develop
git merge --no-ff release/vVERSION
git push origin develop
# Clean up
git branch -d release/vVERSION
git push origin --delete release/vVERSION---
Semantic Versioning Guide
Format: vMAJOR.MINOR.PATCH (e.g., v1.2.3)
MAJOR (v1.0.0 → v2.0.0):
- Breaking API changes
- Incompatible changes to public interfaces
- Removal of deprecated features
- Major architectural changes
MINOR (v1.0.0 → v1.1.0):
- New features (backwards compatible)
- New functionality added
- Deprecations (but not removals)
PATCH (v1.0.0 → v1.0.1):
- Bug fixes
- Security patches
- Performance improvements
- Documentation updates
---
Report
## Release Created
**Version:** vVERSION
**Type:** RELEASE_TYPE bump
**Tag:** vVERSION
**Branch:** release/vVERSION
**Changelog:**
[summary of changes]
**Next Steps:**
1. Test release branch
2. Get approval
3. Run: Finish release workflowSubmodule Workflow
Manage git submodules: add, update, remove, and sync repositories as submodules.
Usage
/GitWorkflow submodule add <url> [path] # Add a repo as submodule
/GitWorkflow submodule update # Update all submodules to latest
/GitWorkflow submodule remove <path> # Remove a submodule
/GitWorkflow submodule status # Show submodule status
/GitWorkflow submodule sync # Sync submodule URLs from .gitmodulesVariables
SUBMODULE_ACTION: {{first word of ARGUMENTS}}
SUBMODULE_URL: {{extract URL from ARGUMENTS}}
SUBMODULE_PATH: {{extract path from ARGUMENTS, or derive from URL}}---
Action: add
Add an external repository as a submodule.
Workflow
1. Validate inputs:
- Check URL is provided
- If path not provided, derive from URL:
repo-namefromgithub.com/org/repo-name.git
2. Check for conflicts:
# Ensure path doesn't already exist
test -e "$SUBMODULE_PATH" && echo "ERROR: Path already exists" && exit 1
# Ensure not already a submodule
git config --file .gitmodules --get "submodule.$SUBMODULE_PATH.url" && echo "ERROR: Already a submodule"3. Add submodule:
git submodule add $SUBMODULE_URL $SUBMODULE_PATH4. Initialize and fetch:
git submodule update --init --recursive $SUBMODULE_PATH5. Update .gitignore if needed:
- Check if path was in .gitignore
- If so, remove it (submodules should be tracked)
- Use
AskUserQuestionto confirm removal
6. Display result:
✅ Submodule added: $SUBMODULE_PATH
Remote: $SUBMODULE_URL
Commit: $(cd $SUBMODULE_PATH && git rev-parse --short HEAD)
Files staged:
- .gitmodules
- $SUBMODULE_PATH
💡 Run `/git:commit` to commit the submodule additionPath Conventions
| Repo Type | Suggested Path |
|---|---|
| Related project repos | repos/<name> |
| Shared libraries | packages/<name> or libs/<name> |
| Documentation repos | docs/<name> |
| Tools/scripts | tools/<name> |
---
Action: update
Update all submodules to their latest remote commits.
Workflow
1. Fetch latest from all remotes:
git submodule foreach --recursive 'git fetch origin'2. Check for updates:
git submodule foreach --recursive 'git log HEAD..origin/$(git rev-parse --abbrev-ref HEAD) --oneline'3. If updates available, ask user:
- Use
AskUserQuestion: "Update submodules to latest?" - Options: "Yes, update all", "Let me choose which ones", "Cancel"
4. Update submodules:
git submodule update --remote --merge5. Display results:
git submodule status6. Stage and prompt for commit:
💡 Submodule pointers updated. Run `/git:commit` to commit the updates.---
Action: remove
Remove a submodule from the repository.
Workflow
1. Validate submodule exists:
git config --file .gitmodules --get "submodule.$SUBMODULE_PATH.url"2. Confirm with user:
- Use
AskUserQuestion: "Remove submodule at $SUBMODULE_PATH? This will delete the directory." - Show current commit being tracked
3. Remove submodule:
# De-init the submodule
git submodule deinit -f $SUBMODULE_PATH
# Remove from .git/modules
rm -rf .git/modules/$SUBMODULE_PATH
# Remove from working tree and index
git rm -f $SUBMODULE_PATH4. Display result:
✅ Submodule removed: $SUBMODULE_PATH
💡 Run `/git:commit` to commit the removal---
Action: status
Show detailed status of all submodules.
Workflow
1. Check for submodules:
test -f .gitmodules || echo "No submodules in this repository"2. Display status table:
git submodule status --recursive3. Interpret and display:
| Prefix | Meaning |
|---|---|
(space) | Clean, at recorded commit |
+ | Submodule has new commits (need to commit parent) |
- | Not initialized (run git submodule update --init) |
U | Merge conflict |
4. Check for dirty content:
git submodule foreach 'git status --porcelain'5. Display formatted output:
## Submodules Status
| Submodule | Status | Commit | Dirty |
|-----------|--------|--------|-------|
| acp-church-media | clean | abc1234 | No |
| repos/daemon-mcp | ahead | def5678 | Yes (3 files) |
| repos/playlist-transcripts | clean | ghi9012 | No |
💡 Dirty submodules need: `cd <path> && git commit` or `/git:commit` (handles automatically)
💡 Ahead submodules need: parent commit to update pointer---
Action: sync
Sync submodule remote URLs after editing .gitmodules.
Workflow
1. Sync URLs:
git submodule sync --recursive2. Display synced URLs:
git submodule foreach 'echo "$name: $(git remote get-url origin)"'---
Error Handling
| Error | Action |
|---|---|
| URL invalid | Validate URL format, suggest HTTPS or SSH |
| Path exists (not submodule) | Ask to convert or choose different path |
| Network error | Retry with SSH if HTTPS fails |
| Submodule not found | Show available submodules from .gitmodules |
| Permission denied | Check SSH keys, suggest HTTPS fallback |
---
Integration with Commit Workflow
The Commit workflow (Phase 0) automatically handles dirty submodules:
1. Detects modified content in submodules 2. Commits changes inside submodule first 3. Pushes submodule to its remote 4. Then updates parent repo's submodule pointer
This Submodule workflow handles structural changes (add/remove/sync), while Commit handles content changes.