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

View File

@@ -0,0 +1,26 @@
{
"name": "git",
"description": "Git focused utilities with namespaced commands for advanced workflows",
"version": "1.0.0",
"author": {
"name": "Geoff Johnson",
"url": "https://github.com/geoffjay"
},
"skills": [
"./skills/git-conventions",
"./skills/git-advanced",
"./skills/git-troubleshooting",
"./skills/git-repository"
],
"commands": [
"./commands/bisect.md",
"./commands/commit.md",
"./commands/worktree.md",
"./commands/rebase-interactive.md",
"./commands/stash-manager.md",
"./commands/branch-cleanup.md",
"./commands/fixup.md",
"./commands/cherry-pick-helper.md",
"./commands/reflog-recover.md"
]
}

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# git
Git focused utilities with namespaced commands for advanced workflows

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

93
plugin.lock.json Normal file
View File

@@ -0,0 +1,93 @@
{
"$schema": "internal://schemas/plugin.lock.v1.json",
"pluginId": "gh:geoffjay/claude-plugins:plugins/utilities/git",
"normalized": {
"repo": null,
"ref": "refs/tags/v20251128.0",
"commit": "eb532f95bfd68bff47149839123d931f89351036",
"treeHash": "37ce08ebf3d452b999154b538667c3ded3f2571b034784c60346890e65342dbf",
"generatedAt": "2025-11-28T10:16:58.488191Z",
"toolVersion": "publish_plugins.py@0.2.0"
},
"origin": {
"remote": "git@github.com:zhongweili/42plugin-data.git",
"branch": "master",
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
},
"manifest": {
"name": "git",
"description": "Git focused utilities with namespaced commands for advanced workflows",
"version": "1.0.0"
},
"content": {
"files": [
{
"path": "README.md",
"sha256": "54069d35c10f71ed0ba6dcaa73758cca9fd88fda22b827fac006c478ae593c75"
},
{
"path": ".claude-plugin/plugin.json",
"sha256": "fb4cb735804139eabdb02a151a8f114bc8a8f6cc143adc045d2e6af8ee225f97"
},
{
"path": "commands/worktree.md",
"sha256": "e0f0c006f57b018b4b9561f638c06516d0664d1cb3585de94e4e44b910e0169c"
},
{
"path": "commands/fixup.md",
"sha256": "d1ce6254bfa59180c4eb19a1e689f5e17c5422637836374241a82d0cf1b4874f"
},
{
"path": "commands/stash-manager.md",
"sha256": "5f947645075f0964ed1bc3499411ac83a38da44607927a339fd5419dd5f41efb"
},
{
"path": "commands/cherry-pick-helper.md",
"sha256": "ea3601a1acc29d6974abbc212bc693d1217a54ab361bd456627db07330a03ec9"
},
{
"path": "commands/branch-cleanup.md",
"sha256": "80c9e63cedbce72f3550ec5f44736d388071daed05b98b5b5bd64ed8a7fd7e8d"
},
{
"path": "commands/rebase-interactive.md",
"sha256": "7032c24ad4f968590ad761a2dc04d0d076dc7db5b1542b8a148a50b18dc4ddee"
},
{
"path": "commands/bisect.md",
"sha256": "5fe3b6968bafafc313b5124e1ca0ec258ca7e06410b72dab4f8625ef0d29effb"
},
{
"path": "commands/commit.md",
"sha256": "ac9d95f69fe62cf5735bcbb69117208bffa02e30a7b3af2437a7a5e386c5d3ea"
},
{
"path": "commands/reflog-recover.md",
"sha256": "3327f28d3c3cf91709667b7621f8511c0b70304a3eba327b04702866b4b63964"
},
{
"path": "skills/git-conventions/SKILL.md",
"sha256": "f7ed1f2609dfbb5761f188e9b35157f284cad173005540a46d5905f28374e807"
},
{
"path": "skills/git-repository/SKILL.md",
"sha256": "e22d450ff89b5443858feaf385f6dfc454f1bd912e63e9cb79f221b774476d8f"
},
{
"path": "skills/git-troubleshooting/SKILL.md",
"sha256": "6e323b3ba7c936acde1c49c1a4e6da0dec6675e5f2ee0103b127397f12e41e3b"
},
{
"path": "skills/git-advanced/SKILL.md",
"sha256": "fec72fe525a724d16dcb89e3eee033d591c45b3297d71be8f6a9a91a6b74ba85"
}
],
"dirSha256": "37ce08ebf3d452b999154b538667c3ded3f2571b034784c60346890e65342dbf"
},
"security": {
"scannedAt": null,
"scannerVersion": null,
"flags": []
}
}

View File

