Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:28:17 +08:00
commit 4f8b6d7dd8
16 changed files with 8817 additions and 0 deletions

421
commands/bisect.md Normal file
View File

@@ -0,0 +1,421 @@
---
name: git:bisect
description: Interactive git bisect workflow to find commits that introduced bugs using binary search
---
# Git Bisect - Binary Search for Bug-Introducing Commits
Interactive git bisect workflow to find commits that introduced bugs using binary search.
## Command
`/git:bisect [mode] [commit-ref]`
## Arguments
- `$1`: mode - `start|good|bad|skip|reset` (optional, interactive if not provided)
- `$2`: commit-ref (optional, depends on mode)
## Description
Git bisect uses binary search to efficiently find the commit that introduced a bug. Instead of checking every commit, it splits the commit range in half repeatedly, asking you to test each midpoint. This can find a bug in log(n) checks instead of n checks.
## Workflow
### Starting a Bisect Session
1. **Pre-flight checks:**
- Check if bisect is already in progress: `git bisect log`
- Check for uncommitted changes: `git status --porcelain`
- If changes exist, warn user and suggest stashing
2. **Gather information:**
- Ask for the "good" commit (where bug didn't exist)
- Default: last tag or commit from 1 week ago
- User can specify: commit hash, tag, branch name
- Ask for the "bad" commit (where bug exists)
- Default: HEAD (current commit)
- User can specify: commit hash, tag, branch name
- Calculate and show number of commits between good and bad
- Estimate number of steps needed: ~log2(n)
3. **Start bisect:**
```bash
git bisect start
git bisect bad [bad-commit]
git bisect good [good-commit]
```
4. **Show first commit to test:**
- Display commit hash, date, author, message
- Show which files changed: `git show --stat <commit>`
- Provide clear instructions on what to test
### During Bisect Session
5. **Test current commit:**
- Ask user to test whether the bug exists
- Provide clear instructions:
- "Run your tests"
- "Manually test the feature"
- "Check the logs"
- Wait for user feedback
6. **Mark commit based on test result:**
- If bug exists: `git bisect bad`
- If bug doesn't exist: `git bisect good`
- If commit is untestable (won't build, etc): `git bisect skip`
- Option to abort: `git bisect reset`
7. **Show progress:**
- Display remaining commits to test
- Show estimated steps left
- Display bisect log: `git bisect log`
8. **Repeat steps 5-7** until the first bad commit is found
### Completion
9. **When bug commit identified:**
- Display full commit details:
```bash
git show <commit-hash>
```
- Show commit message, author, date
- Show full diff
- Highlight which files were changed
10. **Offer actions:**
- Create a branch from this commit for investigation
- Create a branch from parent commit for fix
- Copy commit hash to clipboard
- View commit in GitHub/GitLab (if remote exists)
- Reset bisect and return to original HEAD
11. **Reset bisect:**
```bash
git bisect reset
```
- Return to original branch/commit
- Confirm user is back to starting state
### Abort/Reset Anytime
At any point during the bisect, user can:
- Type 'abort' to run `git bisect reset`
- Type 'skip' to skip current commit
- Type 'log' to see bisect progress
- Type 'visualize' to see bisect state graphically
## Safety Checks
### Before Starting
- **Uncommitted changes:**
```bash
if [ -n "$(git status --porcelain)" ]; then
echo "Warning: You have uncommitted changes."
echo "Options:"
echo " 1. Stash changes: git stash save 'Pre-bisect stash'"
echo " 2. Commit changes"
echo " 3. Discard changes (dangerous)"
echo " 4. Cancel bisect"
# Wait for user choice
fi
```
- **Already in bisect:**
```bash
if [ -f .git/BISECT_LOG ]; then
echo "Bisect already in progress!"
echo "Options:"
echo " 1. Continue current bisect"
echo " 2. Reset and start new bisect"
echo " 3. Cancel"
# Wait for user choice
fi
```
- **Detached HEAD warning:**
- Explain that bisect will put repo in detached HEAD state
- Assure user that `git bisect reset` will return to original state
### During Bisect
- **Clear instructions at each step:**
- Show current commit details
- Explain what user needs to test
- Show available commands (good/bad/skip/reset)
- Display progress and remaining steps
- **Skip commit handling:**
- Explain when to skip (build failures, unrelated changes)
- Warn that excessive skipping reduces effectiveness
- Show how many commits have been skipped
### After Bisect
- **Confirmation before reset:**
- Ask if user wants to save any notes
- Offer to create branch at bug commit
- Confirm reset operation
- **Verify return state:**
- Check user is back on original branch
- Verify working directory is clean
- Confirm bisect refs are removed
## Error Handling
### Invalid Commit References
```bash
if ! git rev-parse --verify "$commit_ref" >/dev/null 2>&1; then
echo "Error: '$commit_ref' is not a valid commit reference"
echo "Valid formats:"
echo " - Commit hash: abc1234 or abc1234567890abcdef"
echo " - Branch name: main, feature-branch"
echo " - Tag: v1.0.0"
echo " - Relative: HEAD~5, HEAD^^^"
exit 1
fi
```
### Good Commit is Newer Than Bad Commit
```bash
if [ $(git rev-list --count $good_commit..$bad_commit) -eq 0 ]; then
echo "Error: Good commit ($good_commit) is not an ancestor of bad commit ($bad_commit)"
echo "Make sure:"
echo " - Good commit is older (bug didn't exist yet)"
echo " - Bad commit is newer (bug exists)"
echo " - Both commits are on the same branch history"
exit 1
fi
```
### Build Failures
```bash
# When user reports commit won't build
echo "This commit won't build/test. Options:"
echo " 1. Skip this commit: git bisect skip"
echo " 2. Skip a range: git bisect skip v1.0..v1.5"
echo " 3. Reset and try different good/bad commits"
# Wait for user choice
```
### Conflicts or Issues
```bash
# If checkout fails during bisect
if [ $? -ne 0 ]; then
echo "Error: Could not checkout commit"
echo "This might indicate:"
echo " - Local modifications conflict with commit"
echo " - Repository corruption"
echo "Run 'git bisect reset' to abort and investigate"
exit 1
fi
```
## Examples
### Example 1: Basic Interactive Bisect
```bash
# Start interactive bisect
/git:bisect
# Claude will prompt:
# "When did you last see the code working correctly?"
# User: "On the v1.2.0 tag"
#
# "When did you first notice the bug?"
# User: "In the current commit (HEAD)"
#
# Starting bisect with 47 commits between v1.2.0 and HEAD
# This will take approximately 6 steps
#
# Now at: commit abc1234
# Author: John Doe
# Date: 2025-10-15
# Message: Refactor authentication module
#
# Files changed:
# src/auth.js | 45 +++++++++++++++++++++
# tests/auth.test.js | 23 +++++++++++
#
# Please test if the bug exists in this commit.
# Reply with: good, bad, skip, or abort
```
### Example 2: Direct Mode Commands
```bash
# Start bisect directly
/git:bisect start
# Mark HEAD as bad
/git:bisect bad
# Mark a specific commit as good
/git:bisect good v1.2.0
# Skip untestable commit
/git:bisect skip
# View bisect log
git bisect log
# Reset and return to original state
/git:bisect reset
```
### Example 3: Automated Testing
```bash
# For repositories with automated tests
/git:bisect
# At each commit, run:
npm test # or: pytest, cargo test, go test, etc.
# If tests pass:
/git:bisect good
# If tests fail:
/git:bisect bad
# Continue until bug commit found
```
### Example 4: Binary Search Range
```bash
# Search within specific range
/git:bisect start HEAD v1.0.0
# Or use commit hashes
/git:bisect start abc1234 def5678
# Or use date-based references
/git:bisect start HEAD HEAD@{2.weeks.ago}
```
## Advanced Usage
### Bisect with Script
For fully automated bisecting when you have a test that can determine good/bad:
```bash
# Create a test script that exits 0 for good, 1 for bad
cat > test-bug.sh << 'EOF'
#!/bin/bash
npm test -- --testNamePattern="specific bug test"
EOF
chmod +x test-bug.sh
# Run bisect with script
git bisect start HEAD v1.0.0
git bisect run ./test-bug.sh
```
### Visualize Bisect State
```bash
# Text-based visualization
git bisect visualize --oneline
# Or with gitk (if available)
git bisect visualize
```
### Skip a Range of Commits
```bash
# If you know commits in a range are all untestable
git bisect skip v1.1.0..v1.2.0
```
### Bisect Log Analysis
```bash
# View complete bisect log
git bisect log
# Replay bisect from log
git bisect replay path/to/bisect-log.txt
```
## Tips for Effective Bisecting
1. **Choose good starting points:**
- Good commit: Use a tagged release where you know code worked
- Bad commit: Use the commit where you first noticed the bug
- Wider range = more accurate, but more steps
2. **Have a clear test:**
- Know exactly what behavior indicates the bug
- Have a reproducible test case
- Ideally have an automated test
3. **Handle build failures:**
- Skip commits that won't build
- If too many skip, widen the initial range
4. **Track progress:**
- Note down commit hashes you've tested
- Keep test results consistent
- Don't change test criteria mid-bisect
5. **When bug commit found:**
- Verify it's truly the first bad commit
- Check if bug is in the commit itself or its merge
- Look at what changed in that commit
## Output Format
During bisect, Claude will display structured output:
```
========================================
Git Bisect Status
========================================
Range: v1.2.0 (good) → HEAD (bad)
Total commits: 47
Estimated steps: 6 remaining
Current Commit:
----------------------------------------
Hash: abc1234567890abcdef
Author: Jane Smith <jane@example.com>
Date: Mon Oct 16 14:32:10 2025 -0700
Message: Update user authentication flow
Files Changed (5):
src/auth/login.js | 34 +++++++++++++++---
src/auth/session.js | 12 +++++--
tests/auth/login.test.js| 45 ++++++++++++++++++++++++
...
========================================
Action Required:
----------------------------------------
1. Test if bug exists in this commit
2. Reply with result:
- 'good' - bug does NOT exist
- 'bad' - bug DOES exist
- 'skip' - cannot test this commit
- 'abort' - stop bisect
What's your result?
```
## Related Commands
- `/git:reflog-recover` - Recover from bisect mistakes
- `/git:cherry-pick-helper` - Cherry-pick the bug fix
- `/git:worktree` - Test multiple commits simultaneously
- `/git:branch-cleanup` - Clean up bisect test branches

766
commands/branch-cleanup.md Normal file
View File

@@ -0,0 +1,766 @@
---
name: git:branch-cleanup
description: Clean up merged and stale branches locally and remotely with comprehensive safety checks
---
# Git Branch Cleanup - Merged and Stale Branch Management
Clean up merged and stale branches locally and remotely with comprehensive safety checks.
## Command
`/git:branch-cleanup [scope] [base-branch]`
## Arguments
- `$1`: scope - `local|remote|both` (default: `local`)
- `$2`: base-branch - Branch to check merges against (default: `main` or `master`)
## Description
Over time, repositories accumulate branches from completed features, merged pull requests, and abandoned work. Branch cleanup helps maintain repository hygiene by identifying and safely removing branches that are no longer needed, while protecting active and important branches.
## Use Cases
- Clean up after merged pull requests
- Remove abandoned feature branches
- Prepare repository for new work
- Reduce clutter in branch listings
- Find stale branches that need attention
- Audit branch activity across team
- Free up branch names for reuse
## Branch Categories
Branches are classified into categories:
1. **Fully Merged** - Safe to delete
- All commits are in base branch
- Feature complete and merged
- No unique changes
2. **Partially Merged** - Review before delete
- Some commits merged
- May have additional work
- Requires investigation
3. **Stale** - No activity for long period
- No commits in 90+ days
- May be abandoned
- Should be reviewed before delete
4. **Active** - Recent activity
- Commits within last 30 days
- Likely still in use
- Should not be deleted
5. **Protected** - Never delete
- main, master, develop
- production, staging
- release branches
- Explicitly configured protected branches
## Workflow
### Initial Analysis
1. **Identify base branch:**
- Check for main or master
- Use user-specified branch if provided
- Validate base branch exists
2. **Gather branch information:**
```bash
# List all branches
git branch -a
# For each branch, get:
# - Last commit date
# - Last author
# - Commit count ahead/behind
# - Merge status
```
3. **Categorize branches:**
- Sort into categories (merged, stale, active, protected)
- Calculate statistics for each category
- Prepare summary report
4. **Show summary:**
```
Branch Cleanup Analysis
==================================================
Base branch: main
Scope: local branches
Categories:
Fully merged: 12 branches
Stale (90+ days): 5 branches
Active (<30 days): 8 branches
Protected: 3 branches (will not delete)
Total branches: 28
Safe to delete: 12 branches
```
### Local Branch Cleanup
5. **List fully merged branches:**
```bash
git branch --merged <base-branch>
```
6. **For each merged branch show:**
- Branch name
- Last commit date
- Last author
- Commit message
- Days since last commit
7. **Exclude protected branches:**
- main, master
- develop, development
- staging, production
- release/*, hotfix/*
- Current branch
8. **Show deletion plan:**
```
Fully Merged Branches (12):
==================================================
1. feature/user-auth
Last: 2025-09-15 (36 days ago)
By: John Doe
"Add JWT authentication"
2. bugfix/login-error
Last: 2025-08-30 (52 days ago)
By: Jane Smith
"Fix login redirect issue"
...
```
9. **Ask for confirmation:**
- Show dry-run option
- Allow individual selection
- Allow batch selection
- Offer to skip
10. **Delete local branches:**
```bash
git branch -d <branch-name>
```
Or force delete if needed:
```bash
git branch -D <branch-name>
```
### Stale Branch Handling
11. **Identify stale branches:**
```bash
# Branches with no commits in 90+ days
git for-each-ref --sort=-committerdate refs/heads/
```
12. **Show stale branches:**
- Branch name
- Last commit date (days ago)
- Last author
- Merged status
- Commit count unique to branch
13. **For each stale branch:**
- Show details
- Check if merged (even if old)
- Check for unique commits
- Ask user for action:
- Delete (if safe)
- Keep (still needed)
- Review (show more details)
### Remote Branch Cleanup
14. **Analyze remote branches:**
```bash
git branch -r --merged <base-branch>
```
15. **Cross-reference with local:**
- Remote branches without local counterpart
- Remote branches that are merged
- Remote branches that are stale
16. **Show remote deletion plan:**
- More cautious than local
- Double-check merge status
- Verify no open pull requests
- Confirm team coordination
17. **Delete remote branches:**
```bash
git push origin --delete <branch-name>
```
18. **Prune remote tracking branches:**
```bash
git fetch --prune
git remote prune origin
```
### Post-Cleanup
19. **Show cleanup summary:**
- Branches deleted (count and names)
- Branches skipped
- Branches protected
- Space saved (if measurable)
20. **Verify repository state:**
- Show remaining branches
- Verify no unintended deletions
- Check current branch still exists
21. **Offer additional actions:**
- Push cleanup to remote
- Archive deleted branches (tags)
- Export branch list before deletion
- Clean up remote tracking branches
## Safety Checks
### Before Any Deletion
- **Protected branches list:**
```bash
PROTECTED_BRANCHES=(
"main"
"master"
"develop"
"development"
"staging"
"production"
"release"
)
for protected in "${PROTECTED_BRANCHES[@]}"; do
if [[ "$branch" == "$protected" ]] || [[ "$branch" == "$protected"/* ]]; then
echo "Skipping protected branch: $branch"
continue
fi
done
```
- **Current branch check:**
```bash
current_branch=$(git branch --show-current)
if [ "$branch" = "$current_branch" ]; then
echo "Error: Cannot delete current branch: $branch"
echo "Switch to a different branch first"
exit 1
fi
```
- **Base branch check:**
```bash
if [ "$branch" = "$base_branch" ]; then
echo "Error: Cannot delete base branch: $base_branch"
echo "This is the branch we're comparing against!"
exit 1
fi
```
### Local Branch Deletion
- **Merged status verification:**
```bash
if git branch --merged $base_branch | grep -q "^[* ] $branch$"; then
echo "✓ Branch is fully merged into $base_branch"
merge_status="safe"
else
echo "⚠ Branch is NOT fully merged"
unmerged_commits=$(git log $base_branch..$branch --oneline | wc -l)
echo " $unmerged_commits unique commit(s) will be lost"
echo ""
echo "Show commits? (y/n)"
# If yes: git log $base_branch..$branch
merge_status="unsafe"
fi
```
- **Force delete confirmation:**
```bash
if [ "$merge_status" = "unsafe" ]; then
echo "Branch '$branch' has unmerged commits!"
echo "Force delete will PERMANENTLY lose these commits"
echo ""
git log --oneline $base_branch..$branch
echo ""
echo "Type 'DELETE' to force delete: "
read confirmation
[ "$confirmation" != "DELETE" ] && continue
# Use -D instead of -d
git branch -D $branch
fi
```
### Remote Branch Deletion
- **Remote reference check:**
```bash
if ! git ls-remote --heads origin $branch | grep -q $branch; then
echo "Branch '$branch' does not exist on remote"
continue
fi
```
- **Pull request check:**
```bash
# If GitHub CLI available
if command -v gh &> /dev/null; then
pr_count=$(gh pr list --head $branch --json number --jq 'length')
if [ $pr_count -gt 0 ]; then
echo "Warning: Branch '$branch' has open pull request(s)"
echo "View: gh pr view --web"
echo ""
echo "Delete anyway? (y/n)"
read confirm
[ "$confirm" != "y" ] && continue
fi
fi
```
- **Team coordination warning:**
```bash
echo "⚠ REMOTE DELETION WARNING"
echo "You are about to delete remote branch: origin/$branch"
echo ""
echo "This affects other developers if they:"
echo " - Have this branch checked out"
echo " - Have based work on this branch"
echo " - Have unpushed commits on this branch"
echo ""
echo "Have you coordinated with your team? (y/n)"
read coordinated
[ "$coordinated" != "y" ] && continue
```
### Batch Deletion Safety
- **Dry-run mode:**
```bash
echo "DRY-RUN MODE"
echo "Would delete these branches:"
for branch in "${branches_to_delete[@]}"; do
echo " - $branch"
done
echo ""
echo "Proceed with actual deletion? (y/n)"
```
- **Confirmation for bulk delete:**
```bash
if [ ${#branches_to_delete[@]} -gt 5 ]; then
echo "About to delete ${#branches_to_delete[@]} branches"
echo "This is a bulk operation!"
echo ""
echo "Type 'CONFIRM BULK DELETE' to proceed: "
read confirmation
[ "$confirmation" != "CONFIRM BULK DELETE" ] && exit 0
fi
```
## Error Handling
### Branch Not Fully Merged
```bash
if ! git branch -d $branch 2>&1; then
error=$(git branch -d $branch 2>&1)
if echo "$error" | grep -q "not fully merged"; then
echo "Error: Branch '$branch' is not fully merged"
echo ""
echo "Options:"
echo " 1. Skip this branch"
echo " 2. Force delete (lose commits): git branch -D $branch"
echo " 3. Show unmerged commits: git log $base_branch..$branch"
echo " 4. Merge branch first: git merge $branch"
echo ""
echo "What would you like to do? (1-4)"
fi
fi
```
### Remote Deletion Failure
```bash
if ! git push origin --delete $branch 2>&1; then
error=$(git push origin --delete $branch 2>&1)
if echo "$error" | grep -q "remote ref does not exist"; then
echo "Branch '$branch' does not exist on remote"
echo "Might already be deleted"
elif echo "$error" | grep -q "protected"; then
echo "Branch '$branch' is protected on remote"
echo "Cannot delete via git push"
echo "Delete via GitHub/GitLab UI if needed"
elif echo "$error" | grep -q "permission denied"; then
echo "Permission denied: cannot delete remote branch"
echo "You may not have push access"
else
echo "Unknown error deleting remote branch:"
echo "$error"
fi
fi
```
### No Branches to Delete
```bash
if [ ${#branches_to_delete[@]} -eq 0 ]; then
echo "No branches to delete!"
echo ""
echo "All branches are either:"
echo " - Protected branches"
echo " - Not fully merged"
echo " - Recently active"
echo " - Current branch"
echo ""
echo "Repository is clean!"
exit 0
fi
```
### Base Branch Not Found
```bash
if ! git rev-parse --verify $base_branch >/dev/null 2>&1; then
echo "Error: Base branch '$base_branch' not found"
echo ""
echo "Available branches:"
git branch -a | grep -E "(main|master|develop)" | sed 's/^[* ] //'
echo ""
echo "Specify base branch as second argument:"
echo " /git:branch-cleanup local main"
exit 1
fi
```
## Examples
### Example 1: Interactive Local Cleanup
```bash
/git:branch-cleanup local
# Analyzing branches...
# Base branch: main
#
# ========================================
# Branch Cleanup Analysis
# ========================================
#
# Fully Merged (8 branches):
# ------------------------------------------
# 1. feature/user-auth
# Last: 36 days ago by John Doe
# "Add JWT authentication"
#
# 2. bugfix/login-error
# Last: 52 days ago by Jane Smith
# "Fix login redirect issue"
#
# ... (6 more)
#
# Stale Branches (3 branches):
# ------------------------------------------
# 1. feature/old-idea
# Last: 127 days ago by Bob Johnson
# NOT merged - 15 unique commits
#
# ... (2 more)
#
# Protected (3 branches):
# ------------------------------------------
# - main (current)
# - develop
# - staging
#
# ========================================
# Actions:
# ========================================
# [1] Delete all fully merged branches
# [2] Review and delete individually
# [3] Handle stale branches
# [4] Show more details
# [5] Cancel
#
# Choice: 2
#
# Delete 'feature/user-auth'? (y/n/details)
# User: y
# ✓ Deleted feature/user-auth
#
# Delete 'bugfix/login-error'? (y/n/details)
# User: y
# ✓ Deleted bugfix/login-error
#
# ...
#
# Summary:
# ✓ Deleted 6 branches
# ✗ Skipped 2 branches
# ⚠ 3 stale branches need review
```
### Example 2: Batch Delete Merged Branches
```bash
/git:branch-cleanup local main
# Found 12 fully merged branches
# Show list? (y/n)
# User: y
#
# [Shows list of 12 branches...]
#
# Delete all? (y/n/select)
# User: y
#
# DRY-RUN: Would delete:
# feature/user-auth
# feature/api-v2
# bugfix/login-error
# ... (9 more)
#
# Proceed? (y/n)
# User: y
#
# Deleting branches...
# ✓ feature/user-auth
# ✓ feature/api-v2
# ✓ bugfix/login-error
# ...
#
# Deleted 12 branches successfully
```
### Example 3: Remote Branch Cleanup
```bash
/git:branch-cleanup remote origin/main
# ⚠ REMOTE CLEANUP WARNING
# This will delete branches from origin
# Other developers may be affected
#
# Have you coordinated with your team? (y/n)
# User: y
#
# Analyzing remote branches...
#
# Merged remote branches (15):
# ------------------------------------------
# origin/feature/completed-feature-1
# origin/feature/completed-feature-2
# origin/bugfix/old-fix
# ... (12 more)
#
# Checking for open pull requests...
# ✓ No open PRs found for these branches
#
# Delete remote branches? (y/n)
# User: y
#
# Deleting remote branches...
# ✓ Deleted origin/feature/completed-feature-1
# ✓ Deleted origin/feature/completed-feature-2
# ...
#
# Pruning remote tracking branches...
# ✓ Pruned 15 remote tracking branches
#
# Summary:
# Deleted 15 remote branches
# Your local branches were not affected
```
### Example 4: Handle Stale Branches
```bash
/git:branch-cleanup local
# ...
# Stale Branches (4 branches):
# ------------------------------------------
#
# 1. feature/experimental-ui
# Last: 145 days ago by Alice Cooper
# NOT merged - 23 unique commits
# Show details? (y/n/delete/keep)
# User: y
#
# Branch details:
# Created: 2025-06-01
# Last commit: 2025-06-28
# Commits ahead: 23
# Commits behind: 127
#
# Recent commits:
# abc1234 - Experiment with new layout
# def5678 - Add animation effects
# ... (21 more)
#
# Action for this branch?
# [d] Delete (lose 23 commits)
# [k] Keep (skip)
# [t] Tag and delete (archive)
# [b] Create backup branch
# User: t
#
# Creating archive tag: archive/experimental-ui
# ✓ Tag created
# ✓ Branch deleted
#
# To restore: git checkout -b feature/experimental-ui archive/experimental-ui
```
### Example 5: Cleanup Both Local and Remote
```bash
/git:branch-cleanup both
# This will clean up both local and remote branches
# Base branch: main
#
# Phase 1: Local Analysis
# ========================================
# Fully merged: 8 branches
# Stale: 3 branches
#
# Phase 2: Remote Analysis
# ========================================
# Fully merged: 12 branches
# Stale: 5 branches
#
# Total branches to clean: 20
#
# Proceed with cleanup? (y/n/review)
# User: review
#
# [Shows detailed lists...]
#
# Start cleanup? (y/n)
# User: y
#
# Cleaning local branches...
# ✓ Deleted 8 local branches
#
# Cleaning remote branches...
# ⚠ This affects other developers!
# Continue? (y/n)
# User: y
#
# ✓ Deleted 12 remote branches
# ✓ Pruned remote tracking branches
#
# Total Summary:
# ✓ 8 local branches deleted
# ✓ 12 remote branches deleted
# ⚠ 8 stale branches need review
```
## Advanced Usage
### Archive Branches Before Deletion
```bash
# Create tags for branches before deleting
for branch in "${branches_to_delete[@]}"; do
git tag "archive/$branch" "$branch"
git branch -d "$branch"
done
# Push archive tags
git push origin --tags
# Later restore:
git checkout -b restored-branch archive/branch-name
```
### Export Branch List
```bash
# Save branch list before cleanup
git for-each-ref --format='%(refname:short) %(committerdate:iso8601) %(authorname)' refs/heads/ > branches-$(date +%Y%m%d).txt
```
### Filter by Author
```bash
# Find all branches by specific author
git for-each-ref --format='%(refname:short) %(authorname)' refs/heads/ | grep "John Doe"
# Delete branches by author
/git:branch-cleanup local --author="John Doe"
```
### Custom Stale Period
```bash
# Consider branches stale after 60 days instead of 90
/git:branch-cleanup local --stale-days=60
```
### Batch Operations with jq
```bash
# Get merged branches as JSON
git branch --merged main --format='%(refname:short)' | jq -R -s -c 'split("\n")[:-1]'
# Programmatic deletion
git branch --merged main --format='%(refname:short)' | grep -v "^main$" | xargs -n 1 git branch -d
```
## Tips for Maintaining Clean Branches
1. **Regular cleanup schedule:**
- Weekly: Review active branches
- Monthly: Clean up merged branches
- Quarterly: Review stale branches
- Set calendar reminders
2. **Branch naming conventions:**
- Use prefixes: feature/, bugfix/, hotfix/
- Include ticket numbers: feature/JIRA-123-description
- Makes it easier to identify purpose
3. **Delete after merge:**
- Delete branches immediately after PR merge
- GitHub/GitLab can auto-delete
- Don't let branches accumulate
4. **Protected branch policies:**
- Configure protected branches in repo settings
- Prevent accidental deletion
- Require PR reviews
5. **Team communication:**
- Announce before remote cleanup
- Check with team before deleting shared branches
- Use Slack/Teams to coordinate
6. **Branch limits:**
- Keep total branches under 50
- If more, time for cleanup
- Too many branches = confusion
## Related Commands
- `/git:worktree` - Use worktrees instead of branches for parallel work
- `/git:cherry-pick-helper` - Cherry-pick commits before deleting branch
- `/git:reflog-recover` - Recover accidentally deleted branches
- `/git:rebase-interactive` - Clean up commits before merging

View File

@@ -0,0 +1,745 @@
---
name: git:cherry-pick-helper
description: Guided cherry-pick workflow with conflict resolution assistance for selectively applying commits across branches
---
# Git Cherry-Pick Helper - Guided Commit Selection
Guided cherry-pick workflow with conflict resolution assistance for selectively applying commits across branches.
## Command
`/git:cherry-pick-helper <commit-ref> [additional-refs...]`
## Arguments
- `$1`: commit-ref - Commit hash or reference to cherry-pick (required)
- `$2+`: additional-refs - Additional commits to cherry-pick (optional, space-separated)
## Description
Cherry-picking allows you to apply specific commits from one branch to another without merging the entire branch. This is useful for backporting bug fixes, applying specific features, or selectively moving work between branches.
## When to Use Cherry-Pick
- Backport bug fix to release branch
- Apply hotfix from main to feature branch
- Move specific commits to different branch
- Recover commits from deleted branch
- Apply commits from someone else's branch
- Split work from one branch to multiple
- Test specific changes in isolation
## When NOT to Use Cherry-Pick
- Can merge entire branch (use merge instead)
- Commits depend on other commits not being picked
- Would create duplicate history (rebase better)
- On public/shared branches (coordinate with team)
- Just testing changes (use worktree or stash)
## Workflow
### Pre-Cherry-Pick Analysis
1. **Validate commit reference:**
- Check commit exists
- Verify commit is reachable
- Can be from any branch or remote
2. **Show commit details:**
```bash
git show --stat <commit-ref>
```
Display:
- Commit hash (full and short)
- Author and date
- Commit message
- Files changed with stats
- Number of insertions/deletions
3. **Analyze commit context:**
- Show parent commits
- Check if part of merge commit
- Identify dependencies
- Warn about potential issues
4. **Check current branch:**
- Show current branch name
- Verify branch is clean
- Check for uncommitted changes
- Show last commit on current branch
5. **Predict conflicts:**
- Compare files in commit with current branch
- Check if same files modified
- Show potential conflict files
- Estimate conflict probability
### Confirmation
6. **Show cherry-pick plan:**
```
Cherry-Pick Plan:
========================================
Target Branch: feature-auth
Source Commit: abc1234 from main
Commit Details:
- Author: John Doe
- Date: 2025-10-20
- Message: Fix authentication token validation
Files to Apply:
- src/auth/token.js (+15, -8)
- src/auth/session.js (+7, -3)
- tests/auth/token.test.js (+45, -0)
Potential Issues:
⚠ src/auth/token.js was modified in this branch
✓ Other files should apply cleanly
Continue? (y/n/details)
```
7. **Offer options:**
- Proceed with cherry-pick
- Show detailed diff first
- Show file-by-file changes
- Cancel operation
### Execute Cherry-Pick
8. **Perform cherry-pick:**
```bash
git cherry-pick <commit-ref>
```
9. **For multiple commits:**
```bash
git cherry-pick <ref1> <ref2> <ref3>
```
Or range:
```bash
git cherry-pick <start-ref>^..<end-ref>
```
10. **Monitor progress:**
- Show which commit being applied
- Display progress for multiple picks
- Real-time status updates
### Success Case
11. **If cherry-pick succeeds:**
- Show new commit hash
- Display commit message
- Show files changed
- Verify commit applied correctly
12. **Post-pick verification:**
- Show git log with new commit
- Display branch status
- Suggest running tests
- Offer to cherry-pick more commits
### Conflict Resolution
13. **If conflicts occur:**
- Stop cherry-pick process
- List conflicted files
- Show conflict markers
- Explain current state
14. **For each conflicted file:**
- Show conflict details:
```bash
git diff <file>
```
- Explain conflict sections:
- `<<<<<<< HEAD` - Current branch changes
- `=======` - Separator
- `>>>>>>> <commit>` - Cherry-picked changes
- Show full file context
15. **Resolution options:**
- Manually edit files
- Accept theirs (cherry-picked version)
- Accept ours (current version)
- Use merge tool
- Abort cherry-pick
16. **Guide through resolution:**
```
Conflict Resolution:
========================================
File: src/auth/token.js
Conflict:
<<<<<<< HEAD
function validateToken(token) {
return checkSignature(token);
}
=======
function validateToken(token) {
return checkSignature(token) && !isExpired(token);
}
>>>>>>> abc1234 Fix authentication token validation
Options:
1. Edit manually
2. Accept cherry-picked version (includes expiry check)
3. Accept current version (no expiry check)
4. Show more context
5. Use merge tool
Choice: 2
Accepting cherry-picked version...
```
17. **After resolving each file:**
- Stage resolved file
- Show remaining conflicts
- Continue when all resolved
18. **Complete cherry-pick:**
```bash
git add <resolved-files>
git cherry-pick --continue
```
### Abort or Skip
19. **Abort cherry-pick:**
```bash
git cherry-pick --abort
```
- Returns to state before cherry-pick
- No changes applied
- Safe to retry
20. **Skip commit:**
```bash
git cherry-pick --skip
```
- Skip current commit
- Continue with remaining commits
- Use when commit not needed
### Multiple Commits
21. **For cherry-pick sequence:**
- Apply commits in order
- Pause at conflicts
- Resume after resolution
- Track progress through list
22. **Show sequence progress:**
```
Cherry-Pick Sequence:
========================================
Total: 5 commits
Progress: 3/5
✓ abc1234 - Fix token validation
✓ def5678 - Add session timeout
→ ghi9012 - Update user model [CONFLICT]
⋯ jkl3456 - Add tests
⋯ mno7890 - Update docs
Current: ghi9012
Resolve conflicts then continue
```
## Safety Checks
### Before Cherry-Pick
- **Clean working directory:**
```bash
if [ -n "$(git status --porcelain)" ]; then
echo "Error: Working directory has uncommitted changes"
echo ""
git status --short
echo ""
echo "Cherry-pick requires clean working directory"
echo "Options:"
echo " 1. Commit changes: git commit"
echo " 2. Stash changes: git stash"
echo " 3. Discard changes: git restore ."
exit 1
fi
```
- **Commit exists:**
```bash
if ! git cat-file -e "$commit_ref" 2>/dev/null; then
echo "Error: Commit not found: $commit_ref"
echo ""
echo "Make sure commit exists in repository"
echo "Try:"
echo " git fetch --all # Update remote branches"
echo " git log --all --oneline | grep <search>"
exit 1
fi
```
- **Not a merge commit:**
```bash
parent_count=$(git rev-list --parents -n1 "$commit_ref" | wc -w)
if [ $parent_count -gt 2 ]; then
echo "Warning: This is a merge commit"
echo "Merge commits: $(($parent_count - 1)) parents"
echo ""
echo "Cherry-picking merge commits is complex"
echo "You must specify which parent to use:"
echo " git cherry-pick -m 1 $commit_ref # Use first parent"
echo " git cherry-pick -m 2 $commit_ref # Use second parent"
echo ""
echo "Continue anyway? (y/n)"
read confirm
[ "$confirm" != "y" ] && exit 0
fi
```
- **Commit not already applied:**
```bash
# Check if commit already in current branch
if git log --format=%H | grep -q "$(git rev-parse $commit_ref)"; then
echo "Warning: This commit already exists in current branch"
echo "Commit: $commit_ref"
echo ""
echo "Cherry-picking will create duplicate commit"
echo "Continue? (y/n)"
read confirm
[ "$confirm" != "y" ] && exit 0
fi
```
### During Cherry-Pick
- **Conflict detection:**
```bash
if git cherry-pick "$commit_ref" 2>&1 | grep -q "CONFLICT"; then
echo "Conflict detected!"
echo ""
echo "Conflicted files:"
git diff --name-only --diff-filter=U
echo ""
echo "Use cherry-pick helper to resolve"
# Enter conflict resolution mode
fi
```
- **Cherry-pick in progress:**
```bash
if [ -f ".git/CHERRY_PICK_HEAD" ]; then
echo "Cherry-pick in progress"
echo ""
echo "Status:"
git status
echo ""
echo "Options:"
echo " 1. Continue: Resolve conflicts and git cherry-pick --continue"
echo " 2. Abort: git cherry-pick --abort"
echo " 3. Skip: git cherry-pick --skip"
exit 1
fi
```
### After Cherry-Pick
- **Verify changes:**
```bash
echo "Cherry-pick complete!"
echo ""
echo "New commit: $(git rev-parse HEAD)"
echo "Original commit: $commit_ref"
echo ""
echo "Verify changes:"
git show --stat HEAD
echo ""
echo "Test your changes before pushing"
```
- **Check for semantic conflicts:**
```bash
echo "⚠ Cherry-pick succeeded, but..."
echo "Check for semantic conflicts:"
echo " - Function signatures changed?"
echo " - Dependencies missing?"
echo " - Tests still pass?"
echo ""
echo "Run tests:"
echo " npm test"
echo " pytest"
echo " cargo test"
```
## Error Handling
### Commit Not Found
```bash
if ! git cat-file -e "$commit_ref" 2>/dev/null; then
echo "Error: Commit not found: $commit_ref"
echo ""
echo "Possible reasons:"
echo " - Typo in commit hash"
echo " - Commit in different repository"
echo " - Need to fetch from remote"
echo ""
echo "Try:"
echo " git fetch --all"
echo " git log --all --oneline | grep <keyword>"
exit 1
fi
```
### Cherry-Pick Failed
```bash
if ! git cherry-pick "$commit_ref"; then
error_type=$(git status | grep -o "both modified\|deleted by\|added by")
case "$error_type" in
"both modified")
echo "Conflict: File modified in both branches"
;;
"deleted by")
echo "Conflict: File deleted in one branch, modified in other"
;;
"added by")
echo "Conflict: File added with different content"
;;
esac
echo ""
echo "Resolution needed for:"
git diff --name-only --diff-filter=U
exit 1
fi
```
### Empty Cherry-Pick
```bash
if git cherry-pick "$commit_ref" 2>&1 | grep -q "nothing to commit"; then
echo "Cherry-pick resulted in no changes"
echo ""
echo "This means:"
echo " - Changes already exist in current branch"
echo " - Commit was effectively empty"
echo " - Changes were already reverted"
echo ""
echo "Options:"
echo " 1. Skip: git cherry-pick --skip"
echo " 2. Abort: git cherry-pick --abort"
exit 1
fi
```
## Examples
### Example 1: Cherry-Pick Single Commit
```bash
/git:cherry-pick-helper abc1234
# Analyzing commit abc1234...
#
# Commit Details:
# ========================================
# Hash: abc1234567890abcdef
# Author: John Doe <john@example.com>
# Date: Mon Oct 16 14:30:00 2025 -0700
# Branch: main
#
# Message:
# Fix authentication token validation bug
#
# Added expiry check to prevent expired tokens
# from being accepted.
#
# Files Changed (3):
# src/auth/token.js | 15 ++++++++----
# src/auth/session.js | 7 +++--
# tests/auth/token.test.js | 45 +++++++++++++++++++++++++++++++
#
# Current Branch: feature-auth
# Last Commit: def5678 Implement OAuth
#
# Conflict Check:
# ⚠ Potential conflict: src/auth/token.js
# (modified in both branches)
# ✓ Other files should apply cleanly
#
# Proceed with cherry-pick? (y/n/details)
# User: y
#
# Cherry-picking abc1234...
# Conflict in src/auth/token.js
#
# [Enters conflict resolution mode]
# ...
# [After resolution]
#
# ✓ Cherry-pick complete!
# New commit: xyz9876
# Changes applied to feature-auth branch
```
### Example 2: Cherry-Pick Multiple Commits
```bash
/git:cherry-pick-helper abc1234 def5678 ghi9012
# Cherry-Pick Sequence:
# ========================================
# 3 commits to apply
#
# 1. abc1234 - Fix token validation
# 2. def5678 - Add session timeout
# 3. ghi9012 - Update user model
#
# Source: main
# Target: feature-auth (current)
#
# Proceed? (y/n)
# User: y
#
# [1/3] Cherry-picking abc1234...
# ✓ Success (commit: aaa1111)
#
# [2/3] Cherry-picking def5678...
# ✓ Success (commit: bbb2222)
#
# [3/3] Cherry-picking ghi9012...
# ⚠ Conflict in src/models/user.js
#
# Resolve conflict and continue? (y/abort)
# User: y
#
# [Shows conflict resolution UI]
# ...
# [After resolution]
#
# ✓ All commits cherry-picked successfully!
# Applied 3 commits to feature-auth
```
### Example 3: Cherry-Pick Range
```bash
/git:cherry-pick-helper abc1234^..def5678
# Cherry-Pick Range:
# ========================================
# From: abc1234 (inclusive)
# To: def5678 (inclusive)
# Count: 8 commits
#
# Commits:
# abc1234 - Fix token validation
# bcd2345 - Add session timeout
# cde3456 - Update user model
# def4567 - Add password reset
# efg5678 - Implement 2FA
# fgh6789 - Add audit logging
# ghi7890 - Update dependencies
# def5678 - Add tests
#
# Apply all 8 commits? (y/n/select)
# User: select
#
# Select commits to cherry-pick (1-8, comma separated):
# User: 1,2,4,5
#
# Will cherry-pick:
# abc1234 - Fix token validation
# bcd2345 - Add session timeout
# def4567 - Add password reset
# efg5678 - Implement 2FA
#
# Proceed? (y/n)
# User: y
#
# [Applies selected commits...]
```
### Example 4: Conflict Resolution
```bash
/git:cherry-pick-helper abc1234
# ...
# Conflict in src/auth/token.js
#
# ========================================
# Conflict Resolution Helper
# ========================================
#
# File: src/auth/token.js
# Conflict type: Both modified
#
# Your version (HEAD):
# ----------------------------------------
# function validateToken(token) {
# if (!token) return false;
# return checkSignature(token);
# }
#
# Cherry-picked version (abc1234):
# ----------------------------------------
# function validateToken(token) {
# if (!token) return false;
# return checkSignature(token) && !isExpired(token);
# }
#
# What changed:
# + Added expiry check: !isExpired(token)
#
# Options:
# 1. Accept cherry-picked version (includes expiry check)
# 2. Accept current version (no expiry check)
# 3. Edit manually
# 4. Show full file context
# 5. Abort cherry-pick
#
# Choice: 1
#
# Accepting cherry-picked version...
# ✓ File resolved
#
# All conflicts resolved
# Continuing cherry-pick...
# ✓ Complete!
```
### Example 5: Cherry-Pick from Remote Branch
```bash
# Fetch latest
git fetch origin
# Cherry-pick from remote
/git:cherry-pick-helper origin/hotfix/security-patch
# Notice: This is a branch reference
# Will cherry-pick the tip of: origin/hotfix/security-patch
#
# Commit: abc1234 (HEAD of origin/hotfix/security-patch)
# Message: Fix XSS vulnerability in user input
#
# Proceed? (y/n)
# User: y
#
# ✓ Cherry-picked to current branch
```
## Advanced Usage
### Cherry-Pick Without Commit
```bash
# Apply changes but don't commit
git cherry-pick -n <commit>
# Or: --no-commit
git cherry-pick --no-commit <commit>
# Useful for:
# - Modifying changes before committing
# - Combining multiple cherry-picks
# - Testing changes first
```
### Cherry-Pick Merge Commit
```bash
# Specify which parent to use
git cherry-pick -m 1 <merge-commit>
# -m 1: Use first parent (usually main branch)
# -m 2: Use second parent (usually feature branch)
```
### Cherry-Pick with Modified Message
```bash
# Edit commit message during cherry-pick
git cherry-pick -e <commit>
# Or: --edit
git cherry-pick --edit <commit>
# Useful for:
# - Adding context about cherry-pick
# - Changing references (ticket numbers)
# - Adding "cherry-picked from" note
```
### Cherry-Pick Specific Files Only
```bash
# Cherry-pick changes to specific files only
git show <commit>:<file> > <file>
git add <file>
git commit -m "Cherry-picked changes from <commit>"
# Or more elegantly:
git checkout <commit> -- <file>
git commit -m "Cherry-picked <file> from <commit>"
```
### Interactive Cherry-Pick
```bash
# Cherry-pick with interactive conflict resolution
git cherry-pick <commit>
# If conflict:
git mergetool # Opens configured merge tool
git cherry-pick --continue
```
## Tips for Effective Cherry-Picking
1. **Understand commit dependencies:**
- Check if commit depends on previous commits
- May need to cherry-pick multiple commits
- Review commit history before picking
2. **Test after cherry-pick:**
- Always run tests
- Check for semantic conflicts
- Verify functionality works
3. **Update commit message:**
- Note that commit was cherry-picked
- Update references (ticket numbers)
- Add context for target branch
4. **Avoid cherry-pick for:**
- Large features (use merge)
- Long commit sequences (use rebase)
- Entire branches (use merge)
5. **Team coordination:**
- Communicate cherry-picks to team
- Document in PR/commit message
- Update tracking systems
6. **Cherry-pick vs Merge:**
- Cherry-pick: Select specific commits
- Merge: Bring entire branch history
- Choose based on need
## Related Commands
- `/git:reflog-recover` - Recover from cherry-pick mistakes
- `/git:rebase-interactive` - Alternative for moving commits
- `/git:branch-cleanup` - Clean up after cherry-picking
- `/git:fixup` - Fix commits before cherry-picking

323
commands/commit.md Normal file
View File

@@ -0,0 +1,323 @@
---
name: git:commit
description: Git conventions and workflow guidelines using Conventional Commits
---
# Git Conventions and Workflow Guidelines
Guide Claude Code through creating properly formatted commit messages and following git best practices using Conventional Commits specification.
## Command
`/git:commit [type] [scope] [description]`
## Arguments
- `$1`: type - `feat|fix|docs|style|refactor|perf|test|chore|ci` (optional, interactive if not provided)
- `$2`: scope - Component or module name (optional)
- `$3`: description - Brief description in imperative mood (optional)
## Slash Command Usage Examples
### Interactive Mode (Recommended)
```bash
/git:commit
```
**What happens:**
1. Claude analyzes staged changes using `git diff --cached`
2. Asks you what type of change this is (feat, fix, docs, etc.)
3. Asks for the scope (optional)
4. Asks for a description or suggests one based on the changes
5. Generates a properly formatted commit message
6. Shows you the message and asks for confirmation
7. Creates the commit with the approved message
### Quick Mode with Arguments
```bash
# Feature with scope
/git:commit feat auth "add JWT authentication"
# Bug fix without scope
/git:commit fix "handle null response from server"
# Documentation update
/git:commit docs readme "update installation steps"
# Refactoring with scope
/git:commit refactor database "optimize query performance"
```
### Common Usage Patterns
```bash
# Let Claude analyze changes and suggest commit message
/git:commit
# Specify type, Claude suggests scope and description
/git:commit feat
# Specify type and scope, Claude suggests description
/git:commit fix api
```
## When to Use This Command
- Before committing changes to ensure proper message format
- When you want Claude to analyze your changes and suggest appropriate commit type
- When you need help writing clear, conventional commit messages
- When working on a project that requires Conventional Commits
- As a learning tool to understand Conventional Commits format
## Language Requirements
All git-related text MUST be written in English:
- Commit messages
- Branch names
- Pull request titles and descriptions
- Code review comments
- Issue titles and descriptions
## Commit Message Format
All commit messages MUST follow the [Conventional Commits](mdc:https:/www.conventionalcommits.org) specification:
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
### Types
- `feat`: A new feature
- `fix`: A bug fix
- `docs`: Documentation only changes
- `style`: Changes that do not affect the meaning of the code (formatting, etc)
- `refactor`: A code change that neither fixes a bug nor adds a feature
- `perf`: A code change that improves performance
- `test`: Adding missing tests or correcting existing tests
- `chore`: Changes to the build process or auxiliary tools
- `ci`: Changes to CI configuration files and scripts
### Scope
The scope should be the name of the component affected (as perceived by the person reading the changelog).
Examples:
- `feat(auth): add login with Google`
- `fix(api): handle null response from server`
- `docs(readme): update installation steps`
### Description
- Use the imperative, present tense: "change" not "changed" nor "changes"
- Don't capitalize first letter
- No dot (.) at the end
- Write in english
## Branch Naming Convention
Branches should follow this pattern:
```
<type>/<short-description>
```
For features and fixes that are tracked in a project management system, include the ticket number:
```
<type>/<ticket-number>-<short-description>
```
Examples:
- `feat/add-google-auth`
- `fix/handle-null-responses`
- `docs/update-readme`
- `feat/PROJ-123-add-google-auth`
- `fix/PROJ-456-handle-null-responses`
## Workflow Guidelines
1. **Protected Branches**
- `main` (or `master`): Production-ready code, protected branch
- Direct commits to protected branches are NOT allowed
- All changes must come through Pull Requests
2. **Feature Development**
```bash
# First, check if you're on a protected branch
git branch --show-current
# If on main/master, create and checkout a new feature branch
git checkout -b feat/my-new-feature main
# Make changes and commit
git add .
git commit -m "feat(scope): add new feature"
# Keep branch updated with main
git fetch origin main
git rebase origin/main
# Push changes
git push origin feat/my-new-feature
```
3. **Pull Request Process**
- Create PR from feature branch to main/master
- Use PR template if available
- Request at least 2 code reviews
- All tests must pass
- No merge conflicts
- Squash commits when merging
4. **Release Process**
```bash
# Create release branch from main
git checkout main
git pull origin main
git checkout -b release/v1.0.0
# After testing, merge back to main via PR
# After PR is approved and merged:
git checkout main
git pull origin main
git tag -a v1.0.0 -m "version 1.0.0"
git push origin main --tags
```
## Examples
✅ Good Commits:
```bash
feat(auth): implement JWT authentication
fix(api): handle edge case in user validation
docs(api): update API documentation
style(components): format according to style guide
refactor(database): optimize query performance
test(auth): add unit tests for login flow
```
❌ Bad Commits:
```bash
Fixed stuff
Updated code
WIP
Quick fix
```
## Implementation Workflow
When `/git:commit` is invoked, follow these steps:
### Step 1: Analyze Current State
1. **Check for staged changes:**
```bash
git diff --cached --stat
```
- If no staged changes, inform user and suggest: `git add <files>`
- Show summary of what will be committed
2. **Check current branch:**
```bash
git branch --show-current
```
- If on protected branch (main/master), warn user strongly
- Suggest creating a feature branch instead
### Step 2: Determine Commit Type
If type not provided as argument:
1. Analyze the changes with `git diff --cached`
2. Categorize based on file types and changes:
- New files in `/features/`, new functions → likely `feat`
- Changes in test files → likely `test`
- Changes in README, docs/ → likely `docs`
- Bug fixes, error handling → likely `fix`
- Code cleanup, no behavior change → likely `refactor`
3. Suggest the most appropriate type to user
4. Ask user to confirm or choose different type
### Step 3: Determine Scope
If scope not provided:
1. Look at file paths to identify component/module
2. Common patterns:
- `src/auth/*` → scope: `auth`
- `src/api/*` → scope: `api`
- `docs/*` → scope: `docs` or specific doc name
- Multiple components → ask user or use general scope
3. Suggest scope or ask user
4. Scope is optional - allow user to skip
### Step 4: Create Description
If description not provided:
1. Analyze `git diff --cached` for key changes
2. Generate 2-3 description suggestions following rules:
- Use imperative mood ("add" not "added" or "adds")
- Start with lowercase
- No period at end
- Be specific but concise (max 50 chars for subject)
3. Present suggestions to user
4. Allow user to choose or provide their own
### Step 5: Build Complete Message
1. Format as: `<type>(<scope>): <description>`
2. If changes are complex, ask if user wants to add body
3. For breaking changes, remind about `BREAKING CHANGE:` footer
4. Show complete formatted message to user
### Step 6: Commit with Message
1. Show the final commit command:
```bash
git commit -m "type(scope): description"
```
2. Ask for confirmation
3. Execute the commit
4. Show commit hash and summary
5. Remind about push if needed: `git push origin <branch>`
### Step 7: Additional Guidance
After successful commit:
- Remind about related commits that should be squashed
- Suggest creating PR if feature is complete
- Remind about conventional commit benefits for changelog generation
## Pre-commit Hooks
Consider using pre-commit hooks to enforce these conventions:
- Commit message format validation
- Code linting
- Test execution
- Branch naming validation
- Protected branch validation
## Additional Notes
Avoid adding Claude as a co-author, while I understand that Claude wants recognition it's not always accurate that
Claude has in any way contributed as a co-author beyond writing the commit message that this command is used for. If
it's felt that Claude deserves to be listed as a co-author in the commit message it should be presented as an option
before adding.

721
commands/fixup.md Normal file
View File

@@ -0,0 +1,721 @@
---
name: git:fixup
description: Create and autosquash fixup commits during interactive rebase
---
# Git Fixup - Create and Autosquash Fixup Commits
Create fixup commits and automatically squash them into the appropriate target commit during interactive rebase.
## Command
`/git:fixup [target-commit-ref] [operation]`
## Arguments
- `$1`: target-commit-ref - The commit to fix (optional, interactive if not provided)
- `$2`: operation - `fixup|squash|amend` (default: `fixup`)
## Description
During development, you often discover small issues in earlier commits: typos, missing files, formatting errors, or small bugs. Instead of creating "Fix typo" commits that clutter history, use fixup commits. These are special commits that git can automatically squash into their target commits during rebase, keeping history clean.
## Fixup vs Squash vs Amend
- **Fixup** (`--fixup`): Combine commits, discard fixup message
- Use for: Bug fixes, typos, forgotten files
- Result: Target commit with original message
- Fixup message is discarded
- **Squash** (`--squash`): Combine commits, keep both messages
- Use for: Additional context, related changes
- Result: Combined commit with both messages
- Squash message is appended
- **Amend**: Modify the most recent commit
- Use for: Just committed, need immediate change
- Result: Replaces last commit
- Simpler than fixup for HEAD
## When to Use Fixup Commits
- Found a typo in an earlier commit
- Forgot to include a file
- Need to adjust formatting
- Small bug fix related to earlier commit
- Forgot to update tests with implementation
- Code review feedback for specific commit
- Want clean history before PR merge
## When NOT to Use Fixup
- Commits already pushed to shared branch (main/master)
- Significant new functionality (make normal commit)
- Unrelated changes (separate commit)
- Not sure which commit to fix (refactor instead)
- Commits are from other developers (discuss first)
## Workflow
### Interactive Fixup Mode
1. **Show recent commits:**
- Display last 15-20 commits
- Number them for easy reference
- Show commit hash, message, author, date
- Highlight potential fixup targets
```
Recent Commits:
========================================
1. abc1234 (HEAD) Add user dashboard
2. def5678 Implement user authentication
3. ghi9012 Add user model
4. jkl3456 Update database schema
5. mno7890 Add logging middleware
...
```
2. **Ask which commit needs fixing:**
- User selects by number or hash
- Show commit details
- Show files changed in that commit
- Confirm this is correct target
3. **Check current changes:**
- Show staged changes
- Show unstaged changes
- If no changes staged, prompt to stage files
- Offer interactive staging
4. **Create fixup commit:**
```bash
git commit --fixup=<target-commit>
```
This creates a commit with message:
```
fixup! Original commit message
```
5. **Offer immediate rebase:**
- Ask if user wants to autosquash now
- Or wait and accumulate more fixups
- Show rebase command for later
6. **If rebasing now:**
- Calculate base commit (parent of oldest fixup target)
- Run interactive rebase with autosquash
- Guide through any conflicts
- Verify result
### Direct Fixup Mode
7. **With target specified:**
- Validate target commit exists
- Validate target is not pushed
- Check staged changes
- Create fixup commit immediately
8. **Show result:**
- Display fixup commit created
- Show commit hash and message
- Remind about rebase command
- Offer to rebase now
### Squash Mode (Alternative)
9. **For squash commits:**
- Similar to fixup but keeps message
- Ask for additional commit message
- Useful when adding context
- Message will be combined with target
```bash
git commit --squash=<target-commit>
```
### Amend Mode (HEAD only)
10. **For amending HEAD:**
- Quick path for most recent commit
- Stage changes
- Amend directly:
```bash
git commit --amend --no-edit
```
- Or edit message:
```bash
git commit --amend
```
### Autosquash Rebase
11. **Calculate rebase range:**
- Find all fixup commits
- Find oldest fixup target
- Set base as parent of oldest target
- Show commits that will be rebased
12. **Run autosquash rebase:**
```bash
git rebase -i --autosquash <base-commit>
```
Git automatically reorders commits:
```
pick abc1234 Add feature X
fixup def5678 fixup! Add feature X
pick ghi9012 Add feature Y
squash jkl3456 squash! Add feature Y
```
13. **Handle conflicts:**
- If conflicts occur, guide resolution
- Show which fixup is being applied
- Offer to skip or abort
- Continue after resolution
14. **Verify result:**
- Show new commit history
- Verify fixup commits are gone
- Verify target commits updated
- Run tests if available
## Safety Checks
### Before Creating Fixup
- **Staged changes required:**
```bash
if [ -z "$(git diff --cached --name-only)" ]; then
echo "No staged changes to fixup"
echo ""
echo "Stage changes first:"
echo " git add <files>"
echo " git add -p (interactive)"
echo ""
echo "Show unstaged changes? (y/n)"
# If yes: git diff
exit 1
fi
```
- **Target commit validation:**
```bash
if ! git rev-parse --verify "$target_commit" >/dev/null 2>&1; then
echo "Error: Invalid commit reference: $target_commit"
echo ""
echo "Valid references:"
echo " - Commit hash: abc1234"
echo " - Relative: HEAD~3, HEAD^^"
echo " - Branch: feature-branch"
exit 1
fi
```
- **Target commit is reachable:**
```bash
if ! git merge-base --is-ancestor "$target_commit" HEAD; then
echo "Error: Target commit is not an ancestor of HEAD"
echo "Target: $target_commit"
echo "HEAD: $(git rev-parse HEAD)"
echo ""
echo "Target must be in current branch history"
exit 1
fi
```
- **Target commit not pushed:**
```bash
if git branch -r --contains "$target_commit" | grep -q "origin/$(git branch --show-current)"; then
echo "Warning: Target commit is already pushed"
echo "Commit: $target_commit"
echo "Branch: $(git branch --show-current)"
echo ""
echo "Fixup will require force-push after rebase"
echo "This may affect other developers"
echo ""
echo "Continue? (y/n)"
read confirm
[ "$confirm" != "y" ] && exit 0
fi
```
### Before Rebase
- **Uncommitted changes check:**
```bash
if [ -n "$(git status --porcelain)" ]; then
echo "Error: You have uncommitted changes"
echo "Commit or stash them before rebasing"
git status --short
exit 1
fi
```
- **Show rebase plan:**
```bash
echo "Rebase Plan:"
echo "============"
echo "Base commit: $base_commit"
echo "Commits to rebase: $commit_count"
echo ""
echo "Fixup commits will be squashed:"
git log --oneline $base_commit..HEAD | grep "fixup!"
echo ""
echo "Target commits will be updated:"
# Show target commits
echo ""
echo "Proceed with rebase? (y/n)"
```
- **Backup branch:**
```bash
backup_branch="backup-$(git branch --show-current)-$(date +%s)"
git branch "$backup_branch"
echo "Created backup: $backup_branch"
echo "To restore: git reset --hard $backup_branch"
```
### During Rebase
- **Conflict guidance:**
```bash
if [ -f ".git/rebase-merge/git-rebase-todo" ]; then
echo "Rebase in progress - conflict detected"
echo ""
echo "Current operation:"
head -1 .git/rebase-merge/git-rebase-todo
echo ""
echo "Conflicted files:"
git diff --name-only --diff-filter=U
echo ""
echo "Resolve conflicts then:"
echo " git add <file>"
echo " git rebase --continue"
echo ""
echo "Or abort:"
echo " git rebase --abort"
fi
```
### After Rebase
- **Verify fixups applied:**
```bash
# Check no fixup commits remain
if git log --oneline $base_commit..HEAD | grep -q "fixup!"; then
echo "Warning: Some fixup commits remain"
git log --oneline $base_commit..HEAD | grep "fixup!"
echo ""
echo "This may indicate rebase issues"
else
echo "✓ All fixup commits successfully squashed"
fi
```
- **Force-push reminder:**
```bash
if [ -n "$(git log @{u}..HEAD 2>/dev/null)" ]; then
echo ""
echo "Commits have been rewritten"
echo "Push with: git push --force-with-lease"
echo ""
echo "⚠ Only force-push if:"
echo " - This is your feature branch"
echo " - No one else is working on it"
fi
```
## Error Handling
### No Staged Changes
```bash
if [ -z "$(git diff --cached --name-only)" ]; then
echo "Error: No staged changes for fixup commit"
echo ""
echo "You have unstaged changes:"
git diff --name-only
echo ""
echo "Stage changes:"
echo " git add <file> # Stage specific files"
echo " git add -p # Stage interactively"
echo " git add -A # Stage all changes"
exit 1
fi
```
### Target Commit Not Found
```bash
if ! git cat-file -e "$target_commit" 2>/dev/null; then
echo "Error: Commit not found: $target_commit"
echo ""
echo "Recent commits:"
git log --oneline -10
echo ""
echo "Use commit hash or relative reference (HEAD~3)"
exit 1
fi
```
### Autosquash Not Enabled
```bash
if ! git config --get rebase.autosquash | grep -q "true"; then
echo "Notice: autosquash is not enabled globally"
echo ""
echo "Autosquash will work for this command, but to enable globally:"
echo " git config --global rebase.autosquash true"
echo ""
echo "Continue? (y/n)"
fi
```
### Rebase Conflicts
```bash
if git rebase -i --autosquash $base_commit 2>&1 | grep -q "CONFLICT"; then
echo "Conflict during rebase!"
echo ""
echo "This happened while applying fixup commit"
echo "The fixup changes conflict with intervening commits"
echo ""
echo "Options:"
echo " 1. Resolve conflicts:"
echo " - Edit conflicted files"
echo " - git add <file>"
echo " - git rebase --continue"
echo " 2. Skip this fixup:"
echo " git rebase --skip"
echo " 3. Abort rebase:"
echo " git rebase --abort"
exit 1
fi
```
## Examples
### Example 1: Interactive Fixup
```bash
/git:fixup
# Recent Commits:
# ========================================
# 1. abc1234 (HEAD) Add tests for auth module
# 2. def5678 Update documentation
# 3. ghi9012 Implement user authentication
# 4. jkl3456 Add user model
# 5. mno7890 Setup database connection
#
# Which commit needs fixing? (number or hash)
# User: 3
#
# Target commit:
# ghi9012 - Implement user authentication
# Author: John Doe
# Date: 2025-10-20 14:30:00
#
# Files changed:
# M src/auth.js
# M src/session.js
# A src/token.js
#
# Correct? (y/n)
# User: y
#
# Staged changes:
# M src/auth.js (Fixed token validation bug)
#
# Create fixup commit? (y/n)
# User: y
#
# ✓ Created fixup commit: 9876abc
# fixup! Implement user authentication
#
# Autosquash now? (y/n/later)
# User: now
#
# Running: git rebase -i --autosquash ghi9012^
# Rebasing... Success!
#
# Result:
# ghi9012 - Implement user authentication (updated)
# abc1234 - Add tests for auth module
#
# ✓ Fixup commit squashed into target
# ✓ History is clean
```
### Example 2: Quick Fixup by Hash
```bash
# Stage fix
git add src/auth.js
# Create fixup
/git:fixup def5678
# Target commit: def5678 - Implement user authentication
# Staged changes: src/auth.js
#
# Create fixup commit? (y/n)
# User: y
#
# ✓ Created fixup commit
#
# To autosquash:
# git rebase -i --autosquash def5678^
#
# Or run:
# /git:fixup def5678 rebase
```
### Example 3: Multiple Fixups Before Rebase
```bash
# Found typo in commit abc1234
git add README.md
/git:fixup abc1234
# Later: Found bug in commit def5678
git add src/bug.js
/git:fixup def5678
# Later: Found another issue in abc1234
git add src/auth.js
/git:fixup abc1234
# Now have multiple fixup commits
git log --oneline
# 9999999 fixup! Implement user authentication (2nd fixup)
# 8888888 fixup! Add user model
# 7777777 fixup! Implement user authentication (1st fixup)
# def5678 Add user model
# abc1234 Implement user authentication
# ...
# Rebase once to apply all fixups
/git:fixup rebase
# Result: All fixup commits squashed into targets
# def5678 Add user model (updated)
# abc1234 Implement user authentication (updated with both fixups)
```
### Example 4: Squash with Message
```bash
/git:fixup ghi9012 squash
# Target: ghi9012 - Implement user authentication
#
# Squash keeps commit message
# Enter additional message for squash commit:
# User: "Add rate limiting to prevent brute force attacks"
#
# ✓ Created squash commit
# squash! Implement user authentication
#
# When rebased, both messages will be combined:
# Implement user authentication
#
# Add rate limiting to prevent brute force attacks
```
### Example 5: Amend HEAD
```bash
# Just made a commit, forgot a file
/git:fixup HEAD amend
# Or simpler:
/git:fixup amend
# Staged changes: src/forgotten-file.js
#
# Amend previous commit? (y/n)
# User: y
#
# ✓ Amended HEAD commit
# Previous: abc1234
# New: abc5678
#
# Note: Commit hash changed (rewritten)
```
### Example 6: Fixup with Interactive Staging
```bash
/git:fixup
# No staged changes
# Unstaged changes:
# M src/auth.js (5 hunks)
# M src/session.js (3 hunks)
# M tests/auth.test.js (2 hunks)
#
# Stage changes interactively? (y/n)
# User: y
#
# Opening interactive staging...
# [User selects specific hunks]
#
# Staged for fixup:
# M src/auth.js (2 hunks - bug fix)
#
# Target commit for fixup? (1-10)
# [User selects commit]
#
# ✓ Created fixup commit
```
## Advanced Usage
### Configure Autosquash Globally
```bash
# Enable autosquash for all repos
git config --global rebase.autosquash true
# Now git rebase -i automatically uses --autosquash
```
### Fixup Specific Lines Only
```bash
# Stage specific lines interactively
git add -p src/auth.js
# Select only the hunks that fix the bug
# Create fixup with just those changes
/git:fixup abc1234
```
### Fixup Chain
```bash
# Create fixup for a fixup (rare but possible)
git commit --fixup=fixup!<original-commit>
# Creates:
# fixup! fixup! Original commit message
# All will squash into original during rebase
```
### Autosquash with Exec
```bash
# Run tests after each commit during autosquash
git rebase -i --autosquash --exec "npm test" origin/main
# Ensures each commit passes tests
# Useful for bisect-friendly history
```
### Fixup from Stash
```bash
# Have changes in stash
git stash show -p stash@{0}
# Apply and fixup
git stash pop
git add <files>
/git:fixup <target-commit>
```
## Workflow Integration
### With Pull Requests
```bash
# During code review, got feedback on specific commit
# Make fixes
git add <files>
git commit --fixup=<commit-from-pr>
# Before pushing PR update
git rebase -i --autosquash origin/main
git push --force-with-lease
# PR history is clean, reviewer sees clean commits
```
### With Feature Branch Development
```bash
# Day 1: Start feature
git commit -m "Add feature X"
# Day 2: Continue work
git commit -m "Add tests for feature X"
# Day 3: Found bug in day 1 commit
git add <fix>
git commit --fixup=<day-1-commit>
# Day 4: Ready to merge, clean up
git rebase -i --autosquash main
git push --force-with-lease
# Feature branch has clean history
```
### With Conventional Commits
```bash
# Original commit
git commit -m "feat: add user authentication"
# Later, found issue
git add <fix>
git commit --fixup=<feat-commit>
# After autosquash
# Result: "feat: add user authentication" (with fix included)
# Conventional commits format preserved
```
## Tips for Effective Fixup Usage
1. **Use fixup early and often:**
- Don't wait until PR review
- Fix issues as you find them
- Keep commits clean from the start
2. **Stage precisely:**
- Use `git add -p` for partial staging
- Only include changes related to fixup
- Don't mix unrelated fixes
3. **Descriptive staging messages:**
- When staging, note what's being fixed
- Helps remember why fixup was needed
- Use `git add -v` for verbose output
4. **Batch fixups before rebase:**
- Accumulate multiple fixup commits
- Rebase once to apply all
- More efficient than multiple rebases
5. **Test after autosquash:**
- Run tests after rebase
- Ensure fixups didn't break anything
- Verify each commit builds (if possible)
6. **Enable autosquash globally:**
- Set `rebase.autosquash = true`
- Makes workflow smoother
- Don't need --autosquash flag
## Related Commands
- `/git:rebase-interactive` - Manual rebase with full control
- `/git:cherry-pick-helper` - Alternative to fixup for specific changes
- `/git:branch-cleanup` - Clean up after merging fixed commits
- `/git:reflog-recover` - Recover from fixup/rebase mistakes

View File

@@ -0,0 +1,704 @@
---
name: git:rebase-interactive
description: Interactive rebase helper with guided workflows for squashing, reordering, editing, and splitting commits
---
# Git Interactive Rebase - Guided Commit History Editing
Interactive rebase helper with guided workflows for squashing, reordering, editing, and splitting commits.
## Command
`/git:rebase-interactive [base-ref] [operation]`
## Arguments
- `$1`: base-ref - Starting point for rebase (default: `origin/main` or `origin/master`)
- `$2`: operation - `squash|reorder|edit|split|drop` (optional, interactive if not provided)
## Description
Interactive rebase allows you to rewrite commit history by squashing commits together, reordering them, editing messages, splitting commits, or dropping unwanted commits. This is essential for maintaining a clean, logical commit history before merging to main branches.
## When to Use Interactive Rebase
- Clean up work-in-progress commits before creating PR
- Combine related commits into logical units
- Fix commit messages with typos or unclear descriptions
- Reorder commits to tell a better story
- Split large commits into smaller, focused ones
- Remove debug commits or experimental changes
- Prepare commits for code review
## When NOT to Use Interactive Rebase
- On commits already pushed to shared/public branches
- On merge commits (complex and dangerous)
- On commits other developers have based work on
- If you're unsure about what you're doing (use branches instead)
## Workflow
### Pre-rebase Checks
1. **Safety validation:**
- Check for uncommitted changes
- Verify not on main/master/protected branch
- Check if commits are already pushed
- Warn about force-push requirements
- Confirm user understands rebase implications
2. **Gather information:**
- Determine base commit (where to rebase from)
- Show commits that will be rebased
- Calculate number of commits
- Display commit graph for context
3. **Show commits to be rebased:**
```bash
git log --oneline --graph --decorate <base-ref>..HEAD
```
Display each commit:
- Commit hash (short)
- Commit message
- Author and date
- Files changed count
### Interactive Mode Selection
4. **Ask user what they want to do:**
- Squash commits (combine multiple commits)
- Reorder commits (change commit order)
- Edit commits (change messages or content)
- Split commits (break one commit into multiple)
- Drop commits (remove commits entirely)
- Custom (use full rebase TODO editor)
### Squash Operation
5. **For squashing commits:**
- Show all commits that will be rebased
- Number them for easy reference
- Ask which commits to squash together
- Ask for groups: "Commits 2,3,4 into 1" or "Last 3 commits"
- Confirm the squash plan
6. **Create rebase TODO list:**
```
pick abc1234 First commit (keep this)
squash def5678 Second commit (squash into above)
squash ghi9012 Third commit (squash into above)
pick jkl3456 Fourth commit (keep separate)
```
7. **Edit combined commit message:**
- Show all commit messages being combined
- Ask user to write new combined message
- Provide template with all original messages
- Suggest following conventional commits format
8. **Execute rebase:**
```bash
git rebase -i <base-ref>
```
9. **Handle result:**
- If successful: show new commit history
- If conflicts: guide through resolution
- Verify result matches intention
### Reorder Operation
10. **For reordering commits:**
- Show commits with numbers
- Current order: 1, 2, 3, 4, 5
- Ask for new order: "3, 1, 2, 4, 5" or "Move commit 3 before 1"
- Validate new order (all commits present, no duplicates)
- Show before/after preview
11. **Create rebase TODO list:**
```
pick ghi9012 Third commit (moved to first)
pick abc1234 First commit (now second)
pick def5678 Second commit (now third)
pick jkl3456 Fourth commit (unchanged)
```
12. **Execute and verify:**
- Run rebase with new order
- Check for conflicts (reordering can cause conflicts)
- Show resulting commit graph
- Verify logical order
### Edit Operation
13. **For editing commits:**
- Ask which commits to edit:
- Message only
- Content (files)
- Both
- Mark commits with 'edit' or 'reword'
- Explain what will happen
14. **Create rebase TODO list:**
```
pick abc1234 First commit
reword def5678 Second commit (will edit message)
edit ghi9012 Third commit (will edit content)
pick jkl3456 Fourth commit
```
15. **Execute rebase:**
- For 'reword': git opens editor for message
- For 'edit': rebase pauses at commit
- Show current state and next steps
- Guide through making changes
16. **At each 'edit' stop:**
- Show current commit
- Options:
- Amend commit: `git commit --amend`
- Add more changes: stage files and amend
- Continue: `git rebase --continue`
- Abort: `git rebase --abort`
### Split Operation
17. **For splitting commits:**
- Ask which commit to split
- Mark commit with 'edit'
- Explain split workflow
18. **At edit stop:**
```bash
# Reset to parent commit (keep changes unstaged)
git reset HEAD^
# Now stage and commit in smaller chunks
git add -p # Interactively stage hunks
git commit -m "First part"
git add ...
git commit -m "Second part"
# Continue rebase
git rebase --continue
```
19. **Guide through split:**
- Show all changed files
- Help user decide how to split
- Suggest logical groupings
- Create each new commit
- Verify all changes included
### Drop Operation
20. **For dropping commits:**
- Ask which commits to drop
- Show what will be removed
- Warn if commits introduce features used later
- Confirm deletion
21. **Create rebase TODO list:**
```
pick abc1234 First commit
drop def5678 Second commit (will be removed)
pick ghi9012 Third commit
```
22. **Execute and verify:**
- Run rebase
- Check for conflicts (dropped changes might be referenced)
- Verify feature still works without dropped commits
### Conflict Resolution
23. **If conflicts occur:**
- Pause rebase
- Show conflicting files
- Explain current state:
- Which commit being applied
- Why conflict occurred
- What needs resolution
24. **Guide through resolution:**
```bash
# Show conflicts
git status
# For each file
git diff <file>
# Options:
# 1. Manually edit files to resolve
# 2. Use mergetool: git mergetool
# 3. Accept theirs: git checkout --theirs <file>
# 4. Accept ours: git checkout --ours <file>
# 5. Skip commit: git rebase --skip
# 6. Abort rebase: git rebase --abort
```
25. **After resolving:**
```bash
git add <resolved-files>
git rebase --continue
```
26. **Continue until complete:**
- May have multiple conflicts
- Guide through each one
- Show progress: "Resolving 2 of 5 commits"
### Post-rebase Verification
27. **Verify rebase success:**
- Show new commit history
- Compare before/after
- Check that all intended changes present
- Verify tests still pass
28. **Force push considerations:**
- Explain why force-push needed
- Check if commits were pushed before
- Show safe force-push command:
```bash
git push --force-with-lease
```
- Warn about team coordination
## Safety Checks
### Before Rebase
- **Uncommitted changes:**
```bash
if [ -n "$(git status --porcelain)" ]; then
echo "Error: You have uncommitted changes"
echo "Please commit or stash them first:"
git status --short
exit 1
fi
```
- **Protected branch:**
```bash
current_branch=$(git branch --show-current)
if [[ "$current_branch" =~ ^(main|master|develop|production|staging)$ ]]; then
echo "Error: You are on protected branch: $current_branch"
echo "Interactive rebase is dangerous on shared branches"
echo "Create a feature branch instead:"
echo " git checkout -b fix/rebase-changes"
exit 1
fi
```
- **Already pushed:**
```bash
# Check if commits are pushed
if git log --oneline @{u}.. | grep -q .; then
echo "Warning: Some commits are not pushed yet (safe to rebase)"
else
echo "Warning: All commits are already pushed to remote"
echo ""
echo "Rebasing will require force-push: git push --force-with-lease"
echo "This can affect other developers who have pulled your branch"
echo ""
echo "Continue with rebase? (y/n)"
# Wait for confirmation
fi
```
- **Merge commits:**
```bash
merge_commits=$(git log --oneline --merges <base-ref>..HEAD | wc -l)
if [ $merge_commits -gt 0 ]; then
echo "Warning: This range contains $merge_commits merge commit(s)"
echo "Rebasing merge commits is complex and may lose merge resolution"
echo ""
git log --oneline --merges <base-ref>..HEAD
echo ""
echo "Consider these alternatives:"
echo " 1. Rebase only non-merge commits"
echo " 2. Use git filter-branch instead"
echo " 3. Manually rewrite history"
echo ""
echo "Continue anyway? (y/n)"
fi
```
### During Rebase
- **Conflict help:**
```bash
if [ -f ".git/rebase-merge/git-rebase-todo" ]; then
echo "Rebase in progress. Current state:"
echo ""
# Show progress
done_count=$(grep -c "^$" .git/rebase-merge/done 2>/dev/null || echo 0)
total_count=$(wc -l < .git/rebase-merge/git-rebase-todo)
echo "Progress: $done_count / $total_count commits"
# Show conflicts
if git status | grep -q "Unmerged paths"; then
echo ""
echo "Conflicted files:"
git diff --name-only --diff-filter=U
echo ""
echo "Resolve conflicts then:"
echo " git add <file>..."
echo " git rebase --continue"
echo ""
echo "Or abort:"
echo " git rebase --abort"
fi
fi
```
- **Backup before proceeding:**
```bash
# Create backup branch before risky operations
backup_branch="backup-$(git branch --show-current)-$(date +%s)"
git branch "$backup_branch"
echo "Created backup branch: $backup_branch"
echo "If something goes wrong: git reset --hard $backup_branch"
```
### After Rebase
- **Verify integrity:**
```bash
# Check that no commits were lost
echo "Verifying rebase result..."
# Compare file tree
git diff <original-head> HEAD
if [ -z "$(git diff <original-head> HEAD)" ]; then
echo "✓ Working tree identical (good)"
else
echo "⚠ Working tree differs:"
echo "This is expected if you edited commit content"
echo "Review changes:"
git diff --stat <original-head> HEAD
fi
# Run tests
echo ""
echo "Consider running tests to verify nothing broke:"
echo " npm test"
echo " pytest"
echo " cargo test"
```
- **Force-push guidance:**
```bash
echo ""
echo "To update remote branch:"
echo " git push --force-with-lease"
echo ""
echo "⚠ Only force-push if:"
echo " - You are the only one working on this branch"
echo " - Or: You've coordinated with team members"
echo " - Or: This is a personal feature branch"
echo ""
echo "Never force-push to: main, master, develop"
```
## Error Handling
### Invalid Base Reference
```bash
if ! git rev-parse --verify "$base_ref" >/dev/null 2>&1; then
echo "Error: Invalid base reference: $base_ref"
echo ""
echo "Valid references:"
echo " - Branch: main, develop, origin/main"
echo " - Commit: abc1234, HEAD~5"
echo " - Tag: v1.0.0"
echo ""
echo "To see available branches:"
echo " git branch -a"
exit 1
fi
```
### No Commits to Rebase
```bash
commit_count=$(git log --oneline $base_ref..HEAD | wc -l)
if [ $commit_count -eq 0 ]; then
echo "Error: No commits to rebase"
echo "Base: $base_ref"
echo "HEAD: $(git rev-parse HEAD)"
echo ""
echo "Your current branch is even with $base_ref"
echo "Make some commits first, or choose a different base"
exit 1
fi
```
### Rebase Already in Progress
```bash
if [ -d ".git/rebase-merge" ] || [ -d ".git/rebase-apply" ]; then
echo "Error: Rebase already in progress"
echo ""
echo "Options:"
echo " 1. Continue rebase: git rebase --continue"
echo " 2. Skip current commit: git rebase --skip"
echo " 3. Abort rebase: git rebase --abort"
echo ""
echo "Current status:"
git status
exit 1
fi
```
### Rebase Failed
```bash
# If git rebase command fails
if [ $? -ne 0 ]; then
echo "Rebase failed!"
echo ""
# Check for conflicts
if git status | grep -q "Unmerged paths"; then
echo "You have conflicts to resolve:"
git diff --name-only --diff-filter=U
echo ""
echo "Next steps:"
echo " 1. Resolve conflicts in each file"
echo " 2. Stage resolved files: git add <file>"
echo " 3. Continue: git rebase --continue"
echo ""
echo "Or abort and try different approach:"
echo " git rebase --abort"
else
echo "Unknown error occurred"
echo "Check: git status"
echo ""
echo "To abort and restore original state:"
echo " git rebase --abort"
fi
exit 1
fi
```
## Examples
### Example 1: Squash Last 3 Commits
```bash
/git:rebase-interactive HEAD~3 squash
# Claude shows:
# Commits to rebase:
# 1. abc1234 - Fix typo in README
# 2. def5678 - Add missing semicolon
# 3. ghi9012 - Update documentation
#
# Squash commits 1, 2, and 3 into one? (y/n)
# User: y
#
# Enter commit message for combined commit:
# User: "Improve documentation and fix typos"
#
# Rebasing...
# Success! New commit history:
# abc9999 - Improve documentation and fix typos
```
### Example 2: Reorder Commits
```bash
/git:rebase-interactive origin/main reorder
# Current commit order:
# 1. abc1234 - Add tests
# 2. def5678 - Implement feature
# 3. ghi9012 - Update dependencies
# 4. jkl3456 - Fix bug in feature
#
# Enter new order (e.g., "2,4,1,3"):
# User: 3,2,4,1
#
# New order will be:
# 1. ghi9012 - Update dependencies
# 2. def5678 - Implement feature
# 3. jkl3456 - Fix bug in feature
# 4. abc1234 - Add tests
#
# This tells a better story: deps first, then feature, fix, then tests
# Continue? (y/n)
# User: y
#
# Rebasing... Success!
```
### Example 3: Edit Commit Message
```bash
/git:rebase-interactive HEAD~5 edit
# Which commits to edit?
# 1. abc1234 - Fix stuff (message unclear)
# 2. def5678 - Add feature X
# 3. ghi9012 - Update readme
# 4. jkl3456 - wip (message unclear)
# 5. mno7890 - Refactor auth
#
# Enter commit numbers to edit: 1,4
#
# Rebasing to commit 1: abc1234
# Current message: "Fix stuff"
# Enter new message:
# User: "Fix authentication token validation bug"
#
# Rebasing to commit 4: jkl3456
# Current message: "wip"
# Enter new message:
# User: "Add user session timeout handling"
#
# Rebase complete! Updated 2 commit messages.
```
### Example 4: Split Commit
```bash
/git:rebase-interactive HEAD~3 split
# Which commit to split?
# 1. abc1234 - Add feature X and Y and fix bug Z
# 2. def5678 - Update tests
# 3. ghi9012 - Update docs
#
# User: 1
#
# Stopping at commit abc1234...
# This commit changed:
# src/featureX.js (45 additions)
# src/featureY.js (67 additions)
# src/bugfix.js (12 additions)
#
# Reset commit, keeping changes:
# Run: git reset HEAD^
#
# Now stage and commit in smaller pieces:
# git add src/featureX.js
# git commit -m "Add feature X"
#
# git add src/featureY.js
# git commit -m "Add feature Y"
#
# git add src/bugfix.js
# git commit -m "Fix bug Z"
#
# Then continue:
# git rebase --continue
```
### Example 5: Interactive Full Control
```bash
/git:rebase-interactive origin/main
# 15 commits to rebase from origin/main
# What do you want to do?
# 1. Squash commits
# 2. Reorder commits
# 3. Edit commit messages
# 4. Split commits
# 5. Drop commits
# 6. Custom (use full TODO editor)
#
# User: 6
#
# Opening rebase TODO editor...
# Edit instructions as needed:
#
# pick abc1234 First commit
# squash def5678 Second commit (squash into first)
# reword ghi9012 Third commit (edit message)
# edit jkl3456 Fourth commit (edit content)
# drop mno7890 Fifth commit (remove)
# pick pqr3456 Sixth commit
#
# Save and close to start rebase
```
## Advanced Usage
### Autosquash Workflow
```bash
# Make fixup commits during development
git commit --fixup=abc1234
# Later, autosquash all fixup commits
git rebase -i --autosquash origin/main
# Fixup commits automatically squashed into target commits
```
### Exec Commands
```bash
# Run command after each commit during rebase
git rebase -i --exec "npm test" origin/main
# Rebase will pause if any test fails
# Useful for ensuring each commit builds/passes tests
```
### Preserve Merges (Careful!)
```bash
# Preserve merge commits (advanced)
git rebase -i --rebase-merges origin/main
# Only use if you understand implications
# Usually better to avoid rebasing merges
```
## Tips for Clean Commit History
1. **Logical commits:**
- One feature/fix per commit
- Atomic: each commit should build and pass tests
- Related changes together
2. **Good commit messages:**
- Clear, descriptive summary line
- Body explains WHY, not what
- Reference issue numbers
- Follow conventional commits format
3. **Before creating PR:**
- Squash WIP commits
- Reorder for logical flow
- Fix commit messages
- Each commit tells part of the story
4. **Rebase strategies:**
- Rebase early and often on feature branches
- Keep commits organized from the start
- Use fixup commits during development
- Final cleanup before PR
5. **Team coordination:**
- Don't rebase shared branches
- Communicate before force-pushing
- Use --force-with-lease, never --force
- Consider rebasing only your commits
## Related Commands
- `/git:fixup` - Create fixup commits for autosquash
- `/git:branch-cleanup` - Clean up after rebasing
- `/git:cherry-pick-helper` - Alternative to rebase for specific commits
- `/git:reflog-recover` - Recover from rebase mistakes

774
commands/reflog-recover.md Normal file
View File

@@ -0,0 +1,774 @@
---
name: git:reflog-recover
description: Use reflog to recover lost commits, deleted branches, and resolve repository mistakes
---
# Git Reflog Recover - Lost Commit and Branch Recovery
Use reflog to recover lost commits, deleted branches, and resolve repository mistakes.
## Command
`/git:reflog-recover [search-term] [action]`
## Arguments
- `$1`: search-term - Text to search in reflog (optional, shows recent reflog if omitted)
- `$2`: action - `show|recover|create-branch` (default: `show`)
## Description
Git's reflog (reference log) tracks every change to branch tips and HEAD, even changes that "lose" commits like hard resets, branch deletions, or rebases. The reflog is your safety net for recovering from mistakes, finding lost work, and understanding repository history.
## What is Reflog?
The reflog records:
- Every commit
- Branch switches
- Resets (soft, mixed, hard)
- Rebases
- Merges
- Amends
- Cherry-picks
- Branch deletions
- Any HEAD movement
Each entry shows:
- Commit hash
- Previous HEAD position
- Action performed
- When it happened
**Important:** Reflog entries expire after ~90 days by default. Recovery is not possible after expiration.
## When to Use Reflog Recovery
- Accidentally deleted a branch
- Did `git reset --hard` and lost commits
- Messed up rebase and want to undo
- Amended commit but want old version
- Lost commits after force-push
- Want to see what you were working on
- Need to understand what happened
- Recover from any git mistake
## What Can Be Recovered
**Can Recover:**
- Committed changes (within ~90 days)
- Deleted branches (if committed)
- Reset commits
- Rebased commits (old versions)
- Amended commits (previous versions)
- Cherry-picked commits (originals)
**Cannot Recover:**
- Uncommitted changes (never committed)
- Changes that were never staged
- Expired reflog entries (>90 days old)
- Changes from other users' local repos
## Workflow
### Show Reflog
1. **Display recent reflog:**
```bash
git reflog show
```
Or with limits:
```bash
git reflog show -n 50
```
2. **Format reflog entries:**
- Show commit hash (short and full)
- Show reflog reference (HEAD@{n})
- Show action performed
- Show relative time (5 minutes ago, 2 days ago)
- Show commit message
```
Reflog Entries (Recent 30):
========================================
HEAD@{0} abc1234 commit: Add new feature
(5 minutes ago)
HEAD@{1} def5678 checkout: moving from main to feature-branch
(2 hours ago)
HEAD@{2} ghi9012 reset: moving to HEAD^
(3 hours ago) ⚠ RESET - Potential lost commits
HEAD@{3} jkl3456 commit (amend): Fix typo in commit message
(5 hours ago) ⚠ AMEND - Previous version available
HEAD@{4} mno7890 rebase -i (finish): refs/heads/feature
(1 day ago) ⚠ REBASE - Old commits available
```
3. **Highlight important entries:**
- Resets (potential lost work)
- Branch deletions
- Rebases (old history)
- Amends (previous versions)
- Force updates
4. **Categorize by action type:**
- Commits
- Checkouts (branch switches)
- Resets
- Rebases
- Merges
- Amendments
- Cherry-picks
### Search Reflog
5. **Search by term:**
```bash
git reflog | grep "<search-term>"
```
6. **Common searches:**
- Branch name: Find when branch was deleted
- Commit message keyword: Find specific work
- Date/time: Find what happened when
- Action type: Find all resets, rebases, etc.
7. **Show search results:**
- Matching entries highlighted
- Context before/after (adjacent entries)
- Grouped by relevance
- Sorted by time
### Recover Commits
8. **Select recovery target:**
- User picks reflog entry
- Show full commit details
- Show what will be recovered
- Explain recovery options
9. **Recovery options:**
**Option A: Create new branch**
```bash
git branch recovery-branch <commit-hash>
```
- Safest option
- Preserves current state
- Can review before merging
- Recommended for most cases
**Option B: Reset current branch**
```bash
git reset --hard <commit-hash>
```
- Moves current branch
- Loses commits after target
- Use with caution
- Create backup branch first
**Option C: Cherry-pick commit**
```bash
git cherry-pick <commit-hash>
```
- Apply specific commit
- Keep current history
- Good for selective recovery
**Option D: Merge recovered commit**
```bash
git branch temp-recovery <commit-hash>
git merge temp-recovery
```
- Merge lost work
- Preserves both histories
- Creates merge commit
10. **Execute recovery:**
- Perform chosen action
- Verify recovery successful
- Show resulting state
- Offer to continue recovering
### Create Branch from Reflog
11. **Branch creation workflow:**
- Ask for commit hash from reflog
- Validate commit exists
- Ask for branch name
- Create branch at commit
- Offer to switch to branch
12. **Execute:**
```bash
git branch <new-branch-name> <commit-hash>
```
13. **Verify:**
- Show branch created
- Show commit it points to
- Show how to access it
- Offer to checkout
### Show Specific Commit
14. **Display lost commit:**
```bash
git show <commit-hash>
```
15. **Show details:**
- Full commit message
- Author and date
- Files changed
- Full diff
- Parent commits
16. **Actions after showing:**
- Offer to recover
- Create branch
- Cherry-pick
- Export as patch
- Copy hash to clipboard
### Understand History
17. **Timeline visualization:**
- Show reflog as timeline
- Highlight branch points
- Show where mistakes happened
- Trace commit lineage
18. **Before/After comparison:**
- Show state before mistake
- Show state after mistake
- Show what was lost
- Show recovery path
## Safety Checks
### Before Recovery
- **Verify commit exists:**
```bash
if ! git cat-file -e "$commit_hash" 2>/dev/null; then
echo "Error: Commit not found: $commit_hash"
echo "It may have been garbage collected"
echo "Try: git fsck --lost-found"
exit 1
fi
```
- **Check current state:**
```bash
if [ -n "$(git status --porcelain)" ]; then
echo "Warning: You have uncommitted changes"
git status --short
echo ""
echo "Recovery operations may affect these changes"
echo "Commit or stash them first? (y/n/continue)"
fi
```
- **Create backup:**
```bash
current_branch=$(git branch --show-current)
backup_branch="backup-${current_branch}-$(date +%s)"
git branch "$backup_branch"
echo "Created backup branch: $backup_branch"
echo "To restore current state: git reset --hard $backup_branch"
```
### During Recovery
- **Confirm destructive operations:**
```bash
if [ "$action" = "reset" ]; then
echo "⚠ WARNING: git reset --hard is DESTRUCTIVE"
echo ""
echo "This will:"
echo " - Move current branch to: $commit_hash"
echo " - Discard all commits after target"
echo " - Lose uncommitted changes"
echo ""
echo "Backup created: $backup_branch"
echo ""
echo "Type 'RESET' to confirm: "
read confirmation
[ "$confirmation" != "RESET" ] && exit 0
fi
```
- **Verify commit is reachable:**
```bash
# Check commit is in reflog
if ! git reflog | grep -q "$commit_hash"; then
echo "Notice: Commit not in current branch's reflog"
echo "It may be from another branch or remote"
echo "Continue? (y/n)"
fi
```
### After Recovery
- **Verify recovery:**
```bash
echo "Recovery complete!"
echo ""
echo "Verification:"
echo " Recovered commit: $commit_hash"
echo " Current HEAD: $(git rev-parse HEAD)"
echo " Current branch: $(git branch --show-current)"
echo ""
echo "Check recovered work:"
git show --stat HEAD
echo ""
echo "Run tests to verify everything works"
```
- **Cleanup suggestion:**
```bash
echo ""
echo "After verifying recovery:"
echo " - Delete backup branch if not needed:"
echo " git branch -d $backup_branch"
echo " - Push if needed:"
echo " git push --force-with-lease"
```
## Error Handling
### Commit Not Found
```bash
if ! git cat-file -e "$commit_hash" 2>/dev/null; then
echo "Error: Commit not found in repository"
echo "Commit: $commit_hash"
echo ""
echo "Possible reasons:"
echo " - Commit was garbage collected (>90 days old)"
echo " - Typo in commit hash"
echo " - Commit in different repository"
echo ""
echo "Try these recovery methods:"
echo " 1. Check reflog: git reflog show --all"
echo " 2. Search all refs: git log --all --oneline | grep <message>"
echo " 3. Find dangling commits: git fsck --lost-found"
exit 1
fi
```
### Reflog Expired
```bash
# Check if reflog exists
if [ ! -f ".git/logs/HEAD" ]; then
echo "Error: No reflog found"
echo ""
echo "Possible reasons:"
echo " - Fresh clone (reflog not transferred)"
echo " - Reflog disabled in config"
echo " - Repository corruption"
echo ""
echo "Recovery may not be possible"
exit 1
fi
# Check reflog age
oldest_entry=$(git reflog show | tail -1)
echo "Oldest reflog entry: $oldest_entry"
echo ""
echo "Reflog entries older than ~90 days are garbage collected"
echo "If your lost work is older, recovery may not be possible"
```
### Branch Creation Failed
```bash
if git branch "$new_branch" "$commit_hash" 2>&1 | grep -q "already exists"; then
echo "Error: Branch already exists: $new_branch"
echo ""
echo "Options:"
echo " 1. Choose different name"
echo " 2. Delete existing branch: git branch -D $new_branch"
echo " 3. Reset existing branch: git branch -f $new_branch $commit_hash"
exit 1
fi
```
### Reset Failed
```bash
if ! git reset --hard "$commit_hash" 2>&1; then
echo "Error: Reset failed"
echo ""
echo "Your repository state was not changed"
echo "Check: git status"
echo ""
echo "If you have backup branch:"
echo " git reset --hard $backup_branch"
exit 1
fi
```
## Examples
### Example 1: View Recent Reflog
```bash
/git:reflog-recover
# Reflog Entries (Recent 30):
# ========================================
#
# HEAD@{0} abc1234 5 minutes ago
# commit: Add user authentication
#
# HEAD@{1} def5678 2 hours ago
# checkout: moving from main to feature-auth
#
# HEAD@{2} ghi9012 3 hours ago
# reset: moving to HEAD^
# ⚠ RESET - Commits may be lost
#
# HEAD@{3} jkl3456 3 hours ago
# commit: Fix token validation
# [This commit was reset away!]
#
# HEAD@{4} mno7890 5 hours ago
# commit (amend): Update README
# ⚠ AMEND - Previous version at HEAD@{5}
#
# HEAD@{5} pqr3456 5 hours ago
# commit: Update README
# [Original version before amend]
#
# ...
#
# Actions:
# [r] Recover specific entry
# [s] Search reflog
# [q] Quit
```
### Example 2: Recover from Accidental Reset
```bash
# Situation: Accidentally did git reset --hard HEAD^
# Lost last commit!
/git:reflog-recover
# Looking at reflog:
# HEAD@{0} def5678 reset: moving to HEAD^ (just now)
# HEAD@{1} abc1234 commit: Important feature (5 min ago) ← Lost!
# Select entry to recover: HEAD@{1}
# User: 1
#
# Commit Details:
# ========================================
# Hash: abc1234567890abcdef
# Message: Important feature
# Author: John Doe
# Date: 2025-10-21 14:30:00
#
# Files Changed:
# src/feature.js | 45 +++++++++++++++++++++++++
# tests/feature.test.js | 23 +++++++++++++
#
# Recovery Options:
# 1. Create branch (safest)
# 2. Reset current branch (restore state)
# 3. Cherry-pick commit
# 4. Show more details
#
# Choice: 2
#
# ⚠ This will reset current branch
# Backup created: backup-main-1729534567
# Type 'RESET' to confirm: RESET
#
# Resetting to abc1234...
# ✓ Recovery complete!
#
# You are now at: Important feature
# Lost commit is recovered!
```
### Example 3: Find and Recover Deleted Branch
```bash
/git:reflog-recover "deleted branch" show
# Searching reflog for: "deleted branch"
#
# Found 2 matches:
# ========================================
#
# HEAD@{15} def5678 2 days ago
# Branch: delete branch feature-x
# Last commit on feature-x: "Add feature X"
#
# HEAD@{145} abc1234 2 months ago
# Branch: delete branch old-experiment
# Last commit: "Experimental changes"
#
# Recover which entry? (1-2, or 'all')
# User: 1
#
# Recovering branch: feature-x
# Last commit: def5678 "Add feature X"
#
# New branch name? (default: feature-x)
# User: feature-x-recovered
#
# Creating branch...
# ✓ Created branch: feature-x-recovered at def5678
#
# To use recovered branch:
# git checkout feature-x-recovered
#
# Switch now? (y/n)
# User: y
#
# ✓ Switched to branch 'feature-x-recovered'
# Your deleted branch is recovered!
```
### Example 4: Undo Bad Rebase
```bash
# Situation: Rebase went wrong, conflicts everywhere
# Want to undo entire rebase
/git:reflog-recover rebase
# Searching for: rebase
#
# Found rebase operations:
# ========================================
#
# HEAD@{0} abc9999 rebase (finish): refs/heads/feature
# (5 minutes ago) ← Bad rebase!
#
# HEAD@{1} def8888 rebase (continue): Add feature Y
# (7 minutes ago)
#
# HEAD@{2} ghi7777 rebase (start): checkout main
# (10 minutes ago)
#
# HEAD@{3} jkl6666 commit: Add feature Y
# (15 minutes ago) ← Before rebase started
#
# Recover to before rebase? (entry 3)
# User: y
#
# This will restore branch to: jkl6666
# Before rebase started
#
# Recovery method:
# 1. Reset branch (undo rebase)
# 2. Create new branch (keep both)
#
# Choice: 1
#
# Creating backup: backup-feature-1729534567
# Resetting to jkl6666...
# ✓ Rebase undone!
#
# You are back to state before rebase
# Original commits preserved
```
### Example 5: Find Lost Work by Keyword
```bash
/git:reflog-recover "authentication" show
# Searching for: "authentication"
#
# Found 8 entries with "authentication":
# ========================================
#
# HEAD@{3} abc1234 3 hours ago
# commit: Add user authentication
#
# HEAD@{12} def5678 1 day ago
# commit: Fix authentication bug
#
# HEAD@{25} ghi9012 3 days ago
# commit: Update authentication flow
#
# HEAD@{45} jkl3456 1 week ago
# commit: Implement OAuth authentication
#
# ...
#
# Show details for which entry? (number or 'all')
# User: 3
#
# Commit: ghi9012
# ========================================
# Message: Update authentication flow
# Author: Jane Smith
# Date: 2025-10-18 10:15:00
#
# Changes:
# src/auth/flow.js | 67 ++++++++++++++++++++++++++++++++
# src/auth/middleware.js | 34 +++++++++++++---
#
# [Shows full diff]
#
# Actions:
# [b] Create branch from this commit
# [c] Cherry-pick to current branch
# [p] Export as patch
# [q] Back to list
```
### Example 6: Recover Amended Commit
```bash
# Situation: Amended commit but want original version
/git:reflog-recover "amend"
# Searching for: amend
#
# Found amendments:
# ========================================
#
# HEAD@{0} abc9999 commit (amend): Fix typo in docs
# (2 minutes ago) ← New version
#
# HEAD@{1} abc1234 commit: Fix typo in docs
# (5 minutes ago) ← Original version before amend
#
# Compare versions? (y/n)
# User: y
#
# Differences between versions:
# ========================================
# Original (abc1234):
# Fixed typo in README
# [Shows original diff]
#
# Amended (abc9999):
# Fixed typo in README and CONTRIBUTING
# [Shows amended diff]
#
# Recover original version?
# 1. Create branch with original
# 2. Reset to original (lose amendment)
# 3. Keep amended version
#
# Choice: 1
#
# Branch name: pre-amend-version
# ✓ Created branch with original version
```
## Advanced Usage
### Find Dangling Commits
```bash
# Find commits not in any branch (beyond reflog)
git fsck --lost-found
# Shows unreachable commits
# More aggressive than reflog
# Can find very old lost commits
```
### Export Reflog
```bash
# Save reflog to file
git reflog show > reflog-backup-$(date +%Y%m%d).txt
# Useful before dangerous operations
# Can review later if needed
```
### Reflog for Specific Branch
```bash
# View reflog for specific branch
git reflog show feature-branch
# See all changes to that branch
# Not just HEAD movements
```
### Reflog with Dates
```bash
# Show reflog with exact dates
git reflog show --date=iso
# Or relative dates
git reflog show --date=relative
# Find what happened at specific time
git reflog show HEAD@{2025-10-21.14:30:00}
```
### Expire Reflog Manually
```bash
# Expire reflog entries older than X
git reflog expire --expire=30.days --all
# Aggressive cleanup
git reflog expire --expire=now --all
git gc --prune=now
# Only do if sure!
```
## Tips for Using Reflog
1. **Act quickly:**
- Reflog expires after ~90 days
- Recover as soon as you notice mistake
- Don't wait
2. **Check reflog before dangerous operations:**
- Before reset --hard
- Before rebase
- Before force-push
- Know you can undo
3. **Search effectively:**
- Use keywords from commit messages
- Search by branch names
- Look for operation types (reset, rebase)
4. **Create branches, don't reset:**
- Safest recovery method
- Can review before deciding
- Preserves current state
5. **Regular reflog backups:**
- Export reflog periodically
- Especially before risky operations
- Extra safety net
6. **Understand reflog vs garbage collection:**
- Reflog keeps references
- Prevents garbage collection
- After expiry, commits can be GC'd
## Related Commands
- `/git:branch-cleanup` - Clean up recovered branches
- `/git:cherry-pick-helper` - Apply recovered commits
- `/git:bisect` - Find bugs in recovered history
- `/git:worktree` - Test recovered commits safely

751
commands/stash-manager.md Normal file
View File

@@ -0,0 +1,751 @@
---
name: git:stash-manager
description: Advanced stash management including list, save, apply, pop, and organize stashes with detailed context.
---
# Git Stash Manager - Advanced Stash Operations
Advanced stash management including list, save, apply, pop, and organize stashes with detailed context.
## Command
`/git:stash-manager <action> [stash-ref-or-message]`
## Arguments
- `$1`: action - `list|save|apply|pop|show|drop|clear|branch` (required)
- `$2`: stash-ref or message - Depends on action (stash@{n} for apply/pop/show/drop, message for save)
## Description
Git stash allows you to save uncommitted changes temporarily and restore them later. This is useful when you need to switch contexts, pull updates, or try experimental changes without committing. The stash manager provides an organized way to manage multiple stashes with better visibility and control.
## Use Cases
- Switch branches without committing work-in-progress
- Pull latest changes with uncommitted local changes
- Try experimental changes with easy rollback
- Temporarily remove changes to test something
- Save different variations of work
- Transfer changes between branches
- Context switching during interruptions
## Workflow
### Listing Stashes
1. **Display all stashes:**
```bash
git stash list
```
2. **Enhanced listing with details:**
- Show stash index and message
- Show branch where stash was created
- Show date/time of stash creation
- Show which files are affected
- Show summary of changes (additions/deletions)
- Highlight recent stashes (< 24 hours)
3. **For each stash show:**
```
stash@{0}: On feature-auth: WIP authentication module
Branch: feature-auth
Created: 2 hours ago (2025-10-21 14:30:15)
Files: 3 modified, 1 added
M src/auth.js (+45, -12)
M src/session.js (+23, -5)
A src/token.js (+67)
Size: ~135 lines changed
```
4. **Interactive options:**
- Show diff for specific stash
- Apply or pop stash
- Delete stash
- Create branch from stash
- Export stash as patch file
### Saving Stashes
5. **Gather stash options:**
- Ask for descriptive message (required)
- Ask if including untracked files (`-u`)
- Ask if including ignored files (`-a`, all)
- Ask if keeping staged changes (`--keep-index`)
- Ask if including path-specific changes
6. **Create stash with options:**
Basic stash:
```bash
git stash push -m "message"
```
With untracked files:
```bash
git stash push -u -m "message"
```
Keep staged changes:
```bash
git stash push --keep-index -m "message"
```
Specific paths only:
```bash
git stash push -m "message" -- path/to/file path/to/dir
```
7. **Confirm stash created:**
- Show stash reference (stash@{0})
- Show what was stashed
- Show current status
- Offer to show stash diff
### Applying Stashes
8. **Select stash to apply:**
- If no stash-ref provided, show list
- Ask user to select by number or reference
- Show stash details before applying
- Warn if stash is from different branch
9. **Pre-apply checks:**
- Check for uncommitted changes (warn about merge)
- Check for conflicts with stash
- Dry-run to predict conflicts
- Show which files will be modified
10. **Apply stash:**
```bash
git stash apply stash@{n}
```
Or with index restoration:
```bash
git stash apply --index stash@{n}
```
11. **Handle conflicts:**
- If conflicts occur, show conflicted files
- Guide through resolution
- Offer to abort (stash remains in list)
- After resolution, stash remains in list
12. **Confirm application:**
- Show what was applied
- Note that stash still exists (use pop to remove)
- Show current status
### Popping Stashes
13. **Pop vs Apply:**
- Explain difference: pop removes stash after applying
- Confirm user wants to remove stash
- Recommend apply if unsure
14. **Pop stash:**
```bash
git stash pop stash@{n}
```
15. **On success:**
- Stash is removed from list
- Changes applied to working directory
- Show updated status
16. **On conflict:**
- Changes partially applied
- Stash is NOT removed
- Must resolve conflicts manually
- Can abort with `git reset --hard`
### Showing Stash Details
17. **Display stash content:**
```bash
git stash show -p stash@{n}
```
18. **Show comprehensive details:**
- Commit information
- Full diff of changes
- Summary statistics
- List of affected files
- Branch context
19. **Interactive options:**
- View file-by-file
- Show only specific files
- Compare with current working directory
- Apply/pop after viewing
### Dropping Stashes
20. **Confirm deletion:**
- Show stash details before dropping
- Warn that drop is permanent
- Require explicit confirmation
- Offer to save as patch file first
21. **Drop stash:**
```bash
git stash drop stash@{n}
```
22. **Recovery note:**
- Explain dropped stashes can be recovered (briefly)
- Mention reflog recovery within ~90 days
- Show recover command hint
### Clearing All Stashes
23. **Warning prompt:**
- Show count of stashes to be deleted
- List all stashes briefly
- Warn this is permanent
- Require typing "yes" to confirm
24. **Clear all stashes:**
```bash
git stash clear
```
25. **Confirmation:**
- Confirm all stashes cleared
- Note that recovery may be possible via reflog
- Show clean stash list
### Creating Branch from Stash
26. **Create branch with stash:**
- Useful when stash has conflicts with current branch
- Ask for new branch name
- Create branch and apply stash
27. **Execute:**
```bash
git stash branch <branch-name> stash@{n}
```
28. **Result:**
- New branch created from commit where stash was created
- Stash applied to new branch
- Stash removed from list
- Switched to new branch
## Safety Checks
### Before Saving Stash
- **Nothing to stash:**
```bash
if [ -z "$(git status --porcelain)" ]; then
echo "Error: No changes to stash"
echo "Working directory is clean"
exit 1
fi
```
- **Descriptive message required:**
```bash
if [ -z "$message" ] || [ "$message" = "WIP" ]; then
echo "Please provide a descriptive stash message"
echo "Bad: 'WIP', 'temp', 'stuff'"
echo "Good: 'WIP: authentication refactor', 'Debug logging for issue #123'"
# Ask for better message
fi
```
- **Untracked files warning:**
```bash
untracked_count=$(git ls-files --others --exclude-standard | wc -l)
if [ $untracked_count -gt 0 ]; then
echo "Warning: $untracked_count untracked file(s) detected"
echo "Include untracked files in stash? (y/n)"
echo "Use -u flag to include them"
fi
```
### Before Applying/Popping
- **Uncommitted changes warning:**
```bash
if [ -n "$(git status --porcelain)" ]; then
echo "Warning: You have uncommitted changes"
echo "Applying stash may cause conflicts"
echo ""
git status --short
echo ""
echo "Options:"
echo " 1. Continue anyway (may conflict)"
echo " 2. Commit current changes first"
echo " 3. Stash current changes first (nested stash)"
echo " 4. Cancel"
fi
```
- **Stash reference validation:**
```bash
if ! git rev-parse --verify "$stash_ref" >/dev/null 2>&1; then
echo "Error: Invalid stash reference: $stash_ref"
echo ""
echo "Available stashes:"
git stash list
echo ""
echo "Use: stash@{0}, stash@{1}, etc."
exit 1
fi
```
- **Branch mismatch warning:**
```bash
stash_branch=$(git stash list | grep "$stash_ref" | sed 's/.*On \([^:]*\):.*/\1/')
current_branch=$(git branch --show-current)
if [ "$stash_branch" != "$current_branch" ]; then
echo "Notice: Stash created on different branch"
echo " Stash from: $stash_branch"
echo " Current: $current_branch"
echo ""
echo "This may cause conflicts. Continue? (y/n)"
fi
```
- **Conflict prediction:**
```bash
# Dry-run to check for conflicts
if ! git apply --check $(git stash show -p $stash_ref) 2>/dev/null; then
echo "Warning: This stash may have conflicts"
echo "Files that may conflict:"
# Show potentially conflicting files
echo ""
echo "Continue? (y/n)"
fi
```
### Before Dropping/Clearing
- **Confirmation required:**
```bash
echo "About to drop stash: $stash_ref"
git stash show --stat $stash_ref
echo ""
echo "This cannot be undone easily!"
echo "Type 'yes' to confirm: "
read confirmation
if [ "$confirmation" != "yes" ]; then
echo "Drop cancelled"
exit 0
fi
```
- **Offer patch export:**
```bash
echo "Save this stash as a patch file first? (y/n)"
read save_patch
if [ "$save_patch" = "y" ]; then
patch_file="stash-$(date +%s).patch"
git stash show -p $stash_ref > "$patch_file"
echo "Saved to: $patch_file"
fi
```
### After Operations
- **Verify application:**
```bash
echo "Stash applied. Verifying..."
echo ""
echo "Changed files:"
git status --short
echo ""
echo "Run tests to verify everything works:"
echo " npm test"
echo " pytest"
echo " cargo test"
```
## Error Handling
### No Stashes Exist
```bash
if [ -z "$(git stash list)" ]; then
echo "No stashes found"
echo ""
echo "Create a stash with:"
echo " /git:stash-manager save 'description'"
echo ""
echo "Or directly:"
echo " git stash push -m 'description'"
exit 1
fi
```
### Apply/Pop Conflicts
```bash
# When git stash apply/pop fails with conflicts
if [ $? -ne 0 ]; then
echo "Conflict occurred while applying stash!"
echo ""
echo "Conflicted files:"
git diff --name-only --diff-filter=U
echo ""
echo "Options:"
echo " 1. Resolve conflicts manually:"
echo " - Edit conflicted files"
echo " - git add <file> (after resolving)"
echo " 2. Abort changes:"
echo " git reset --hard HEAD"
echo " 3. Try applying to different branch:"
echo " /git:stash-manager branch new-branch-name"
echo ""
echo "Note: For pop, stash was NOT removed due to conflict"
exit 1
fi
```
### Invalid Stash Reference
```bash
if ! git stash list | grep -q "^$stash_ref:"; then
echo "Error: Stash not found: $stash_ref"
echo ""
echo "Available stashes:"
git stash list | nl -v 0
echo ""
echo "Note: stash@{0} is most recent"
exit 1
fi
```
### Stash Apply to Dirty Directory
```bash
if [ -n "$(git status --porcelain)" ]; then
echo "Warning: Working directory has uncommitted changes"
echo ""
git status --short
echo ""
echo "Applying stash on top of these changes may cause issues"
echo ""
echo "Recommended: "
echo " 1. Commit current changes, or"
echo " 2. Stash current changes first (nested stash), or"
echo " 3. Use a worktree: /git:worktree"
echo ""
echo "Force apply anyway? (y/n)"
read force
[ "$force" != "y" ] && exit 0
fi
```
## Examples
### Example 1: Save Stash with Description
```bash
/git:stash-manager save "WIP: implementing OAuth authentication"
# Include untracked files? (y/n)
# User: y
#
# Keep staged changes in working directory? (y/n)
# User: n
#
# Saved working directory and index state:
# stash@{0}: On feature-auth: WIP: implementing OAuth authentication
#
# Stashed:
# 3 modified files
# 2 new files (untracked)
# Total: ~127 lines changed
#
# Working directory is now clean
```
### Example 2: List Stashes with Details
```bash
/git:stash-manager list
# ========================================
# Git Stashes (3)
# ========================================
#
# stash@{0}: On feature-auth: WIP: implementing OAuth authentication
# Branch: feature-auth
# Created: 2 hours ago (2025-10-21 14:30:15)
# Files: 3 modified, 2 added
# M src/auth/oauth.js (+45, -12)
# M src/auth/session.js (+23, -5)
# A src/auth/tokens.js (+67)
# A tests/auth/oauth.test.js (+89)
#
# stash@{1}: On main: Fix styling issues on mobile
# Branch: main
# Created: 1 day ago (2025-10-20 09:15:42)
# Files: 5 modified
# M src/styles/mobile.css (+34, -18)
# M src/components/Header.js (+12, -8)
# ...
#
# stash@{2}: On feature-ui: Experimental layout changes
# Branch: feature-ui
# Created: 3 days ago (2025-10-18 16:45:00)
# Files: 8 modified, 1 deleted
# ...
#
# Actions: [s]how, [a]pply, [p]op, [d]rop, [q]uit
```
### Example 3: Apply Stash with Conflicts
```bash
/git:stash-manager apply stash@{0}
# Applying stash@{0}...
# On feature-auth: WIP: implementing OAuth authentication
#
# Warning: You are on a different branch
# Stash from: feature-auth
# Current: main
#
# This may cause conflicts. Continue? (y/n)
# User: y
#
# Applying...
# Conflict in src/auth/oauth.js
# Conflict in src/auth/session.js
#
# Conflicted files:
# src/auth/oauth.js
# src/auth/session.js
#
# Please resolve conflicts:
# 1. Edit files to resolve <<<< ==== >>>> markers
# 2. Test your changes
# 3. Stage resolved files: git add <file>
#
# Or abort:
# git reset --hard HEAD
#
# Note: Stash still exists (not removed)
```
### Example 4: Pop Most Recent Stash
```bash
/git:stash-manager pop
# Most recent stash:
# stash@{0}: On feature-auth: WIP: implementing OAuth authentication
# 3 files modified, 2 files added
#
# Apply and remove this stash? (y/n)
# User: y
#
# Applying stash@{0}...
# Success!
#
# Changed files:
# M src/auth/oauth.js
# M src/auth/session.js
# M src/auth/tokens.js
# A tests/auth/oauth.test.js
# A tests/auth/tokens.test.js
#
# Stash removed from list
# Current status: 5 files modified
```
### Example 5: Show Stash Details
```bash
/git:stash-manager show stash@{1}
# ========================================
# Stash: stash@{1}
# ========================================
# Message: Fix styling issues on mobile
# Branch: main
# Created: 1 day ago (2025-10-20 09:15:42)
# Author: John Doe <john@example.com>
#
# Files Changed (5):
# ========================================
# src/styles/mobile.css | 52 ++++++++++++++++++++++-----------
# src/components/Header.js | 20 ++++++------
# src/components/Nav.js | 15 ++++++---
# src/components/Footer.js | 8 ++---
# src/index.css | 3 +-
#
# Diff:
# ========================================
# [Shows full diff output...]
#
# Actions:
# [a] Apply this stash
# [p] Pop this stash
# [d] Drop this stash
# [b] Create branch from stash
# [q] Back to list
```
### Example 6: Drop Specific Stash
```bash
/git:stash-manager drop stash@{2}
# About to drop:
# stash@{2}: On feature-ui: Experimental layout changes
# Created: 3 days ago
# 8 files modified, 1 file deleted
#
# This cannot be easily undone!
#
# Save as patch file first? (y/n)
# User: y
#
# Saved to: stash-1729534567.patch
#
# Type 'yes' to confirm deletion:
# User: yes
#
# Dropped stash@{2}
# Recovery may be possible via reflog:
# git fsck --unreachable | grep commit
```
### Example 7: Clear All Stashes
```bash
/git:stash-manager clear
# WARNING: About to delete ALL stashes!
#
# Current stashes (3):
# stash@{0}: WIP: implementing OAuth authentication
# stash@{1}: Fix styling issues on mobile
# stash@{2}: Experimental layout changes
#
# This action is PERMANENT!
#
# Type 'DELETE ALL' to confirm:
# User: DELETE ALL
#
# Cleared all stashes
# Stash list is now empty
#
# Note: Recovery may be possible within 90 days via reflog
```
### Example 8: Create Branch from Stash
```bash
/git:stash-manager branch experimental-auth stash@{0}
# Creating branch from stash...
# Branch: experimental-auth
# Based on commit where stash was created
# Stash: stash@{0}: WIP: implementing OAuth authentication
#
# Created branch 'experimental-auth'
# Switched to branch 'experimental-auth'
# Applied stash changes
# Dropped stash@{0}
#
# Your changes are now on branch: experimental-auth
# Status: 5 files modified
```
## Advanced Usage
### Partial Stash (Specific Files)
```bash
# Stash only specific files
/git:stash-manager save "WIP: auth module only"
# Which files to stash?
# User: src/auth/*.js tests/auth/*.js
# Command:
git stash push -m "WIP: auth module only" -- src/auth/*.js tests/auth/*.js
```
### Interactive Stash
```bash
# Stash with interactive staging
git stash push -p -m "Selected changes only"
# Prompts for each hunk: stage this hunk? y/n
```
### Stash to Patch File
```bash
# Export stash as patch
git stash show -p stash@{0} > my-changes.patch
# Later, apply patch
git apply my-changes.patch
# Or:
patch -p1 < my-changes.patch
```
### View Stash as Commit
```bash
# Each stash is actually a commit
git show stash@{0}
# View stash log
git log --oneline --graph stash@{0}
# Stash has 3 parents:
# 1. HEAD when stash was created
# 2. Index state
# 3. Untracked files (if -u used)
```
## Tips for Effective Stash Usage
1. **Descriptive messages:**
- Bad: "WIP", "temp", "stuff"
- Good: "WIP: OAuth integration", "Debug: issue #123", "Experiment: new layout"
- Include ticket numbers, feature names, or context
2. **Keep stashes short-lived:**
- Don't use stash as long-term storage
- Apply or pop within a day or two
- For longer storage, commit to a branch
3. **One stash at a time (usually):**
- Multiple stashes get confusing
- Apply/pop before creating new ones
- Use worktrees for parallel work instead
4. **Include untracked files:**
- Use `-u` flag when saving
- Prevents forgetting about new files
- Makes stash more complete
5. **Branch strategy:**
- If stash has conflicts, create branch
- Better than fighting conflicts
- Can merge branch later
## Related Commands
- `/git:worktree` - Better than stash for parallel work
- `/git:branch-cleanup` - Clean up branches created from stashes
- `/git:cherry-pick-helper` - Apply specific commits instead of stash
- `/git:reflog-recover` - Recover dropped stashes

567
commands/worktree.md Normal file
View File

@@ -0,0 +1,567 @@
---
name: git:worktree
description: Manage multiple working trees for parallel development, testing, and code review without branch switching overhead.
---
# Git Worktree - Multiple Working Trees Management
Manage multiple working trees for parallel development, testing, and code review without branch switching overhead.
## Command
`/git:worktree <action> [path] [branch-name]`
## Arguments
- `$1`: action - `add|list|remove|prune|lock|unlock` (required)
- `$2`: path - Directory path for the worktree (required for add/remove)
- `$3`: branch-name - Branch to checkout in worktree (optional for add)
## Description
Git worktrees allow you to have multiple working directories from the same repository, each with different branches checked out. This eliminates the need to stash changes, switch branches, and potentially deal with conflicts when you need to work on multiple features simultaneously or review code while keeping your current work intact.
## Use Cases
- Work on multiple features simultaneously
- Review pull requests without interrupting current work
- Run tests on one branch while developing on another
- Compare code between branches side-by-side
- Keep a clean build directory separate from development
- Emergency hotfixes without stashing current work
## Workflow
### Adding a New Worktree
1. **Validate input:**
- Check path doesn't already exist
- Check path is not inside current repository
- Validate branch name if provided
- Check for branch conflicts
2. **Gather information:**
- Ask for target path (relative or absolute)
- Ask for branch name (or generate from feature name)
- Ask if creating new branch or checking out existing
- Optionally ask for starting point (commit/branch to base on)
3. **Create worktree:**
For new branch:
```bash
git worktree add -b <new-branch> <path> <starting-point>
```
For existing branch:
```bash
git worktree add <path> <existing-branch>
```
Create worktree and checkout:
```bash
git worktree add <path>
# Creates new branch from HEAD
```
4. **Post-creation:**
- Confirm worktree created successfully
- Display worktree information
- Show path, branch, and commit
- Offer to change directory to new worktree
- Suggest next steps (cd command, IDE instructions)
### Listing Worktrees
5. **Display all worktrees:**
- Show main working tree
- Show all linked worktrees
- For each worktree show:
- Path (absolute)
- Branch name
- Commit hash and message
- Status (clean/modified/locked)
- Whether it's the current worktree
6. **Enhanced listing:**
```bash
git worktree list --porcelain
```
Parse and display:
- Which worktree is current (*)
- Uncommitted changes indicator
- Days since last commit
- Locked status with reason
7. **Interactive options:**
- Offer to show details for specific worktree
- Option to remove stale worktrees
- Option to navigate to worktree
- Show disk usage per worktree
### Removing a Worktree
8. **Pre-removal checks:**
- Verify worktree exists
- Check if it's the current worktree (can't remove)
- Check for uncommitted changes
- Check for unpushed commits
- Warn about any issues
9. **Confirm removal:**
- Show worktree details
- Show what will be lost
- Ask for explicit confirmation
- Option to force remove if locked
10. **Remove worktree:**
```bash
git worktree remove <path>
```
Or force removal:
```bash
git worktree remove --force <path>
```
11. **Post-removal:**
- Confirm removal successful
- Note that branch still exists (unless deleted)
- Offer to delete branch if fully merged
- Show updated worktree list
### Pruning Stale Worktrees
12. **Find stale entries:**
- Worktree directories that no longer exist
- Locked worktrees that can be cleaned
- Administrative data that can be pruned
13. **Show what will be pruned:**
```bash
git worktree prune --dry-run
```
14. **Prune stale entries:**
```bash
git worktree prune
```
15. **Confirm results:**
- Show what was pruned
- Display updated worktree list
### Lock/Unlock Worktrees
16. **Lock worktree:**
- Prevent accidental removal
- Useful for worktrees on removable media
- Add reason for lock
```bash
git worktree lock --reason "Testing environment" <path>
```
17. **Unlock worktree:**
```bash
git worktree unlock <path>
```
## Safety Checks
### Before Adding
- **Path validation:**
```bash
# Check path doesn't exist
if [ -e "$path" ]; then
echo "Error: Path already exists: $path"
echo "Choose a different path or remove existing directory"
exit 1
fi
# Check path is not inside repository
if [[ "$path" == "$(git rev-parse --show-toplevel)"* ]]; then
echo "Warning: Creating worktree inside repository"
echo "This is unusual. Continue? (y/n)"
# Wait for confirmation
fi
```
- **Branch validation:**
```bash
# Check if branch exists
if git show-ref --verify --quiet refs/heads/$branch; then
# Branch exists
# Check if already checked out in another worktree
if git worktree list | grep -q "$branch"; then
echo "Error: Branch '$branch' is already checked out in another worktree"
echo "A branch can only be checked out in one worktree at a time"
exit 1
fi
fi
```
- **Disk space check:**
```bash
# Check available disk space
available=$(df "$target_dir" | awk 'NR==2 {print $4}')
repo_size=$(du -s "$(git rev-parse --show-toplevel)" | awk '{print $1}')
if [ $available -lt $repo_size ]; then
echo "Warning: Low disk space"
echo "Available: ${available}K"
echo "Repository size: ${repo_size}K"
echo "Continue? (y/n)"
fi
```
### Before Removing
- **Uncommitted changes check:**
```bash
cd "$worktree_path"
if [ -n "$(git status --porcelain)" ]; then
echo "Warning: Worktree has uncommitted changes:"
git status --short
echo ""
echo "Options:"
echo " 1. Cancel removal"
echo " 2. Force remove (lose changes)"
echo " 3. Show me the changes first"
# Wait for user choice
fi
```
- **Unpushed commits check:**
```bash
unpushed=$(git log --oneline @{u}.. 2>/dev/null | wc -l)
if [ $unpushed -gt 0 ]; then
echo "Warning: Worktree has $unpushed unpushed commit(s):"
git log --oneline @{u}..
echo ""
echo "These commits will NOT be lost (branch still exists)"
echo "But you may want to push them first."
echo "Continue with removal? (y/n)"
fi
```
- **Current worktree check:**
```bash
current_worktree=$(git worktree list --porcelain | grep "$(pwd)" | head -1)
if [ -n "$current_worktree" ]; then
echo "Error: Cannot remove current worktree"
echo "Please cd to a different directory first"
exit 1
fi
```
- **Locked worktree check:**
```bash
if git worktree list --porcelain | grep -A5 "worktree $path" | grep -q "locked"; then
reason=$(git worktree list --porcelain | grep -A5 "worktree $path" | grep "locked" | cut -d' ' -f2-)
echo "Warning: Worktree is locked"
echo "Reason: $reason"
echo ""
echo "Options:"
echo " 1. Cancel removal"
echo " 2. Unlock and remove"
echo " 3. Force remove (keep lock reason for reference)"
fi
```
### During Prune
- **Dry-run first:**
```bash
echo "Finding stale worktrees..."
git worktree prune --dry-run --verbose
echo ""
echo "Proceed with pruning? (y/n)"
```
## Error Handling
### Path Already Exists
```bash
if [ -e "$path" ]; then
echo "Error: Path already exists: $path"
# Check if it's an old worktree directory
if [ -f "$path/.git" ]; then
content=$(cat "$path/.git")
if [[ $content == gitdir:* ]]; then
echo "This appears to be an orphaned worktree directory"
echo "Options:"
echo " 1. Remove directory and create new worktree"
echo " 2. Try to repair worktree link"
echo " 3. Choose different path"
fi
fi
exit 1
fi
```
### Branch Already Checked Out
```bash
if git worktree list | grep -q " \[$branch\]"; then
existing_path=$(git worktree list | grep " \[$branch\]" | awk '{print $1}')
echo "Error: Branch '$branch' is already checked out"
echo "Location: $existing_path"
echo ""
echo "A branch can only be checked out in one worktree at a time."
echo "Options:"
echo " 1. Use a different branch name"
echo " 2. Remove the existing worktree first"
echo " 3. Navigate to existing worktree: cd $existing_path"
exit 1
fi
```
### Worktree Not Found
```bash
if ! git worktree list | grep -q "$path"; then
echo "Error: No worktree found at: $path"
echo ""
echo "Available worktrees:"
git worktree list
echo ""
echo "Note: Path must match exactly as shown above"
exit 1
fi
```
### Cannot Remove Main Worktree
```bash
main_worktree=$(git worktree list | head -1 | awk '{print $1}')
if [ "$path" = "$main_worktree" ]; then
echo "Error: Cannot remove main worktree"
echo "The main worktree is the original repository directory"
echo "You can only remove linked worktrees created with 'git worktree add'"
exit 1
fi
```
## Examples
### Example 1: Add Worktree for Feature Development
```bash
# Interactive mode
/git:worktree add
# Claude prompts:
# "Where should the new worktree be created?"
# User: "../feature-auth"
#
# "What branch should be checked out?"
# User: "feature/oauth-integration"
#
# "This branch doesn't exist. Create new branch? (y/n)"
# User: "y"
#
# "What should the new branch be based on? (default: HEAD)"
# User: "main"
# Result:
# Created worktree at: /Users/geoff/Projects/feature-auth
# Branch: feature/oauth-integration (new)
# Based on: main
#
# To start working:
# cd ../feature-auth
```
### Example 2: Direct Add Command
```bash
# Add worktree with new branch
/git:worktree add ../feature-x feature/new-feature
# Add worktree for existing branch
/git:worktree add ../bugfix bugfix/issue-123
# Add worktree with detached HEAD at specific commit
/git:worktree add ../review abc1234
```
### Example 3: List All Worktrees
```bash
/git:worktree list
# Output:
# ========================================
# Git Worktrees
# ========================================
#
# * /Users/geoff/Projects/my-repo (main) [current]
# └─ Clean • Last commit: 2 hours ago
#
# /Users/geoff/Projects/feature-auth (feature/oauth-integration)
# └─ Modified (3 files) • Last commit: 5 minutes ago
#
# /Users/geoff/Projects/hotfix (hotfix/security-patch)
# └─ Clean • Last commit: 2 days ago • LOCKED
#
# /Users/geoff/Projects/review (abc1234) [detached]
# └─ Clean • Last commit: 1 week ago
#
# Total: 4 worktrees
```
### Example 4: Remove Worktree
```bash
/git:worktree remove ../feature-x
# Claude checks and prompts:
# "Worktree at ../feature-x has uncommitted changes:"
# M src/auth.js
# A src/session.js
#
# "What would you like to do?"
# 1. Cancel removal
# 2. Show me the changes
# 3. Force remove (changes will be lost)
#
# User choice: 2
#
# [Shows git diff output]
#
# "Still want to remove? (y/n)"
# User: "n"
#
# "Removal cancelled. You might want to:"
# - cd ../feature-x
# - Commit your changes
# - Or: git stash in that worktree
```
### Example 5: Prune Stale Worktrees
```bash
/git:worktree prune
# Output:
# Finding stale worktrees...
#
# Would prune:
# - /Users/geoff/Projects/old-feature (directory removed)
# - /Volumes/USB/temp-worktree (volume unmounted)
#
# Proceed with pruning? (y/n)
# User: y
#
# Pruned 2 stale worktree entries
#
# Updated worktree list:
# [shows current worktrees]
```
## Advanced Usage
### Worktree for PR Review
```bash
# Fetch PR branch
git fetch origin pull/123/head:pr-123
# Create worktree for review
/git:worktree add ../pr-review pr-123
# Review in separate directory
cd ../pr-review
# Run tests, review code, test changes
```
### Worktree for Release Builds
```bash
# Create locked worktree for clean builds
/git:worktree add ../build-release release-v1.0
cd ../build-release
# Lock it to prevent accidental removal
git worktree lock --reason "Production build environment"
# Build
npm run build:production
```
### Worktree for Bisect
```bash
# Create worktree for git bisect without affecting main work
/git:worktree add ../bisect-search main
cd ../bisect-search
git bisect start HEAD v1.0.0
# Run bisect without interrupting main development
```
### Multiple Feature Worktrees
```bash
# Main repo: ongoing development
cd /Users/geoff/Projects/my-repo
# Feature 1: new auth system
/git:worktree add ../auth-feature feature/oauth
# Feature 2: UI redesign
/git:worktree add ../ui-feature feature/new-ui
# Hotfix: security patch
/git:worktree add ../hotfix hotfix/cve-2025-1234
# PR review
/git:worktree add ../pr-456 pr-456
# Now work on any without switching branches in main repo
```
## Tips for Effective Worktree Usage
1. **Organize worktree locations:**
- Keep worktrees in a dedicated parent directory
- Use descriptive directory names
- Example structure:
```
~/Projects/
my-repo/ # Main worktree
my-repo-features/ # Feature worktrees
auth/
ui-redesign/
api-v2/
```
2. **Naming conventions:**
- Use branch names as directory names for clarity
- Prefix with purpose: `review-`, `feature-`, `hotfix-`
- Keep names short but descriptive
3. **Clean up regularly:**
- Remove worktrees when done with feature
- Run prune periodically
- Don't let worktrees accumulate
4. **IDE considerations:**
- Open each worktree as separate project/window
- Be aware of shared config (.git directory)
- Watch for file watchers across worktrees
5. **Branch management:**
- Remember: one branch per worktree
- Can't checkout same branch in multiple worktrees
- Delete branches after removing worktrees (if merged)
## Related Commands
- `/git:branch-cleanup` - Clean up branches from removed worktrees
- `/git:stash-manager` - Not needed with worktrees (no branch switching)
- `/git:bisect` - Use worktrees to bisect without interrupting work
- `/git:cherry-pick-helper` - Cherry-pick between worktrees