From 4f8b6d7dd87a3f41894fae2018944fc407c76cdf Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sat, 29 Nov 2025 18:28:17 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 26 + README.md | 3 + commands/bisect.md | 421 ++++++++++++++ commands/branch-cleanup.md | 766 ++++++++++++++++++++++++++ commands/cherry-pick-helper.md | 745 +++++++++++++++++++++++++ commands/commit.md | 323 +++++++++++ commands/fixup.md | 721 ++++++++++++++++++++++++ commands/rebase-interactive.md | 704 ++++++++++++++++++++++++ commands/reflog-recover.md | 774 ++++++++++++++++++++++++++ commands/stash-manager.md | 751 +++++++++++++++++++++++++ commands/worktree.md | 567 +++++++++++++++++++ plugin.lock.json | 93 ++++ skills/git-advanced/SKILL.md | 715 ++++++++++++++++++++++++ skills/git-conventions/SKILL.md | 569 +++++++++++++++++++ skills/git-repository/SKILL.md | 820 ++++++++++++++++++++++++++++ skills/git-troubleshooting/SKILL.md | 819 +++++++++++++++++++++++++++ 16 files changed, 8817 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 commands/bisect.md create mode 100644 commands/branch-cleanup.md create mode 100644 commands/cherry-pick-helper.md create mode 100644 commands/commit.md create mode 100644 commands/fixup.md create mode 100644 commands/rebase-interactive.md create mode 100644 commands/reflog-recover.md create mode 100644 commands/stash-manager.md create mode 100644 commands/worktree.md create mode 100644 plugin.lock.json create mode 100644 skills/git-advanced/SKILL.md create mode 100644 skills/git-conventions/SKILL.md create mode 100644 skills/git-repository/SKILL.md create mode 100644 skills/git-troubleshooting/SKILL.md diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..7255579 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -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" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a9c15c --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# git + +Git focused utilities with namespaced commands for advanced workflows diff --git a/commands/bisect.md b/commands/bisect.md new file mode 100644 index 0000000..62f7998 --- /dev/null +++ b/commands/bisect.md @@ -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 ` + - 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 + ``` + - 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 +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 diff --git a/commands/branch-cleanup.md b/commands/branch-cleanup.md new file mode 100644 index 0000000..38779e8 --- /dev/null +++ b/commands/branch-cleanup.md @@ -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 + ``` + +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 + ``` + + Or force delete if needed: + ```bash + git branch -D + ``` + +### 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 + ``` + +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 + ``` + +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 diff --git a/commands/cherry-pick-helper.md b/commands/cherry-pick-helper.md new file mode 100644 index 0000000..977cde5 --- /dev/null +++ b/commands/cherry-pick-helper.md @@ -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 [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 + ``` + + 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 + ``` + +9. **For multiple commits:** + ```bash + git cherry-pick + ``` + + Or range: + ```bash + git cherry-pick ^.. + ``` + +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 + ``` + - Explain conflict sections: + - `<<<<<<< HEAD` - Current branch changes + - `=======` - Separator + - `>>>>>>> ` - 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 + 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 " + 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 " + 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 +# 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 + +# Or: --no-commit +git cherry-pick --no-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 + +# -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 + +# Or: --edit +git cherry-pick --edit + +# 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 : > +git add +git commit -m "Cherry-picked changes from " + +# Or more elegantly: +git checkout -- +git commit -m "Cherry-picked from " +``` + +### Interactive Cherry-Pick + +```bash +# Cherry-pick with interactive conflict resolution +git cherry-pick +# 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 diff --git a/commands/commit.md b/commands/commit.md new file mode 100644 index 0000000..3669707 --- /dev/null +++ b/commands/commit.md @@ -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: + +``` +[optional scope]: + +[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: + +``` +/ +``` + +For features and fixes that are tracked in a project management system, include the ticket number: + +``` +/- +``` + +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 ` + - 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: `(): ` +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 ` + +### 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. diff --git a/commands/fixup.md b/commands/fixup.md new file mode 100644 index 0000000..d18697e --- /dev/null +++ b/commands/fixup.md @@ -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= + ``` + + 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= + ``` + +### 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 + ``` + + 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 " + 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 " + 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 # 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 " + 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! + +# 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 +/git:fixup +``` + +## Workflow Integration + +### With Pull Requests + +```bash +# During code review, got feedback on specific commit +# Make fixes +git add +git commit --fixup= + +# 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 +git commit --fixup= + +# 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 +git commit --fixup= + +# 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 diff --git a/commands/rebase-interactive.md b/commands/rebase-interactive.md new file mode 100644 index 0000000..8f71776 --- /dev/null +++ b/commands/rebase-interactive.md @@ -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 ..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 + ``` + +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 + + # Options: + # 1. Manually edit files to resolve + # 2. Use mergetool: git mergetool + # 3. Accept theirs: git checkout --theirs + # 4. Accept ours: git checkout --ours + # 5. Skip commit: git rebase --skip + # 6. Abort rebase: git rebase --abort + ``` + +25. **After resolving:** + ```bash + git add + 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 ..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 ..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 ..." + 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 HEAD + + if [ -z "$(git diff 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 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 " + 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 diff --git a/commands/reflog-recover.md b/commands/reflog-recover.md new file mode 100644 index 0000000..faef694 --- /dev/null +++ b/commands/reflog-recover.md @@ -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 "" + ``` + +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 + ``` + - Safest option + - Preserves current state + - Can review before merging + - Recommended for most cases + + **Option B: Reset current branch** + ```bash + git reset --hard + ``` + - Moves current branch + - Loses commits after target + - Use with caution + - Create backup branch first + + **Option C: Cherry-pick commit** + ```bash + git cherry-pick + ``` + - Apply specific commit + - Keep current history + - Good for selective recovery + + **Option D: Merge recovered commit** + ```bash + git branch temp-recovery + 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 + ``` + +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 + ``` + +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 " + 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 diff --git a/commands/stash-manager.md b/commands/stash-manager.md new file mode 100644 index 0000000..b7d19f1 --- /dev/null +++ b/commands/stash-manager.md @@ -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 [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 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 (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 +# +# 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 +# +# 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 diff --git a/commands/worktree.md b/commands/worktree.md new file mode 100644 index 0000000..67e0b10 --- /dev/null +++ b/commands/worktree.md @@ -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 [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 + ``` + + For existing branch: + ```bash + git worktree add + ``` + + Create worktree and checkout: + ```bash + git worktree add + # 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 + ``` + + Or force removal: + ```bash + git worktree remove --force + ``` + +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" + ``` + +17. **Unlock worktree:** + ```bash + git worktree unlock + ``` + +## 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 diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..1fddbde --- /dev/null +++ b/plugin.lock.json @@ -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": [] + } +} \ No newline at end of file diff --git a/skills/git-advanced/SKILL.md b/skills/git-advanced/SKILL.md new file mode 100644 index 0000000..a4a6dbb --- /dev/null +++ b/skills/git-advanced/SKILL.md @@ -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 " + +# 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 " +``` + +### 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 diff --git a/skills/git-conventions/SKILL.md b/skills/git-conventions/SKILL.md new file mode 100644 index 0000000..43de706 --- /dev/null +++ b/skills/git-conventions/SKILL.md @@ -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 + +``` +[optional scope]: + +[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 +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 " + +## Branch Naming Conventions + +### Format Pattern + +``` +/- +``` + +### 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 diff --git a/skills/git-repository/SKILL.md b/skills/git-repository/SKILL.md new file mode 100644 index 0000000..72637c9 --- /dev/null +++ b/skills/git-repository/SKILL.md @@ -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 +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 + +# 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 + +# Treeless Clone (Even more minimal) +git clone --filter=tree:0 + +# Shallow Clone (Limited History) +git clone --depth 1 + +# Shallow Clone with Single Branch +git clone --depth 1 --single-branch --branch main +``` + +### 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 +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 + +# Convert Repository +git svn clone --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 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 diff --git a/skills/git-troubleshooting/SKILL.md b/skills/git-troubleshooting/SKILL.md new file mode 100644 index 0000000..3676ac4 --- /dev/null +++ b/skills/git-troubleshooting/SKILL.md @@ -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 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 + +# Fetch only one branch +git clone --single-branch --branch main + +# Partial clone +git clone --filter=blob:none + +# 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