@@ -0,0 +1,715 @@
---
name: git-advanced
description: Advanced git operations including complex rebase strategies, interactive staging, commit surgery, and history manipulation. Use when user needs to perform complex git operations like rewriting history or advanced merging.
---
# Git Advanced Operations Skill
This skill provides comprehensive guidance on advanced git operations, sophisticated rebase strategies, commit surgery techniques, and complex history manipulation for experienced git users.
## When to Use
Activate this skill when:
- Performing complex interactive rebases
- Rewriting commit history
- Splitting or combining commits
- Advanced merge strategies
- Cherry-picking across branches
- Commit message editing in history
- Author information changes
- Complex conflict resolution
## Interactive Rebase Strategies
### Basic Interactive Rebase
```bash
# Rebase last 5 commits
git rebase -i HEAD~5
# Rebase from specific commit
git rebase -i abc123^
# Rebase entire branch
git rebase -i main
```
### Rebase Commands
```bash
# Interactive rebase editor commands:
# p, pick = use commit
# r, reword = use commit, but edit commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like squash, but discard commit message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
```
### Squashing Commits
```bash
# Example: Squash last 3 commits
git rebase -i HEAD~3
# In editor:
pick abc123 feat: add user authentication
squash def456 fix: resolve login bug
squash ghi789 style: format code
# Squash all commits in feature branch
git rebase -i main
# Mark all except first as 'squash'
```
### Fixup Workflow
```bash
# Create fixup commit automatically
git commit --fixup=abc123
# Autosquash during rebase
git rebase -i --autosquash main
# Set autosquash as default
git config --global rebase.autosquash true
# Example workflow:
git log --oneline -5
# abc123 feat: add authentication
# def456 feat: add authorization
git commit --fixup=abc123
git rebase -i --autosquash HEAD~3
```
### Reordering Commits
```bash
# Interactive rebase
git rebase -i HEAD~5
# In editor, change order:
pick def456 feat: add database migration
pick abc123 feat: add user model
pick ghi789 feat: add API endpoints
# Reorder by moving lines:
pick abc123 feat: add user model
pick def456 feat: add database migration
pick ghi789 feat: add API endpoints
```
### Splitting Commits
```bash
# Start interactive rebase
git rebase -i HEAD~3
# Mark commit to split with 'edit'
edit abc123 feat: add user and role features
# When rebase stops:
git reset HEAD^
# Stage and commit parts separately
git add user.go
git commit -m "feat: add user management"
git add role.go
git commit -m "feat: add role management"
# Continue rebase
git rebase --continue
```
### Editing Old Commits
```bash
# Start interactive rebase
git rebase -i HEAD~5
# Mark commit with 'edit'
edit abc123 feat: add authentication
# When rebase stops, make changes
git add modified-file.go
git commit --amend --no-edit
# Or change commit message
git commit --amend
# Continue rebase
git rebase --continue
```
## Commit Surgery
### Amending Commits
```bash
# Amend last commit (add changes)
git add forgotten-file.go
git commit --amend --no-edit
# Amend commit message
git commit --amend -m "fix: correct typo in feature"
# Amend author information
git commit --amend --author="John Doe <john@example.com>"
# Amend date
git commit --amend --date="2024-03-15 10:30:00"
```
### Changing Commit Messages
```bash
# Change last commit message
git commit --amend
# Change older commit messages
git rebase -i HEAD~5
# Mark commits with 'reword'
# Change commit message without opening editor
git commit --amend -m "new message" --no-edit
```
### Changing Multiple Authors
```bash
# Filter-branch (legacy method, use filter-repo instead)
git filter-branch --env-filter '
if [ "$GIT_COMMITTER_EMAIL" = "old@example.com" ]; then
export GIT_COMMITTER_NAME="New Name"
export GIT_COMMITTER_EMAIL="new@example.com"
fi
if [ "$GIT_AUTHOR_EMAIL" = "old@example.com" ]; then
export GIT_AUTHOR_NAME="New Name"
export GIT_AUTHOR_EMAIL="new@example.com"
fi
' --tag-name-filter cat -- --branches --tags
# Modern method with git-filter-repo
git filter-repo --email-callback '
return email.replace(b"old@example.com", b"new@example.com")
'
```
### Removing Files from History
```bash
# Remove file from all history
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
# Better performance with index-filter
git filter-branch --index-filter 'git rm --cached --ignore-unmatch passwords.txt' HEAD
# Modern method with git-filter-repo (recommended)
git filter-repo --path passwords.txt --invert-paths
# Remove large files
git filter-repo --strip-blobs-bigger-than 10M
```
### BFG Repo-Cleaner
```bash
# Install BFG
# brew install bfg (macOS)
# apt-get install bfg (Ubuntu)
# Remove files by name
bfg --delete-files passwords.txt
# Remove large files
bfg --strip-blobs-bigger-than 50M
# Replace passwords in history
bfg --replace-text passwords.txt
# After BFG cleanup
git reflog expire --expire=now --all
git gc --prune=now --aggressive
```
## Advanced Cherry-Picking
### Basic Cherry-Pick
```bash
# Cherry-pick single commit
git cherry-pick abc123
# Cherry-pick multiple commits
git cherry-pick abc123 def456 ghi789
# Cherry-pick range of commits
git cherry-pick abc123..ghi789
# Cherry-pick without committing (stage only)
git cherry-pick -n abc123
```
### Cherry-Pick with Conflicts
```bash
# When conflicts occur
git cherry-pick abc123
# CONFLICT: resolve conflicts
# After resolving conflicts
git add resolved-file.go
git cherry-pick --continue
# Or abort cherry-pick
git cherry-pick --abort
# Skip current commit
git cherry-pick --skip
```
### Cherry-Pick Options
```bash
# Edit commit message during cherry-pick
git cherry-pick -e abc123
# Sign-off cherry-picked commit
git cherry-pick -s abc123
# Keep original author date
git cherry-pick --ff abc123
# Apply changes without commit attribution
git cherry-pick -n abc123
git commit --author="New Author <new@example.com>"
```
### Mainline Selection for Merge Commits
```bash
# Cherry-pick merge commit (specify parent)
git cherry-pick -m 1 abc123
# -m 1 = use first parent (main branch)
# -m 2 = use second parent (merged branch)
# Example workflow:
git log --graph --oneline
# * abc123 Merge pull request #123
# |\
# | * def456 feat: feature commit
# * | ghi789 fix: main branch commit
# To cherry-pick the merge keeping main branch changes:
git cherry-pick -m 1 abc123
```
## Advanced Merging
### Merge Strategies
```bash
# Recursive merge (default)
git merge -s recursive branch-name
# Ours (keep our changes on conflict)
git merge -s ours branch-name
# Theirs (keep their changes on conflict)
git merge -s theirs branch-name
# Octopus (merge 3+ branches)
git merge -s octopus branch1 branch2 branch3
# Subtree merge
git merge -s subtree branch-name
```
### Merge Strategy Options
```bash
# Ours (resolve conflicts with our version)
git merge -X ours branch-name
# Theirs (resolve conflicts with their version)
git merge -X theirs branch-name
# Ignore whitespace
git merge -X ignore-space-change branch-name
git merge -X ignore-all-space branch-name
# Patience algorithm (better conflict detection)
git merge -X patience branch-name
# Renormalize line endings
git merge -X renormalize branch-name
```
### Three-Way Merge
```bash
# Standard three-way merge
git merge feature-branch
# With custom merge message
git merge feature-branch -m "Merge feature: add authentication"
# No fast-forward (always create merge commit)
git merge --no-ff feature-branch
# Fast-forward only (fail if merge commit needed)
git merge --ff-only feature-branch
# Squash merge (combine all commits)
git merge --squash feature-branch
git commit -m "feat: add complete authentication system"
```
## Advanced Conflict Resolution
### Understanding Conflict Markers
```
<<<<<<< HEAD (Current Change)
int result = add(a, b);
=======
int sum = calculate(a, b);
>>>>>>> feature-branch (Incoming Change)
```
### Conflict Resolution Tools
```bash
# Use mergetool
git mergetool
# Specify merge tool
git mergetool --tool=vimdiff
git mergetool --tool=meld
git mergetool --tool=kdiff3
# Configure default merge tool
git config --global merge.tool vimdiff
git config --global mergetool.vimdiff.cmd 'vimdiff "$LOCAL" "$MERGED" "$REMOTE"'
# Check out specific version
git checkout --ours file.go # Keep our version
git checkout --theirs file.go # Keep their version
git checkout --merge file.go # Recreate conflict markers
```
### Rerere (Reuse Recorded Resolution)
```bash
# Enable rerere
git config --global rerere.enabled true
# Rerere will automatically resolve previously seen conflicts
git merge feature-branch
# Conflict occurs and is resolved
git add file.go
git commit
# Later, same conflict:
git merge another-branch
# Rerere automatically applies previous resolution
# View rerere cache
git rerere status
git rerere diff
# Clear rerere cache
git rerere forget file.go
git rerere clear
```
## Interactive Staging
### Partial File Staging
```bash
# Interactive staging
git add -p file.go
# Patch commands:
# y - stage this hunk
# n - do not stage this hunk
# q - quit (do not stage this and remaining hunks)
# a - stage this and all remaining hunks
# d - do not stage this and all remaining hunks
# s - split the current hunk into smaller hunks
# e - manually edit the current hunk
```
### Interactive Add
```bash
# Interactive mode
git add -i
# Commands:
# 1: status - show paths with changes
# 2: update - stage paths
# 3: revert - unstage paths
# 4: add untracked - stage untracked files
# 5: patch - partial staging
# 6: diff - show staged changes
# 7: quit - exit
```
### Partial Commits
```bash
# Stage part of file interactively
git add -p file.go
# Create commit with partial changes
git commit -m "feat: add validation logic"
# Stage remaining changes
git add file.go
git commit -m "feat: add error handling"
```
## Advanced Reset Operations
### Reset Modes
```bash
# Soft reset (keep changes staged)
git reset --soft HEAD~1
# Mixed reset (keep changes unstaged, default)
git reset --mixed HEAD~1
git reset HEAD~1
# Hard reset (discard all changes)
git reset --hard HEAD~1
# Reset to specific commit
git reset --hard abc123
```
### Reset vs Revert
```bash
# Reset (rewrites history, use for local changes)
git reset --hard HEAD~3
# Revert (creates new commit, safe for shared history)
git revert HEAD
git revert HEAD~3
git revert abc123..def456
```
## Advanced Branch Operations
### Branch from Specific Commit
```bash
# Create branch from commit
git branch new-branch abc123
git checkout new-branch
# Or in one command
git checkout -b new-branch abc123
# Create branch from remote commit
git checkout -b local-branch origin/remote-branch
```
### Orphan Branches
```bash
# Create orphan branch (no parent)
git checkout --orphan new-root
git rm -rf .
# Useful for gh-pages, documentation, etc.
echo "# Documentation" > README.md
git add README.md
git commit -m "docs: initialize documentation"
```
### Branch Tracking
```bash
# Set upstream branch
git branch -u origin/main
# Push and set upstream
git push -u origin feature-branch
# Change upstream
git branch -u origin/develop
# View tracking information
git branch -vv
```
## Advanced Stash Operations
### Stash Specific Files
```bash
# Stash specific files
git stash push -m "WIP: feature work" file1.go file2.go
# Stash with pathspec
git stash push -p
# Stash untracked files
git stash -u
# Stash including ignored files
git stash -a
```
### Stash to Branch
```bash
# Create branch from stash
git stash branch new-branch stash@{0}
# Creates new branch and applies stash
git stash branch feature-work
```
### Partial Stash Application
```bash
# Apply specific files from stash
git checkout stash@{0} -- file.go
# Apply stash without dropping
git stash apply stash@{0}
# Apply and drop
git stash pop stash@{0}
```
## Submodule Management
### Advanced Submodule Operations
```bash
# Update submodule to specific commit
cd submodule-dir
git checkout abc123
cd ..
git add submodule-dir
git commit -m "chore: update submodule to version 1.2.3"
# Update all submodules to latest
git submodule update --remote --merge
# Update specific submodule
git submodule update --remote --merge path/to/submodule
# Run command in all submodules
git submodule foreach 'git checkout main'
git submodule foreach 'git pull'
# Clone with submodules at specific depth
git clone --recurse-submodules --depth 1 repo-url
```
### Submodule to Subtree Migration
```bash
# Remove submodule
git submodule deinit path/to/submodule
git rm path/to/submodule
rm -rf .git/modules/path/to/submodule
# Add as subtree
git subtree add --prefix=path/to/submodule \
https://github.com/user/repo.git main --squash
# Update subtree
git subtree pull --prefix=path/to/submodule \
https://github.com/user/repo.git main --squash
```
## Advanced Log and History
### Custom Log Formatting
```bash
# One-line format with custom fields
git log --pretty=format:"%h - %an, %ar : %s"
# Full custom format
git log --pretty=format:"%C(yellow)%h%C(reset) %C(blue)%ad%C(reset) %C(green)%an%C(reset) %s" --date=short
# Aliases for common formats
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"
```
### Finding Lost Commits
```bash
# Find commits not in any branch
git log --all --oneline --no-walk --decorate $(git fsck --no-reflog | grep commit | cut -d' ' -f3)
# Find dangling commits
git fsck --lost-found
# Search commit messages
git log --all --grep="search term"
# Find commits by author
git log --author="John Doe"
# Find commits modifying specific code
git log -S "function_name"
git log -G "regex_pattern"
```
### Bisect Automation
```bash
# Start bisect
git bisect start
git bisect bad HEAD
git bisect good abc123
# Automate bisect with script
git bisect run ./test.sh
# test.sh example:
#!/bin/bash
make && make test
exit $?
# Bisect will automatically find first bad commit
```
## Best Practices
1. **Backup Before History Rewriting:** Create backup branch before complex operations
2. **Never Rewrite Published History:** Only rewrite local commits
3. **Communicate Rebases:** Inform team when force-pushing
4. **Use Descriptive Commit Messages:** Even during interactive rebase
5. **Test After Rebase:** Ensure code still works after history changes
6. **Prefer Rebase for Local Branches:** Keep history linear
7. **Use Merge for Shared Branches:** Preserve complete history
8. **Sign Important Commits:** Use GPG signing for releases
9. **Document Complex Operations:** Leave comments for future reference
10. **Know When to Stop:** Sometimes merge commits are clearer than rebased history
## Resources
Additional guides and examples are available in the `assets/` directory:
- `examples/` - Complex rebase and merge scenarios
- `scripts/` - Automation scripts for common operations
- `workflows/` - Advanced workflow patterns
See `references/` directory for:
- Git internals documentation
- Advanced rebasing strategies
- Filter-branch alternatives
- Conflict resolution techniques

