name: git-workflow description: Complete git workflow automation for feature development. Use when creating feature branches, making commits, creating PRs, addressing reviews, monitoring PR status, merging, and cleaning up branches. Covers the full PR lifecycle from branch creation to merge including review remediation.
Git Workflow Automation
Complete git workflow automation for feature development lifecycle from branch creation to merge.
Overview
This skill automates the complete feature development workflow:
- Create feature branch from the default branch
- Commit changes with emoji conventional commits
- Push to remote
- Create PR with structured markdown template
- Poll for reviews — wait for code review comments
- Evaluate and remediate — categorize and fix each comment
- Push fixes and reply — push changes, acknowledge every comment
- Loop — re-check for new feedback on fixes
- Monitor status (UNSTABLE -> CLEAN)
- Merge PR (squash + delete branch)
- Cleanup local and remote branches
⚠️ MANDATORY: When executing the full workflow, ALL 11 steps MUST execute sequentially. Do NOT stop after creating the PR (Step 4). Steps 5-11 (review, remediation, merge, cleanup) are mandatory parts of the flow, not optional follow-ups. Continue from each step to the next without stopping.
Triggering the Skill
Use natural language to invoke any part of the workflow:
Full Workflow
- "Complete git workflow for feature X"
- "Create feature branch, commit, PR, and merge"
- "Run full PR cycle"
Individual Steps
- "Create a feature branch for X"
- "Commit my changes with emoji conventional commits"
- "Create a PR with structured template"
- "Monitor my PR status"
- "Merge the PR and cleanup"
Review Handling
- "Check for PR comments and address them"
- "Fix review comments on PR #123"
- "Address feedback on current PR"
Step 1: Create Feature Branch
# Detect the default branch (main, master, etc.)
DEFAULT_BRANCH=$(git remote show origin 2>/dev/null | grep 'HEAD branch' | sed 's/.*: //' || echo "main")
git checkout "$DEFAULT_BRANCH"
git pull origin "$DEFAULT_BRANCH"
git checkout -b feat/descriptive-name
Branch naming conventions:
feat/- New featuresfix/- Bug fixesdocs/- Documentation changesrefactor/- Code refactoringperf/- Performance improvementstest/- Test additions/changeschore/- Maintenance tasksci/- CI/CD changes
Step 2: Commit with Emoji Conventional Commits
Stage and Commit
git add <files>
git commit -m "<emoji> <type>[optional scope]: <description>"
Commit Types & Emojis
| Type | Emoji | Description | Example |
|---|---|---|---|
feat | ✨ | New feature | ✨ feat(auth): add JWT token validation |
fix | 🐛 | Bug fix | 🐛 fix(api): resolve memory leak in handler |
docs | 📝 | Documentation | 📝 docs: update API endpoints documentation |
style | 🎨 | Code style | 🎨 style: format code with prettier |
refactor | ♻️ | Code refactoring | ♻️ refactor: simplify authentication logic |
perf | ⚡️ | Performance | ⚡️ perf: optimize database query performance |
test | ✅ | Testing | ✅ test: add unit tests for user service |
chore | 🔧 | Maintenance | 🔧 chore: update build dependencies |
ci | 👷 | CI/CD | 👷 ci: add github actions workflow |
build | 📦 | Build system | 📦 build: upgrade to webpack 5 |
revert | ⏪ | Revert | ⏪ revert: rollback payment integration |
Commit Message Format
Simple (default):
✨ feat(auth): add JWT token validation
Full (with body):
✨ feat(auth): add JWT token validation
Implement JWT token validation middleware that:
- Validates token signature and expiration
- Extracts user claims from payload
- Adds user context to request object
This improves security by ensuring all protected routes
validate authentication tokens properly.
Co-authored-by: Claude <[email protected]>
Best Practices
- ✅ Use present tense, imperative mood ("add" not "added")
- ✅ Keep first line under 50 characters (72 max)
- ✅ Capitalize first letter
- ✅ No period at end of subject line
- ✅ Use scope for context (e.g.,
feat(auth):) - ✅ Include
Co-authored-by:footer for AI-assisted commits
Step 3: Push to Remote
git push -u origin feat/descriptive-name
Step 4: Create PR with Structured Template
Before creating the PR, analyze the actual changes:
# See all changes in this branch vs the default branch
git diff "$DEFAULT_BRANCH"...HEAD
# See commit messages
git log "$DEFAULT_BRANCH"..HEAD --pretty=format:"%s"
You MUST generate the PR title and body from the actual diff — never use placeholder text.
- Title: Use the emoji and type from the primary commit (e.g.,
✨ feat:,🐛 fix:). Include the emoji. - Body: Fill every section with REAL content derived from the diff. Do NOT write
[One-line summary]or[First change]— write actual descriptions of the real changes.
gh pr create \
--title "<EMOJI> <TYPE>: <brief description>" \
--body "$(cat <<EOF
## 📝 Summary
[Write a REAL one-sentence summary based on the actual diff]
## 🔄 Changes
[List each meaningful change as a bullet point with an emoji prefix. Base on git diff output]
## ✅ Verification
[Provide specific, runnable verification steps based on what actually changed]
## 🔗 Sources
[Include relevant links: issue references (Closes #N), docs, related PRs. Omit section if none exist]
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"
PR Template Examples
Feature PR:
## 📝 Summary
Add OAuth2 authentication flow supporting Google and GitHub providers.
## 🔄 Changes
- ✨ Add OAuth2 authorization code flow with PKCE
- 🔐 Implement secure token storage with encrypted cookies
- 📝 Add user profile synchronization on first login
- 🎨 Update login UI with provider buttons
## ✅ Verification
1. Run locally: `npm run dev`
2. Visit `/login` and click "Sign in with Google"
3. Complete OAuth flow
4. Verify user profile is created correctly
5. Check token refresh works on page reload
```bash
# Test suite
npm run test:auth
🔗 Sources
- Closes #456
- OAuth 2.1 RFC: https://datatracker.ietf.org/doc/html/rfc6749
- Design doc: docs/design/oauth2-integration.md
**Bug Fix PR:**
```markdown
## 📝 Summary
Fix memory leak in event handler that caused increased memory usage over time.
## 🔄 Changes
- 🐛 Fix event listener not being properly removed
- ✅ Add cleanup in componentWillUnmount
- 📝 Add documentation for event handler lifecycle
## ✅ Verification
1. Open browser DevTools → Memory
2. Take heap snapshot
3. Navigate through app 10 times
4. Take another snapshot
5. Verify no detached DOM nodes
## 🔗 Sources
- Fixes #789
- Related issue: #123
Step 5: Poll for Code Reviews
Wait for code reviews to complete before checking comments:
echo "⏳ Waiting for code reviews..."
sleep 180
Fetch Review Comments
# Resolve repo slug
REPO_SLUG=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
# List PRs
gh pr list
# View PR details
gh pr view <PR_NUMBER>
# Get inline code-level review comments (filter out replies to get originals only)
gh api repos/$REPO_SLUG/pulls/$PR_NUMBER/comments --jq '.[] | select(.in_reply_to_id == null) | {id: .id, path: .path, line: .line, body: .body}'
# Get issue-level comments (general PR comments)
gh api repos/$REPO_SLUG/issues/$PR_NUMBER/comments --jq '.[] | {id: .id, body: .body}'
# Get review state
gh pr view $PR_NUMBER --json reviews --jq '.reviews[] | {state: .state, body: .body, author: .author.login}'
Step 6: Evaluate and Remediate Review Comments
Categorize Each Comment
| Category | Action | Examples |
|---|---|---|
| Must fix | Code change required | Bugs, security issues, logic errors, broken tests |
| Should fix | Code change recommended | Code style, naming, missing error handling |
| Suggestion | Optional, apply judgment | Alternative approaches, nicer patterns |
| Question | Reply only, no code change | Reviewer asking for clarification |
| Already addressed | Reply only | Comment refers to code already fixed |
Process for Each Comment
- Read the referenced file at the specified line number
- Make the minimal fix needed to address the feedback
- Stage and commit with appropriate emoji commit
- Track the comment ID for replying later
# Make the fix
# ... code changes ...
# Commit the fix
git add <changed-files>
git commit -m "🐛 fix: address review feedback - handle edge case"
Step 7: Push Fixes and Reply to Every Comment
After all fixes are committed:
# Push all fix commits
git push
Before replying, compute the fix hash:
FIX_HASH=$(git rev-parse --short HEAD)
Then for each comment, reply using the shell variable $FIX_HASH and the literal numeric id from Step 5's fetch:
# Reply to inline review comment
gh api repos/$REPO_SLUG/pulls/$PR_NUMBER/comments \
--method POST \
--field body="✅ Fixed in $FIX_HASH. <describe what was actually changed>" \
--field in_reply_to=$COMMENT_ID
# Reply to general PR comment (note: GitHub API creates a new top-level comment, not a threaded reply — this is an API limitation)
gh api repos/$REPO_SLUG/issues/$PR_NUMBER/comments \
--method POST \
--field body="✅ Addressed in $FIX_HASH. <describe what was actually changed>"
Reply format:
- Fixes:
✅ Fixed in <short_hash> — <what was changed> - Questions:
💡 <answer> - Suggestions not applied:
🙏 Good suggestion, but <reason>. Happy to revisit if needed.
Step 8: Loop — Re-check for New Feedback
After pushing fixes:
# Re-fetch comments and compare against already-processed IDs
gh api repos/$REPO_SLUG/pulls/$PR_NUMBER/comments --jq '.[] | select(.in_reply_to_id == null) | .id'
- If new comment IDs found → repeat from Step 6
- If no new comments → proceed to Step 9
Common Review Responses
| Comment Type | Response Approach |
|---|---|
| Code style | Fix + 🎨 style: commit |
| Bug report | Fix + 🐛 fix: commit |
| Missing tests | Add tests + ✅ test: commit |
| Documentation | Update docs + 📝 docs: commit |
| Performance | Optimize + ⚡️ perf: commit |
| Refactoring | Refactor + ♻️ refactor: commit |
Step 9: Monitor PR Status (UNSTABLE -> CLEAN)
Use this monitoring loop to wait for all CI checks to pass:
#!/bin/bash
PR_NUMBER="<PR_NUMBER>"
for i in {1..60}; do
pr_status=$(gh pr view $PR_NUMBER --json mergeStateStatus --jq '.mergeStateStatus')
if [ "$pr_status" = "CLEAN" ]; then
echo "✅ All checks passed! Ready to merge."
exit 0
fi
echo "⏳ Waiting... ($i/60) - status: $pr_status"
sleep 10
done
echo "❌ Timeout - checks did not pass within 10 minutes"
exit 1
Possible statuses:
UNKNOWN- Status not yet determinedBEHIND- Branch is behind base branchBLOCKED- Blocked by failing checksDIRTY- Merge conflictDRAFT- PR is in draft stateUNSTABLE- Checks have not passed yetCLEAN- All checks passed, ready to merge
Step 10: Merge PR (Squash + Delete Branch)
gh pr merge <PR_NUMBER> --squash --delete-branch
Note: Omitting --subject lets GitHub default to the PR title, which already has the correct emoji/type prefix.
Merge options:
--squash- Combine all commits into one (recommended)--merge- Merge with full commit history--rebase- Rebase commits onto base branch--delete-branch- Delete branch after merge
Step 11: Cleanup Local and Remote Branches
# Switch back to the default branch
git checkout "$DEFAULT_BRANCH"
# Pull latest changes
git pull origin "$DEFAULT_BRANCH"
# Delete local branch
git branch -d feat/descriptive-name
# Force delete if needed
git branch -D feat/descriptive-name
# Delete remote branch (if not already deleted)
git push origin --delete feat/descriptive-name
Complete Workflow Script
Here's a complete script that combines the full workflow (monitor, remediate, merge, cleanup):
#!/bin/bash
set -e
PR_NUMBER="<PR_NUMBER>"
REPO_SLUG=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
# Step 5: Wait for reviews
echo "⏳ Waiting 120 seconds for code reviews..."
sleep 180
# Step 6-8: Remediation loop (max 5 iterations)
PROCESSED_IDS=""
MAX_ITERATIONS=5
iteration=0
while [ $iteration -lt $MAX_ITERATIONS ]; do
iteration=$((iteration + 1))
COMMENT_IDS=$(gh api repos/$REPO_SLUG/pulls/$PR_NUMBER/comments --jq '.[] | select(.in_reply_to_id == null) | .id')
NEW_IDS=$(comm -23 <(echo "$COMMENT_IDS" | sort) <(echo "$PROCESSED_IDS" | sort) || true)
if [ -z "$NEW_IDS" ]; then
echo "✅ No new review comments."
break
fi
echo "📝 New review comments found. Addressing..."
# (Claude Code evaluates and fixes each comment here)
git push
PROCESSED_IDS="${PROCESSED_IDS}
${NEW_IDS}"
echo "⏳ Waiting for CI and re-review..."
sleep 60
done
if [ $iteration -ge $MAX_ITERATIONS ]; then
echo "⚠️ Maximum remediation iterations reached. Manual review may be needed."
fi
# Step 9: Monitor PR status
echo "🔍 Monitoring PR #$PR_NUMBER status..."
HEAD_BRANCH=$(gh pr view $PR_NUMBER --json headRefName --jq '.headRefName')
for i in {1..60}; do
pr_status=$(gh pr view $PR_NUMBER --json mergeStateStatus --jq '.mergeStateStatus')
if [ "$pr_status" = "CLEAN" ]; then
echo "✅ All checks passed!"
break
fi
echo "⏳ Waiting... ($i/60) - status: $pr_status"
sleep 10
done
# Step 10: Merge PR
echo "🔀 Merging PR #$PR_NUMBER..."
gh pr merge $PR_NUMBER --squash --delete-branch
# Step 11: Cleanup
echo "🧹 Cleaning up..."
git checkout "$DEFAULT_BRANCH"
git pull origin "$DEFAULT_BRANCH"
git branch -D "$HEAD_BRANCH" 2>/dev/null || true
echo "✅ Done! Ready for next feature."
Quick Reference Commands
Branch Operations
git checkout -b feat/feature-name # Create feature branch
git checkout "$DEFAULT_BRANCH" && git pull # Sync with default branch
git branch -d feat/feature-name # Delete local branch
git push origin --delete feat/... # Delete remote branch
Commit Operations
git add . # Stage all changes
git commit -m "✨ feat: description" # Commit with emoji
git push -u origin feat/... # Push with upstream tracking
PR Operations
gh pr create # Create PR interactively
gh pr list # List open PRs
gh pr view <number> # View PR details
gh pr merge <number> --squash # Merge PR
Status & Monitoring
git status # Working tree status
gh pr checks # View CI status
gh pr view <number> --json status # Get PR status JSON
Important Notes
- NEVER commit directly to the default branch unless explicitly instructed
- Always use feature branches for changes
- Write meaningful commit messages with emoji prefixes
- Keep PRs focused on a single change
- Address all review comments before requesting merge
- Wait for CI to pass before merging
- Squash merges keep the default branch history clean
- Delete branches after merging to keep repo clean
Common Gotchas
1. Merge Conflicts
Problem: PR shows DIRTY status with merge conflicts.
Solution:
git checkout "$DEFAULT_BRANCH"
git pull origin "$DEFAULT_BRANCH"
git checkout feat/your-branch
git merge "$DEFAULT_BRANCH"
# Resolve conflicts
git add .
git commit -m "🔧 chore: resolve merge conflicts"
git push
2. Behind Base Branch
Problem: PR shows BEHIND status.
Solution:
git checkout "$DEFAULT_BRANCH"
git pull origin "$DEFAULT_BRANCH"
git checkout feat/your-branch
git merge "$DEFAULT_BRANCH"
git push
3. Pre-commit Hooks Failing
Problem: Commit blocked by linters/tests.
Solution:
# Run checks manually first
npm run lint
npm run test
# Or skip hooks (not recommended for production)
git commit --no-verify -m "message"
4. PR Template Not Applied
Problem: Created PR without proper template.
Solution: Always use gh pr create --body with heredoc or create PR template file in .github/pull_request_template.md
Example Usage Sessions
Session 1: Quick Bug Fix
User: Create a fix for the login bug
Claude:
1. Creating fix/login-timeout branch
2. Adding timeout handling to auth service
3. Committing with: 🐛 fix(auth): increase login timeout to 30s
4. Pushing to remote
5. Creating PR with template
6. Monitoring status...
Session 2: Feature with Review
User: Complete workflow for user profile feature
Claude:
1. Creating feat/user-profile branch
2. Implementing profile components
3. ✅ feat: add profile picture upload
4. ✅ feat: add profile edit form
5. ✅ test: add profile unit tests
6. Creating PR...
7. Waiting for review...
8. Review comment: "Add validation for image size"
9. Addressing: 🐛 fix: add image size validation
10. Pushing fix...
11. Monitoring status: UNSTABLE -> CLEAN
12. Merging with squash...
13. Cleaning up branches...
14. Done!
Integration with Other Skills
This skill works well with:
- commit-commands - For detailed conventional commit creation
- feature-dev - For feature development workflow
- code-review - For reviewing PRs
- github - For GitHub API operations