git-advanced-workflows logo

git-advanced-workflows

Master advanced Git workflows including rebasing, cherry-picking, bisect, worktrees, and reflog to maintain clean history and recover from any situation. Use when managing complex Git histories, collaborating on feature branches, or troubleshooting repository issues.

SKILL.md

Full skill instructions

Git Advanced Workflows

Advanced Git techniques for clean history, effective collaboration, and confident recovery.

Triggers

Trigger PhraseOperation
rebase my branchInteractive or standard rebase guidance
cherry-pick a commitCherry-pick with conflict resolution
find the breaking commitGit bisect workflow
recover lost commitsReflog exploration and recovery
use git worktreesWorktree setup and management

Process

Phase 1: Assess the Situation

  1. Identify which workflow applies (rebase, cherry-pick, bisect, worktree, recovery)
  2. Check current branch state: git status, git log --oneline -10
  3. Create a safety branch before any destructive operation: git branch backup-<timestamp>
    • macOS/Linux (bash/zsh): git branch backup-$(date +%s)
    • Windows PowerShell: git branch backup-$(Get-Date -UFormat %s)

Phase 2: Execute the Workflow

Rebase: Clean Up Feature Branch Before PR
git checkout feature/user-auth
git rebase -i main
# Squash "fix typo" commits, reword messages, reorder logically
git push --force-with-lease origin feature/user-auth

Rebase operations: pick (keep), reword (change message), edit (amend content), squash (combine keeping message), fixup (combine discarding message), drop (remove).

Autosquash pattern:

git commit --fixup HEAD        # Mark as fixup for previous commit
git rebase -i --autosquash main  # Auto-marks fixup commits

Split a commit:

git rebase -i HEAD~3          # Mark commit with 'edit'
git reset HEAD^               # Reset commit, keep changes in working tree (unstaged)
git add file1.py && git commit -m "feat: add validation"
git add file2.py && git commit -m "feat: add error handling"
git rebase --continue
Cherry-Pick: Apply Hotfix to Multiple Releases
git checkout main
git commit -m "fix: critical security patch"

git checkout release/2.0
git cherry-pick abc123

git checkout release/1.9
git cherry-pick abc123
# On conflict: fix files, git add, git cherry-pick --continue

Partial cherry-pick (specific files only):

git show --name-only abc123
git restore --staged --worktree --source=abc123 -- path/to/file1.py path/to/file2.py  # --staged stages the changes so the following commit captures them
git commit -m "cherry-pick: apply specific changes from abc123"
Bisect: Find Bug Introduction
git bisect start
git bisect bad HEAD
git bisect good v2.1.0
# Git checks out middle commit. Run tests, mark good/bad, repeat.
git bisect reset  # When done

Automated bisect:

git bisect start HEAD v2.1.0
git bisect run ./test.sh
# test.sh: exit 0 = good, 125 = skip, any other non-zero = bad
Worktree: Multi-Branch Development
git worktree add ~/worktrees/myapp-hotfix hotfix/critical-bug
# Work in the new worktree using the -C flag to avoid changing the current directory.
# e.g., git -C ~/worktrees/myapp-hotfix commit -a -m "fix: critical bug"
git worktree remove ~/worktrees/myapp-hotfix  # Clean up when done
git worktree prune  # Remove stale entries

Move-safe caveat: moving a worktree after uv created .venv leaves the absolute-path shebangs in .venv/bin/* (POSIX) or .venv/Scripts/* (Windows) stale, so direct .venv/bin/pytest calls fail with "bad interpreter". Run scripts/maintenance/repair_worktree_venv.py with uv run python (or run uv sync --frozen --extra dev --reinstall) to rewrite them, and prefer uv run python -m pytest for move-safe validation. Each flag earns its place: --reinstall recreates the launchers (a plain --frozen sync no-ops when the packages already appear installed and leaves the stale shebangs unrewritten), --extra dev keeps pytest/ruff/mypy in the repaired venv, and --frozen reproduces uv.lock without re-resolving so the result matches CI.

Recovery: Undo Mistakes with Reflog
git reflog                     # Find lost commit hash
git reset --hard def456        # Restore to that state
# Or create branch: git branch recovery def456

Abort operations in progress:

git rebase --abort
git merge --abort
git cherry-pick --abort
git bisect reset

Other recovery commands:

git restore --source=abc123 path/to/file  # Restore file from commit
git reset --soft HEAD^                     # Undo commit, keep changes staged
git reflog                                 # 1. Find the hash of the desired commit
git branch recovered abc123                # 2. Create a branch from that hash (within reflog retention; ~90 days by default, configurable)

Phase 3: Verify and Clean Up

  1. Confirm working tree is clean: git status
  2. Validate history: git log --oneline matches expectations
  3. Run tests after any history rewrite
  4. Remove worktrees if created: git worktree list

Decision Guide

Rebase vs Merge

Use RebaseUse Merge
Cleaning local commits before pushIntegrating completed features into main
Keeping feature branch current with mainPreserving exact collaboration history
Creating linear history for reviewPublic branches used by others

Anti-Patterns

AvoidWhyInstead
Rebasing shared branchesRewrites history for all collaboratorsMerge for shared branches
--force without --force-with-leaseOverwrites teammates' workAlways --force-with-lease
Bisecting on dirty working treeCheckout fails with uncommitted changesCommit or stash first
Orphaned worktreesConsume disk space silentlyRemove after use
No backup before complex rebaseNo recovery path if rebase failsCreate safety branch first

Verification

  • Working tree is clean (git status)
  • Branch history matches expectations (git log --oneline)
  • Tests pass after history rewrite
  • Force push used --force-with-lease
  • Worktrees cleaned up (git worktree list)