View File

@@ -0,0 +1,569 @@
---
name: git-conventions
description: Git conventions and workflow best practices including Conventional Commits, branch naming, and commit message guidelines. Use when user needs guidance on git standards, commit formats, or workflow patterns.
---
# Git Conventions Skill
This skill provides comprehensive guidance on git conventions, workflow best practices, and standardized commit formats to maintain clean, readable repository history.
## When to Use
Activate this skill when:
- Writing commit messages following standards
- Establishing team git workflows
- Setting up branch naming conventions
- Implementing Conventional Commits
- Creating changelog automation
- Code review for git hygiene
- Onboarding team members on git practices
## Conventional Commits
### Format
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
### Commit Types
**Primary Types:**
- **feat**: New feature for the user
- **fix**: Bug fix for the user
- **docs**: Documentation only changes
- **style**: Code style changes (formatting, missing semi-colons, etc)
- **refactor**: Code change that neither fixes a bug nor adds a feature
- **perf**: Performance improvements
- **test**: Adding or correcting tests
- **build**: Changes to build system or dependencies
- **ci**: Changes to CI configuration files and scripts
- **chore**: Other changes that don't modify src or test files
- **revert**: Reverts a previous commit
### Examples
**Simple commit:**
```bash
feat: add user authentication
Implement JWT-based authentication system with refresh tokens.
Includes middleware for protected routes.
Closes #123
```
**Breaking change:**
```bash
feat!: redesign API response format
BREAKING CHANGE: API now returns data in camelCase instead of snake_case.
Migration guide available in docs/migration-v2.md.
Refs: #456
```
**With scope:**
```bash
fix(auth): resolve token expiration edge case
Token validation now properly handles timezone offsets.
Adds retry logic for expired tokens within 5-minute grace period.
```
**Multiple paragraphs:**
```bash
refactor(database): optimize query performance
- Add indexes on frequently queried columns
- Implement connection pooling
- Cache common queries with Redis
- Reduce N+1 queries in user associations
Performance improved by 60% in production testing.
Reviewed-by: Jane Doe <jane@example.com>
Refs: #789
```
### Commit Message Rules
1. **Subject line:**
- Use imperative mood ("add" not "added" or "adds")
- No capitalization of first letter
- No period at the end
- Maximum 50 characters (soft limit)
- Separate from body with blank line
2. **Body:**
- Wrap at 72 characters
- Explain what and why, not how
- Use bullet points for multiple items
- Reference issues and PRs
3. **Footer:**
- Breaking changes start with "BREAKING CHANGE:"
- Reference issues: "Closes #123", "Fixes #456", "Refs #789"
- Co-authors: "Co-authored-by: Name <email>"
## Branch Naming Conventions
### Format Pattern
```
<type>/<issue-number>-<short-description>
```
### Branch Types
**Common prefixes:**
- `feature/` or `feat/` - New features
- `fix/` or `bugfix/` - Bug fixes
- `hotfix/` - Urgent production fixes
- `release/` - Release preparation
- `docs/` - Documentation updates
- `refactor/` - Code refactoring
- `test/` - Test additions or fixes
- `chore/` - Maintenance tasks
- `experimental/` or `spike/` - Proof of concepts
### Examples
```bash
# Feature branches
feature/123-user-authentication
feat/456-add-payment-gateway
feature/oauth-integration
# Bug fix branches
fix/789-resolve-memory-leak
bugfix/login-redirect-loop
fix/456-null-pointer-exception
# Hotfix branches
hotfix/critical-security-patch
hotfix/production-database-issue
# Release branches
release/v1.2.0
release/2024-Q1
# Documentation branches
docs/api-reference-update
docs/123-add-contributing-guide
# Refactor branches
refactor/database-layer
refactor/456-simplify-auth-flow
# Experimental branches
experimental/graphql-api
spike/performance-optimization
```
### Branch Naming Rules
1. **Use hyphens** for word separation (not underscores)
2. **Lowercase only** (avoid capitals)
3. **Keep it short** but descriptive (max 50 characters)
4. **Include issue number** when applicable
5. **Avoid special characters** except hyphens and forward slashes
6. **No trailing slashes**
7. **Be consistent** within your team
## Protected Branch Strategy
### Main Branches
**main/master:**
- Production-ready code
- Always deployable
- Protected with required reviews
- No direct commits
- Merge only from release or hotfix branches
**develop:**
- Integration branch for features
- Pre-production testing
- Protected with CI checks
- Merge target for feature branches
**staging:**
- Pre-production environment
- QA testing branch
- Mirror of production with new features
### Protection Rules
```yaml
# Example GitHub branch protection
main:
require_pull_request_reviews:
required_approving_review_count: 2
dismiss_stale_reviews: true
require_code_owner_reviews: true
require_status_checks:
strict: true
contexts:
- continuous-integration
- code-quality
- security-scan
enforce_admins: true
require_linear_history: true
allow_force_pushes: false
allow_deletions: false
```
## Semantic Versioning
### Version Format
```
MAJOR.MINOR.PATCH[-prerelease][+build]
```
**Examples:**
- `1.0.0` - Initial release
- `1.2.3` - Minor update with patches
- `2.0.0-alpha.1` - Pre-release alpha
- `1.5.0-rc.2+20240321` - Release candidate with build metadata
### Version Increment Rules
**MAJOR (X.0.0):**
- Breaking changes
- API incompatibilities
- Major redesigns
- Removal of deprecated features
**MINOR (x.Y.0):**
- New features (backward compatible)
- Deprecated features (still functional)
- Substantial internal changes
**PATCH (x.y.Z):**
- Bug fixes
- Security patches
- Performance improvements
- Documentation updates
### Git Tags for Versions
```bash
# Create annotated tag
git tag -a v1.2.3 -m "Release version 1.2.3
- Add user authentication
- Fix memory leak in cache
- Improve API performance"
# Push tags to remote
git push origin v1.2.3
# Push all tags
git push --tags
# Create pre-release tag
git tag -a v2.0.0-beta.1 -m "Beta release for v2.0.0"
# Delete tag
git tag -d v1.2.3
git push origin :refs/tags/v1.2.3
```
## Workflow Patterns
### Git Flow
**Branch structure:**
- `main` - Production releases
- `develop` - Next release development
- `feature/*` - New features
- `release/*` - Release preparation
- `hotfix/*` - Emergency fixes
**Feature workflow:**
```bash
# Start feature
git checkout develop
git pull origin develop
git checkout -b feature/123-new-feature
# Work on feature
git add .
git commit -m "feat: implement user authentication"
# Finish feature
git checkout develop
git pull origin develop
git merge --no-ff feature/123-new-feature
git push origin develop
git branch -d feature/123-new-feature
```
**Release workflow:**
```bash
# Start release
git checkout develop
git checkout -b release/v1.2.0
# Prepare release (bump version, update changelog)
git commit -m "chore: prepare release v1.2.0"
# Merge to main
git checkout main
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release v1.2.0"
# Merge back to develop
git checkout develop
git merge --no-ff release/v1.2.0
# Cleanup
git branch -d release/v1.2.0
```
**Hotfix workflow:**
```bash
# Start hotfix from main
git checkout main
git checkout -b hotfix/critical-bug
# Fix and commit
git commit -m "fix: resolve critical security vulnerability"
# Merge to main
git checkout main
git merge --no-ff hotfix/critical-bug
git tag -a v1.2.1 -m "Hotfix v1.2.1"
# Merge to develop
git checkout develop
git merge --no-ff hotfix/critical-bug
# Cleanup
git branch -d hotfix/critical-bug
```
### GitHub Flow
**Simplified workflow:**
- `main` - Always deployable
- `feature/*` - All changes in feature branches
**Workflow:**
```bash
# Create feature branch
git checkout -b feature/add-logging
git push -u origin feature/add-logging
# Make changes and commit
git commit -m "feat: add structured logging"
git push origin feature/add-logging
# Open pull request on GitHub
# After review and CI passes, merge to main
# Deploy from main
```
### Trunk-Based Development
**Single main branch:**
- Short-lived feature branches (< 2 days)
- Frequent integration to main
- Feature flags for incomplete features
- Continuous integration
**Workflow:**
```bash
# Create short-lived branch
git checkout -b update-api-docs
git push -u origin update-api-docs
# Make small, incremental changes
git commit -m "docs: update API endpoint documentation"
git push origin update-api-docs
# Immediately create PR and merge (same day)
# Main branch always deployable with feature flags
```
## Pull Request Conventions
### PR Title Format
Use Conventional Commits format:
```
feat(auth): add OAuth2 provider support
fix(api): resolve rate limiting edge case
docs: update installation guide
```
### PR Description Template
```markdown
## Summary
Brief description of changes and motivation.
## Changes
- Bullet list of specific changes
- Reference architecture decisions
- Note any breaking changes
## Testing
- Unit tests added/updated
- Integration tests passed
- Manual testing performed
## Screenshots (if applicable)
[Add screenshots for UI changes]
## Related Issues
Closes #123
Refs #456
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] Changelog updated
- [ ] Breaking changes documented
- [ ] Code reviewed by team
```
### Review Guidelines
**Reviewer checklist:**
- [ ] Code follows style guide
- [ ] Commit messages follow conventions
- [ ] Tests are comprehensive
- [ ] Documentation is updated
- [ ] No security vulnerabilities
- [ ] Performance considerations addressed
- [ ] Breaking changes are justified
## Changelog Management
### Keep a Changelog Format
```markdown
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- User authentication with JWT tokens
- API rate limiting middleware
### Changed
- Updated database schema for better performance
### Deprecated
- Old authentication endpoint (use /api/v2/auth instead)
### Removed
- Legacy XML API support
### Fixed
- Memory leak in cache implementation
- Race condition in concurrent requests
### Security
- Patch for SQL injection vulnerability
## [1.2.0] - 2024-03-15
### Added
- Real-time notifications system
- User profile customization
### Fixed
- Login redirect loop issue
- Session timeout handling
## [1.1.0] - 2024-02-01
### Added
- Search functionality
- Export to CSV feature
### Changed
- Improved UI responsiveness
```
### Automated Changelog
Use tools like:
- `conventional-changelog` - Generate changelog from commits
- `release-please` - Automated releases and changelog
- `semantic-release` - Fully automated version management
## Best Practices
1. **Commit Often:** Small, focused commits are easier to review and revert
2. **Write Clear Messages:** Future you will thank present you
3. **One Concern Per Commit:** Each commit should address one logical change
4. **Test Before Committing:** Ensure code works before committing
5. **Reference Issues:** Link commits to issue tracker
6. **Review Your Own Changes:** Use `git diff --staged` before committing
7. **Keep History Clean:** Rebase feature branches to keep linear history
8. **Sign Your Commits:** Use GPG signing for verified commits
9. **Use .gitignore Properly:** Never commit sensitive or generated files
10. **Document Conventions:** Keep team conventions in repository docs
## Team Workflow Examples
### Small Team (2-5 developers)
```bash
# Simplified workflow
- Direct commits to main (with PR reviews)
- Feature branches for major changes
- Tags for releases
- Linear history preferred
```
### Medium Team (5-20 developers)
```bash
# Git Flow variant
- Protected main and develop branches
- Feature branches required
- Release branches for versions
- Hotfix workflow for emergencies
- Squash merge for clean history
```
### Large Team (20+ developers)
```bash
# Trunk-based with feature flags
- Protected main branch
- Very short-lived feature branches
- Feature flags for incomplete work
- Automated testing and deployment
- Multiple daily integrations
```
## Resources
Additional guides and templates are available in the `assets/` directory:
- `templates/` - Commit message and PR templates
- `examples/` - Real-world workflow examples
- `tools/` - Git hooks and automation scripts
See `references/` directory for:
- Conventional Commits specification
- Semantic Versioning documentation
- Git Flow and GitHub Flow guides
- Keep a Changelog standards

View File

@@ -0,0 +1,820 @@
---
name: git-repository
description: Repository management strategies including branch strategies (Git Flow, GitHub Flow, trunk-based), monorepo patterns, submodules, and repository organization. Use when user needs guidance on repository structure or branching strategies.
---
# Git Repository Management Skill
This skill provides comprehensive guidance on repository management strategies, branching models, repository organization patterns, and scaling git for large teams and codebases.
## When to Use
Activate this skill when:
- Setting up new repository structure
- Choosing branching strategy
- Managing monorepo vs polyrepo
- Organizing multi-project repositories
- Implementing submodule or subtree strategies
- Scaling git for large teams
- Migrating repository structures
- Establishing team workflows
## Branching Strategies
### Git Flow
**Branch Structure:**
- `main` (or `master`) - Production releases only
- `develop` - Integration branch for next release
- `feature/*` - Feature development branches
- `release/*` - Release preparation branches
- `hotfix/*` - Emergency production fixes
**Workflow:**
```bash
# Feature Development
git checkout develop
git checkout -b feature/user-authentication
# Work on feature...
git commit -m "feat: add JWT authentication"
git checkout develop
git merge --no-ff feature/user-authentication
git branch -d feature/user-authentication
# Release Preparation
git checkout develop
git checkout -b release/v1.2.0
# Bump version, update changelog, final testing...
git commit -m "chore: prepare release v1.2.0"
# Deploy Release
git checkout main
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"
git checkout develop
git merge --no-ff release/v1.2.0
git branch -d release/v1.2.0
git push origin main develop --tags
# Hotfix
git checkout main
git checkout -b hotfix/security-patch
git commit -m "fix: patch security vulnerability"
git checkout main
git merge --no-ff hotfix/security-patch
git tag -a v1.2.1 -m "Hotfix v1.2.1"
git checkout develop
git merge --no-ff hotfix/security-patch
git branch -d hotfix/security-patch
git push origin main develop --tags
```
**Best For:**
- Scheduled releases
- Multiple production versions
- Large teams with QA process
- Products with maintenance windows
- Enterprise software
**Drawbacks:**
- Complex workflow
- Long-lived branches
- Potential merge conflicts
- Delayed integration
### GitHub Flow
**Branch Structure:**
- `main` - Production-ready code (always deployable)
- `feature/*` - All feature and fix branches
**Workflow:**
```bash
# Create Feature Branch
git checkout main
git pull origin main
git checkout -b feature/add-api-logging
# Develop Feature
git commit -m "feat: add structured logging middleware"
git push -u origin feature/add-api-logging
# Open Pull Request on GitHub
# Review, discuss, CI passes
# Merge and Deploy
# Merge PR on GitHub
# Automatic deployment from main
# Cleanup
git checkout main
git pull origin main
git branch -d feature/add-api-logging
```
**Best For:**
- Continuous deployment
- Small to medium teams
- Web applications
- Rapid iteration
- Cloud-native applications
**Drawbacks:**
- Requires robust CI/CD
- No release staging
- Less structured than Git Flow
### Trunk-Based Development
**Branch Structure:**
- `main` (or `trunk`) - Single source of truth
- Short-lived feature branches (< 2 days, optional)
- Feature flags for incomplete work
**Workflow:**
```bash
# Direct Commit to Main (Small Changes)
git checkout main
git pull origin main
# Make small change...
git commit -m "fix: correct validation logic"
git push origin main
# Short-Lived Branch (Larger Changes)
git checkout -b optimize-query
# Work for < 1 day
git commit -m "perf: optimize database query"
git push -u origin optimize-query
# Immediate PR, quick review, merge same day
# Feature Flags for Incomplete Features
git checkout main
git commit -m "feat: add payment gateway (behind feature flag)"
# Feature disabled in production until complete
git push origin main
```
**Best For:**
- High-velocity teams
- Continuous integration
- Automated testing
- Feature flag infrastructure
- DevOps culture
**Drawbacks:**
- Requires discipline
- Needs comprehensive tests
- Feature flag management
- Higher deployment frequency
### Release Branch Strategy
**Branch Structure:**
- `main` - Current development
- `release/v*` - Long-lived release branches
- `feature/*` - Feature branches
**Workflow:**
```bash
# Create Release Branch
git checkout -b release/v1.0 main
git push -u origin release/v1.0
# Continue Development on Main
git checkout main
# Work on v2.0 features...
# Backport Fixes to Release
git checkout release/v1.0
git cherry-pick abc123 # Fix from main
git push origin release/v1.0
git tag -a v1.0.5 -m "Patch release v1.0.5"
git push origin v1.0.5
# Multiple Release Maintenance
git checkout release/v0.9
git cherry-pick def456
git tag -a v0.9.8 -m "Security patch v0.9.8"
```
**Best For:**
- Multiple product versions
- Long-term support releases
- Enterprise customers
- Regulated industries
**Drawbacks:**
- Maintenance overhead
- Complex cherry-picking
- Diverging codebases
### Feature Branch Workflow
**Branch Structure:**
- `main` - Stable production code
- `feature/*` - Feature branches from main
- `bugfix/*` - Bug fix branches
**Workflow:**
```bash
# Feature Development
git checkout main
git checkout -b feature/payment-integration
# Long-Running Feature (Sync with Main)
git fetch origin
git rebase origin/main
# Or merge
git merge origin/main
# Complete Feature
git push origin feature/payment-integration
# Create pull request
# After review and approval, merge to main
```
**Best For:**
- Medium-sized teams
- Code review processes
- Parallel feature development
- Quality gates before merge
## Repository Organization
### Monorepo
**Structure:**
```
monorepo/
├── .git/
├── services/
│ ├── api/
│ ├── web/
│ └── worker/
├── packages/
│ ├── shared-utils/
│ ├── ui-components/
│ └── api-client/
├── tools/
│ ├── build-tools/
│ └── scripts/
└── docs/
```
**Advantages:**
- Single source of truth
- Shared code visibility
- Atomic cross-project changes
- Unified versioning
- Simplified dependency management
- Consistent tooling
**Disadvantages:**
- Large repository size
- Slower clone/fetch
- Complex CI/CD
- Access control challenges
- Tooling requirements
**Implementation:**
```bash
# Initialize Monorepo
git init
mkdir -p services/api services/web packages/shared-utils
# Workspace Setup (Node.js example)
cat > package.json << EOF
{
"name": "monorepo",
"private": true,
"workspaces": [
"services/*",
"packages/*"
]
}
EOF
# Sparse Checkout (Partial Clone)
git clone --filter=blob:none --no-checkout <url>
cd repo
git sparse-checkout init --cone
git sparse-checkout set services/api packages/shared-utils
git checkout main
# Build Only Changed Packages
git diff --name-only HEAD~1 | grep "^services/api" && cd services/api && npm run build
```
**Tools:**
- **Bazel** - Build system for large monorepos
- **Nx** - Monorepo build system (Node.js)
- **Lerna** - JavaScript monorepo management
- **Turborepo** - High-performance build system
- **Git-subtree** - Merge external repositories
### Polyrepo
**Structure:**
```
organization/
├── api-service/ (separate repo)
├── web-app/ (separate repo)
├── mobile-app/ (separate repo)
├── shared-utils/ (separate repo)
└── documentation/ (separate repo)
```
**Advantages:**
- Clear ownership boundaries
- Independent versioning
- Smaller repository size
- Granular access control
- Flexible CI/CD
- Team autonomy
**Disadvantages:**
- Dependency version conflicts
- Cross-repo changes are complex
- Duplicated tooling/config
- Harder to refactor across repos
**Implementation:**
```bash
# Template Repository
git clone git@github.com:org/template-service.git new-service
cd new-service
rm -rf .git
git init
git remote add origin git@github.com:org/new-service.git
# Shared Configuration
# Use git submodules or packages
git submodule add git@github.com:org/shared-config.git config
```
### Monorepo vs Polyrepo Decision Matrix
| Factor | Monorepo | Polyrepo |
|--------|----------|----------|
| Team Size | Large teams | Small, autonomous teams |
| Code Sharing | High code reuse | Limited sharing |
| Deployment | Coordinated releases | Independent deployments |
| Access Control | Coarse-grained | Fine-grained |
| Repository Size | Very large | Small to medium |
| CI/CD Complexity | High | Low to medium |
| Tooling Requirements | Specialized tools | Standard git tools |
| Refactoring | Easy cross-project | Complex cross-repo |
## Submodule Management
### Basic Submodules
```bash
# Add Submodule
git submodule add https://github.com/org/shared-lib.git libs/shared
# Clone with Submodules
git clone --recurse-submodules <url>
# Initialize After Clone
git submodule init
git submodule update
# Update Submodule
cd libs/shared
git pull origin main
cd ../..
git add libs/shared
git commit -m "chore: update shared library"
# Update All Submodules
git submodule update --remote --merge
# Remove Submodule
git submodule deinit libs/shared
git rm libs/shared
rm -rf .git/modules/libs/shared
```
### Submodule Strategies
**Pinned Version Strategy:**
```bash
# Submodule points to specific commit
# Manual updates with testing
git submodule update --remote libs/shared
# Test changes...
git add libs/shared
git commit -m "chore: update shared-lib to v1.2.3"
```
**Auto-Update Strategy:**
```bash
# CI automatically updates submodules
# .github/workflows/update-submodules.yml
name: Update Submodules
on:
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
- run: git submodule update --remote
- run: git commit -am "chore: update submodules"
- run: git push
```
### Nested Submodules
```bash
# Add Nested Submodule
cd libs/framework
git submodule add https://github.com/org/utils.git utils
# Update Recursively
git submodule update --init --recursive
# Run Command in All Submodules
git submodule foreach 'git checkout main'
git submodule foreach 'git pull'
git submodule foreach --recursive 'echo $name: $(git rev-parse HEAD)'
```
## Subtree Management
### Git Subtree vs Submodule
**Subtree Advantages:**
- Simpler for contributors
- No separate clone steps
- Part of main repository history
- No broken references
**Subtree Disadvantages:**
- More complex to update
- Pollutes main history
- Larger repository
### Subtree Operations
```bash
# Add Subtree
git subtree add --prefix=libs/shared https://github.com/org/shared.git main --squash
# Update Subtree
git subtree pull --prefix=libs/shared https://github.com/org/shared.git main --squash
# Push Changes Back to Subtree
git subtree push --prefix=libs/shared https://github.com/org/shared.git feature-branch
# Split Subtree (Extract to New Repo)
git subtree split --prefix=libs/shared -b shared-lib-branch
git push git@github.com:org/new-shared-lib.git shared-lib-branch:main
```
### Subtree Workflow
```bash
# Setup Remote for Easier Management
git remote add shared-lib https://github.com/org/shared.git
# Add Subtree with Remote
git subtree add --prefix=libs/shared shared-lib main --squash
# Pull Updates
git fetch shared-lib
git subtree pull --prefix=libs/shared shared-lib main --squash
# Contribute Back
git subtree push --prefix=libs/shared shared-lib feature-branch
```
## Repository Templates
### GitHub Template Repository
```bash
# Create Template Structure
mkdir -p .github/workflows
cat > .github/workflows/ci.yml << EOF
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: make test
EOF
# Template Files
touch .gitignore README.md LICENSE CONTRIBUTING.md
mkdir -p docs src tests
# Mark as Template on GitHub Settings
# Use template to create new repositories
```
### Cookiecutter Template
```bash
# Install Cookiecutter
pip install cookiecutter
# Create from Template
cookiecutter https://github.com/org/project-template.git
# Template Structure
project-template/
├── cookiecutter.json
└── {{cookiecutter.project_name}}/
├── .git/
├── src/
├── tests/
└── README.md
```
## Large Repository Management
### Partial Clone
```bash
# Blobless Clone (No file contents initially)
git clone --filter=blob:none <url>
# Treeless Clone (Even more minimal)
git clone --filter=tree:0 <url>
# Shallow Clone (Limited History)
git clone --depth 1 <url>
# Shallow Clone with Single Branch
git clone --depth 1 --single-branch --branch main <url>
```
### Sparse Checkout
```bash
# Enable Sparse Checkout
git sparse-checkout init --cone
# Specify Directories
git sparse-checkout set src/api src/shared
# Add More Directories
git sparse-checkout add docs
# List Current Sparse Checkout
git sparse-checkout list
# Disable Sparse Checkout
git sparse-checkout disable
```
### Git LFS (Large File Storage)
```bash
# Install Git LFS
git lfs install
# Track Large Files
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "data/**"
# Track Files in .gitattributes
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text
# Clone with LFS
git clone <url>
cd repo
git lfs pull
# Migrate Existing Files to LFS
git lfs migrate import --include="*.zip"
```
## Repository Splitting
### Extract Subdirectory to New Repo
```bash
# Using git filter-repo (recommended)
git filter-repo --path services/api --path-rename services/api:
# Result: New repo with only services/api content and history
# Using git subtree
git subtree split --prefix=services/api -b api-service
mkdir ../api-service
cd ../api-service
git init
git pull ../original-repo api-service
```
### Merge Multiple Repos
```bash
# Add Remote
git remote add project-b ../project-b
# Fetch History
git fetch project-b
# Merge with Unrelated Histories
git merge --allow-unrelated-histories project-b/main
# Move Files to Subdirectory
mkdir project-b
git mv * project-b/
git commit -m "chore: organize project-b into subdirectory"
```
## Repository Maintenance
### Regular Maintenance Tasks
```bash
# Optimize Repository
git gc --aggressive
# Prune Unreachable Objects
git prune --expire now
# Verify Integrity
git fsck --full
# Repack Repository
git repack -a -d --depth=250 --window=250
# Update Server Info (for dumb HTTP)
git update-server-info
```
### Automation Script
```bash
#!/bin/bash
# repo-maintenance.sh
echo "Starting repository maintenance..."
# Fetch all branches
git fetch --all --prune
# Clean up stale branches
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D
# Garbage collection
git gc --auto
# Verify integrity
git fsck --full --strict
echo "Maintenance complete!"
```
### Scheduled Maintenance
```yaml
# .github/workflows/maintenance.yml
name: Repository Maintenance
on:
schedule:
- cron: '0 2 * * 0' # Weekly at 2 AM Sunday
jobs:
maintain:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Run Maintenance
run: |
git gc --aggressive
git prune --expire now
git fsck --full
```
## Access Control and Permissions
### Branch Protection Rules
```yaml
# Example Configuration
protected_branches:
main:
required_pull_request_reviews:
required_approving_review_count: 2
dismiss_stale_reviews: true
require_code_owner_reviews: true
required_status_checks:
strict: true
contexts:
- continuous-integration
- security-scan
enforce_admins: true
restrictions:
users: []
teams: [core-team]
```
### CODEOWNERS File
```bash
# .github/CODEOWNERS
# Global owners
* @org/core-team
# Service owners
/services/api/ @org/backend-team
/services/web/ @org/frontend-team
/services/mobile/ @org/mobile-team
# Specific files
/docs/ @org/documentation-team
/.github/ @org/devops-team
/security/ @org/security-team @org/lead-architect
# Require multiple reviews
/packages/shared/ @org/core-team @org/architecture-team
```
## Migration Strategies
### SVN to Git
```bash
# Create Authors File
svn log --quiet | grep "^r" | awk '{print $3}' | sort -u > authors.txt
# Edit authors.txt:
# john = John Doe <john@example.com>
# Convert Repository
git svn clone <svn-url> --authors-file=authors.txt --stdlayout repo
# Convert Tags and Branches
cd repo
git for-each-ref --format="%(refname:short)" refs/remotes/tags | \
cut -d / -f 3 | xargs -I {} git tag {} refs/remotes/tags/{}
# Push to Git
git remote add origin <git-url>
git push -u origin --all
git push origin --tags
```
### Mercurial to Git
```bash
# Using hg-git
hg bookmark -r default main
hg push git+ssh://git@github.com/org/repo.git
# Using fast-export
git clone https://github.com/frej/fast-export.git
mkdir git-repo && cd git-repo
git init
../fast-export/hg-fast-export.sh -r ../hg-repo
git checkout HEAD
```
## Best Practices
1. **Choose Appropriate Strategy:** Match branching model to team size and deployment frequency
2. **Document Workflows:** Keep team documentation current
3. **Automate Maintenance:** Regular repository health checks
4. **Use Branch Protection:** Enforce code review and CI
5. **Clear Ownership:** Define code owners for all areas
6. **Regular Cleanup:** Remove stale branches and merged features
7. **Monitor Repository Size:** Use LFS for large files
8. **Template Repositories:** Standardize new project structure
9. **Access Control:** Implement principle of least privilege
10. **Migration Planning:** Test migrations thoroughly before production
## Resources
Additional repository management resources are available in the `assets/` directory:
- `templates/` - Repository structure templates
- `scripts/` - Automation and maintenance scripts
- `workflows/` - CI/CD workflow examples
See `references/` directory for:
- Branching strategy comparison guides
- Monorepo tool documentation
- Enterprise git patterns
- Repository scaling strategies

View File

@@ -0,0 +1,819 @@
---
name: git-troubleshooting
description: Git troubleshooting techniques including recovering lost commits, fixing merge conflicts, resolving detached HEAD, and diagnosing repository issues. Use when user encounters git errors or needs to recover from mistakes.
---
# Git Troubleshooting Skill
This skill provides comprehensive guidance on diagnosing and resolving git issues, recovering from mistakes, fixing corrupted repositories, and handling common error scenarios.
## When to Use
Activate this skill when:
- Encountering git error messages
- Recovering lost commits or branches
- Fixing corrupted repositories
- Resolving detached HEAD state
- Handling botched merges or rebases
- Diagnosing repository issues
- Recovering from force push
- Fixing authentication problems
## Recovering Lost Commits
### Using Reflog
```bash
# View reflog (local history of HEAD)
git reflog
# View reflog for specific branch
git reflog show branch-name
# Output example:
# abc123 HEAD@{0}: commit: feat: add authentication
# def456 HEAD@{1}: commit: fix: resolve bug
# ghi789 HEAD@{2}: reset: moving to HEAD~1
# Recover lost commit
git cherry-pick abc123
# Or create branch from lost commit
git branch recovered-branch abc123
# Or reset to lost commit
git reset --hard abc123
```
### Finding Dangling Commits
```bash
# Find all unreachable objects
git fsck --lost-found
# Output:
# dangling commit abc123
# dangling blob def456
# View dangling commit
git show abc123
# Recover dangling commit
git branch recovered abc123
# Or merge it
git merge abc123
```
### Recovering Deleted Branch
```bash
# Find branch commit in reflog
git reflog
# Look for branch deletion:
# abc123 HEAD@{5}: checkout: moving from feature-branch to main
# Recreate branch
git branch feature-branch abc123
# Or if branch was merged before deletion
git log --all --oneline | grep "feature"
git branch feature-branch def456
```
### Recovering After Reset
```bash
# After accidental reset --hard
git reflog
# Find commit before reset:
# abc123 HEAD@{0}: reset: moving to HEAD~5
# def456 HEAD@{1}: commit: last good commit
# Restore to previous state
git reset --hard def456
# Or create recovery branch
git branch recovery def456
```
## Resolving Detached HEAD
### Understanding Detached HEAD
```bash
# Detached HEAD state occurs when:
git checkout abc123
git checkout v1.0.0
git checkout origin/main
# HEAD is not attached to any branch
```
### Recovering from Detached HEAD
```bash
# Check current state
git status
# HEAD detached at abc123
# Option 1: Create new branch
git checkout -b new-branch-name
# Option 2: Return to previous branch
git checkout main
# Option 3: Reattach HEAD to branch
git checkout -b temp-branch
git checkout main
git merge temp-branch
# If you made commits in detached HEAD:
git reflog
# Find the commits
git branch recovery-branch abc123
```
### Preventing Detached HEAD
```bash
# Instead of checking out tag directly
git checkout -b release-v1.0 v1.0.0
# Instead of checking out remote branch
git checkout -b local-feature origin/feature-branch
# Check if HEAD is detached
git symbolic-ref -q HEAD && echo "attached" || echo "detached"
```
## Fixing Merge Conflicts
### Understanding Conflict Markers
```
<<<<<<< HEAD (Current Change)
int result = add(a, b);
||||||| merged common ancestors (Base)
int result = sum(a, b);
=======
int sum = calculate(a, b);
>>>>>>> feature-branch (Incoming Change)
```
### Basic Conflict Resolution
```bash
# When merge conflict occurs
git status
# both modified: file.go
# View conflict
cat file.go
# Option 1: Keep ours (current branch)
git checkout --ours file.go
git add file.go
# Option 2: Keep theirs (incoming branch)
git checkout --theirs file.go
git add file.go
# Option 3: Manual resolution
# Edit file.go to resolve conflicts
git add file.go
# Complete merge
git commit
```
### Aborting Operations
```bash
# Abort merge
git merge --abort
# Abort rebase
git rebase --abort
# Abort cherry-pick
git cherry-pick --abort
# Abort revert
git revert --abort
# Abort am (apply mailbox)
git am --abort
```
### Complex Conflict Resolution
```bash
# Use merge tool
git mergetool
# View three-way diff
git diff --ours
git diff --theirs
git diff --base
# Show conflicts with context
git diff --check
# List conflicted files
git diff --name-only --diff-filter=U
# After resolving all conflicts
git add .
git commit
```
## Fixing Botched Rebase
### Recovering from Failed Rebase
```bash
# Abort current rebase
git rebase --abort
# Find state before rebase
git reflog
# abc123 HEAD@{1}: rebase: checkout main
# Return to pre-rebase state
git reset --hard HEAD@{1}
# Alternative: use ORIG_HEAD
git reset --hard ORIG_HEAD
```
### Rebase Conflicts
```bash
# During rebase conflict
git status
# both modified: file.go
# Resolve conflicts
# Edit file.go
git add file.go
git rebase --continue
# Skip problematic commit
git rebase --skip
# Edit commit during rebase
git commit --amend
git rebase --continue
```
### Rebase onto Wrong Branch
```bash
# Find original branch point
git reflog
# Reset to before rebase
git reset --hard HEAD@{5}
# Rebase onto correct branch
git rebase correct-branch
```
## Repository Corruption
### Detecting Corruption
```bash
# Check repository integrity
git fsck --full
# Check connectivity
git fsck --connectivity-only
# Verify pack files
git verify-pack -v .git/objects/pack/*.idx
```
### Fixing Corrupted Objects
```bash
# Remove corrupted object
rm .git/objects/ab/cd1234...
# Try to recover from remote
git fetch origin
# Rebuild object database
git gc --prune=now
# Aggressive cleanup
git gc --aggressive --prune=now
```
### Fixing Index Corruption
```bash
# Remove corrupted index
rm .git/index
# Rebuild index
git reset
# Or reset to HEAD
git reset --hard HEAD
```
### Recovering from Bad Pack File
```bash
# Unpack corrupted pack
git unpack-objects < .git/objects/pack/pack-*.pack
# Remove corrupted pack
rm .git/objects/pack/pack-*
# Repack repository
git repack -a -d
# Verify integrity
git fsck --full
```
## Fixing References
### Corrupted Branch References
```bash
# View all references
git show-ref
# Manual reference fix
echo "abc123def456" > .git/refs/heads/branch-name
# Or use update-ref
git update-ref refs/heads/branch-name abc123
# Delete corrupted reference
git update-ref -d refs/heads/bad-branch
```
### Fixing HEAD Reference
```bash
# HEAD is corrupted or missing
echo "ref: refs/heads/main" > .git/HEAD
# Or point to specific commit
echo "abc123def456" > .git/HEAD
# Verify HEAD
git symbolic-ref HEAD
```
### Pruning Stale References
```bash
# Remove stale remote references
git remote prune origin
# Remove all stale references
git fetch --prune
# Remove all remote branches that no longer exist
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D
```
## Undoing Changes
### Undo Last Commit (Keep Changes)
```bash
# Soft reset (changes staged)
git reset --soft HEAD~1
# Mixed reset (changes unstaged)
git reset HEAD~1
```
### Undo Last Commit (Discard Changes)
```bash
# Hard reset
git reset --hard HEAD~1
# Can still recover via reflog
git reflog
git reset --hard HEAD@{1}
```
### Undo Multiple Commits
```bash
# Reset to specific commit
git reset --hard abc123
# Revert multiple commits (creates new commits)
git revert HEAD~3..HEAD
# Interactive rebase to remove commits
git rebase -i HEAD~5
# Mark commits with 'drop' or delete lines
```
### Undo Changes to File
```bash
# Discard uncommitted changes
git checkout -- file.go
# Or in Git 2.23+
git restore file.go
# Discard staged changes
git reset HEAD file.go
git restore file.go
# Or in Git 2.23+
git restore --staged file.go
git restore file.go
# Restore file from specific commit
git checkout abc123 -- file.go
```
### Undo Public Commits
```bash
# Never use reset on public commits
# Use revert instead
git revert HEAD
git revert abc123
git revert abc123..def456
# Revert merge commit
git revert -m 1 merge-commit-hash
```
## Handling Force Push Issues
### Recovering After Force Push
```bash
# If you were force pushed over
git reflog
# abc123 HEAD@{1}: pull: Fast-forward
# Recover your commits
git reset --hard HEAD@{1}
# Create backup branch
git branch backup-branch
# Merge with force-pushed branch
git pull origin main
git merge backup-branch
```
### Preventing Force Push Damage
```bash
# Always fetch before force push
git fetch origin
# View what would be lost
git log origin/main..HEAD
# Force push with lease (safer)
git push --force-with-lease origin main
# Configure push protection
git config --global push.default simple
```
## Large File Issues
### Finding Large Files
```bash
# Find large files in history
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ {print substr($0,6)}' | \
sort --numeric-sort --key=2 | \
tail -10
# Verify current large files
git ls-files | xargs ls -lh | sort -k 5 -h -r | head -20
```
### Removing Large Files
```bash
# Using git-filter-repo (recommended)
git filter-repo --path large-file.bin --invert-paths
# Using BFG
bfg --strip-blobs-bigger-than 100M
# After removal
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push --force origin main
```
### Preventing Large Files
```bash
# Configure pre-commit hook
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
if git diff --cached --name-only | xargs du -h | awk '$1 ~ /M$|G$/' | grep .; then
echo "Error: Large file detected"
exit 1
fi
EOF
chmod +x .git/hooks/pre-commit
```
## Authentication Issues
### SSH Key Problems
```bash
# Test SSH connection
ssh -T git@github.com
# Check SSH key
ls -la ~/.ssh
# Generate new SSH key
ssh-keygen -t ed25519 -C "email@example.com"
# Add key to ssh-agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Configure SSH
cat > ~/.ssh/config << EOF
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519
EOF
```
### HTTPS Authentication
```bash
# Cache credentials
git config --global credential.helper cache
git config --global credential.helper 'cache --timeout=3600'
# Or use store (less secure)
git config --global credential.helper store
# Update remote URL
git remote set-url origin https://github.com/user/repo.git
# Use personal access token
git clone https://TOKEN@github.com/user/repo.git
```
### Permission Denied
```bash
# Check remote URL
git remote -v
# Change to SSH
git remote set-url origin git@github.com:user/repo.git
# Change to HTTPS
git remote set-url origin https://github.com/user/repo.git
# Verify permissions
ls -la .git/
chmod -R u+rw .git/
```
## Submodule Issues
### Submodule Not Initialized
```bash
# Initialize submodules
git submodule init
git submodule update
# Or in one command
git submodule update --init --recursive
```
### Detached HEAD in Submodule
```bash
# Enter submodule
cd submodule-dir
# Create branch
git checkout -b main
# Or attach to existing branch
git checkout main
git pull origin main
# Update parent repo
cd ..
git add submodule-dir
git commit -m "chore: update submodule"
```
### Submodule Conflicts
```bash
# Check submodule status
git submodule status
# Reset submodule
git submodule update --init --force
# Remove and re-add submodule
git submodule deinit -f path/to/submodule
git rm -f path/to/submodule
git submodule add <url> path/to/submodule
```
## Performance Issues
### Slow Operations
```bash
# Optimize repository
git gc --aggressive
# Repack efficiently
git repack -a -d --depth=250 --window=250
# Prune old objects
git prune --expire now
# Clean up unnecessary files
git clean -fdx
```
### Large Repository
```bash
# Shallow clone
git clone --depth 1 <url>
# Fetch only one branch
git clone --single-branch --branch main <url>
# Partial clone
git clone --filter=blob:none <url>
# Sparse checkout
git sparse-checkout init --cone
git sparse-checkout set folder1 folder2
```
### Memory Issues
```bash
# Increase memory limits
git config --global pack.windowMemory "100m"
git config --global pack.packSizeLimit "100m"
git config --global pack.threads "1"
# Disable delta compression temporarily
git config --global pack.compression 0
```
## Common Error Messages
### "fatal: refusing to merge unrelated histories"
```bash
# Allow merging unrelated histories
git pull origin main --allow-unrelated-histories
```
### "fatal: not a git repository"
```bash
# Reinitialize repository
git init
# Or check if .git directory exists
ls -la .git
# Restore from backup if corrupted
```
### "error: Your local changes would be overwritten"
```bash
# Stash changes
git stash
git pull
git stash pop
# Or discard changes
git reset --hard HEAD
git pull
```
### "error: failed to push some refs"
```bash
# Fetch and merge first
git pull origin main
# Or rebase
git pull --rebase origin main
# Force push (dangerous)
git push --force origin main
# Safer force push
git push --force-with-lease origin main
```
### "fatal: unable to access: SSL certificate problem"
```bash
# Disable SSL verification (not recommended)
git config --global http.sslVerify false
# Or update SSL certificates
git config --global http.sslCAInfo /path/to/cacert.pem
```
## Diagnostic Commands
### Repository Health Check
```bash
# Full integrity check
git fsck --full --strict
# Check connectivity
git fsck --connectivity-only
# Verify objects
git verify-pack -v .git/objects/pack/*.idx
# Check reflog
git reflog expire --dry-run --all
# Analyze repository
git count-objects -vH
```
### Debug Information
```bash
# Enable verbose logging
GIT_TRACE=1 git status
GIT_TRACE=1 git pull
# Debug specific operations
GIT_TRACE_PACKET=1 git fetch
GIT_TRACE_PERFORMANCE=1 git diff
GIT_CURL_VERBOSE=1 git push
# Configuration debugging
git config --list --show-origin
git config --list --show-scope
```
## Prevention Strategies
1. **Regular Backups:** Create backup branches before risky operations
2. **Use Reflog:** Reflog is your safety net, keep it clean
3. **Enable Rerere:** Reuse recorded conflict resolutions
4. **Protect Branches:** Use branch protection rules
5. **Pre-commit Hooks:** Validate commits before they're made
6. **Regular Maintenance:** Run `git gc` periodically
7. **Test Before Force Push:** Always verify with `--dry-run`
8. **Communication:** Inform team about disruptive operations
9. **Learn Git Internals:** Understanding how git works prevents issues
10. **Keep Git Updated:** Use latest stable version
## Resources
Additional troubleshooting guides are available in the `assets/` directory:
- `troubleshooting/` - Step-by-step recovery procedures
- `scripts/` - Diagnostic and recovery scripts
- `checklists/` - Problem diagnosis workflows
See `references/` directory for:
- Git error message database
- Recovery procedure documentation
- Git internal structure guides
- Common pitfall documentation