{"skill":{"slug":"git-workflows","displayName":"Git Workflows","summary":"Advanced git operations beyond add/commit/push. Use when rebasing, bisecting bugs, using worktrees for parallel development, recovering with reflog, managing subtrees/submodules, resolving merge conflicts, cherry-picking across branches, or working with monorepos.","description":"---\nname: git-workflows\ndescription: Advanced git operations beyond add/commit/push. Use when rebasing, bisecting bugs, using worktrees for parallel development, recovering with reflog, managing subtrees/submodules, resolving merge conflicts, cherry-picking across branches, or working with monorepos.\nmetadata: {\"clawdbot\":{\"emoji\":\"🌿\",\"requires\":{\"bins\":[\"git\"]},\"os\":[\"linux\",\"darwin\",\"win32\"]}}\n---\n\n# Git Workflows\n\nAdvanced git operations for real-world development. Covers interactive rebase, bisect, worktree, reflog recovery, subtrees, submodules, sparse checkout, conflict resolution, and monorepo patterns.\n\n## When to Use\n\n- Cleaning up commit history before merging (interactive rebase)\n- Finding which commit introduced a bug (bisect)\n- Working on multiple branches simultaneously (worktree)\n- Recovering lost commits or undoing mistakes (reflog)\n- Managing shared code across repos (subtree/submodule)\n- Resolving complex merge conflicts\n- Cherry-picking commits across branches or forks\n- Working with large monorepos (sparse checkout)\n\n## Interactive Rebase\n\n### Squash, reorder, edit commits\n\n```bash\n# Rebase last 5 commits interactively\ngit rebase -i HEAD~5\n\n# Rebase onto main (all commits since diverging)\ngit rebase -i main\n```\n\nThe editor opens with a pick list:\n\n```\npick a1b2c3d Add user model\npick e4f5g6h Fix typo in user model\npick i7j8k9l Add user controller\npick m0n1o2p Add user routes\npick q3r4s5t Fix import in controller\n```\n\nCommands available:\n```\npick   = use commit as-is\nreword = use commit but edit the message\nedit   = stop after this commit to amend it\nsquash = merge into previous commit (keep both messages)\nfixup  = merge into previous commit (discard this message)\ndrop   = remove the commit entirely\n```\n\n### Common patterns\n\n```bash\n# Squash fix commits into their parent\n# Change \"pick\" to \"fixup\" for the fix commits:\npick a1b2c3d Add user model\nfixup e4f5g6h Fix typo in user model\npick i7j8k9l Add user controller\nfixup q3r4s5t Fix import in controller\npick m0n1o2p Add user routes\n\n# Reorder commits (just move lines)\npick i7j8k9l Add user controller\npick m0n1o2p Add user routes\npick a1b2c3d Add user model\n\n# Split a commit into two\n# Mark as \"edit\", then when it stops:\ngit reset HEAD~\ngit add src/model.ts\ngit commit -m \"Add user model\"\ngit add src/controller.ts\ngit commit -m \"Add user controller\"\ngit rebase --continue\n```\n\n### Autosquash (commit messages that auto-arrange)\n\n```bash\n# When committing a fix, reference the commit to squash into\ngit commit --fixup=a1b2c3d -m \"Fix typo\"\n# or\ngit commit --squash=a1b2c3d -m \"Additional changes\"\n\n# Later, rebase with autosquash\ngit rebase -i --autosquash main\n# fixup/squash commits are automatically placed after their targets\n```\n\n### Abort or continue\n\n```bash\ngit rebase --abort      # Cancel and restore original state\ngit rebase --continue   # Continue after resolving conflicts or editing\ngit rebase --skip       # Skip the current commit and continue\n```\n\n## Bisect (Find the Bug)\n\n### Binary search through commits\n\n```bash\n# Start bisect\ngit bisect start\n\n# Mark current commit as bad (has the bug)\ngit bisect bad\n\n# Mark a known-good commit (before the bug existed)\ngit bisect good v1.2.0\n# or: git bisect good abc123\n\n# Git checks out a middle commit. Test it, then:\ngit bisect good   # if this commit doesn't have the bug\ngit bisect bad    # if this commit has the bug\n\n# Repeat until git identifies the exact commit\n# \"abc123 is the first bad commit\"\n\n# Done — return to original branch\ngit bisect reset\n```\n\n### Automated bisect (with a test script)\n\n```bash\n# Fully automatic: git runs the script on each commit\n# Script must exit 0 for good, 1 for bad\ngit bisect start HEAD v1.2.0\ngit bisect run ./test-for-bug.sh\n\n# Example test script\ncat > /tmp/test-for-bug.sh << 'EOF'\n#!/bin/bash\n# Return 0 if bug is NOT present, 1 if it IS\nnpm test -- --grep \"login should redirect\" 2>/dev/null\nEOF\nchmod +x /tmp/test-for-bug.sh\ngit bisect run /tmp/test-for-bug.sh\n```\n\n### Bisect with build failures\n\n```bash\n# If a commit doesn't compile, skip it\ngit bisect skip\n\n# Skip a range of known-broken commits\ngit bisect skip v1.3.0..v1.3.5\n```\n\n## Worktree (Parallel Branches)\n\n### Work on multiple branches simultaneously\n\n```bash\n# Add a worktree for a different branch\ngit worktree add ../myproject-hotfix hotfix/urgent-fix\n# Creates a new directory with that branch checked out\n\n# Add a worktree with a new branch\ngit worktree add ../myproject-feature -b feature/new-thing\n\n# List worktrees\ngit worktree list\n\n# Remove a worktree when done\ngit worktree remove ../myproject-hotfix\n\n# Prune stale worktree references\ngit worktree prune\n```\n\n### Use cases\n\n```bash\n# Review a PR while keeping your current work untouched\ngit worktree add ../review-pr-123 origin/pr-123\n\n# Run tests on main while developing on feature branch\ngit worktree add ../main-tests main\ncd ../main-tests && npm test\n\n# Compare behavior between branches side by side\ngit worktree add ../compare-old release/v1.0\ngit worktree add ../compare-new release/v2.0\n```\n\n## Reflog (Recovery)\n\n### See everything git remembers\n\n```bash\n# Show reflog (all HEAD movements)\ngit reflog\n# Output:\n# abc123 HEAD@{0}: commit: Add feature\n# def456 HEAD@{1}: rebase: moving to main\n# ghi789 HEAD@{2}: checkout: moving from feature to main\n\n# Show reflog for a specific branch\ngit reflog show feature/my-branch\n\n# Show with timestamps\ngit reflog --date=relative\n```\n\n### Recover from mistakes\n\n```bash\n# Undo a bad rebase (find the commit before rebase in reflog)\ngit reflog\n# Find: \"ghi789 HEAD@{5}: checkout: moving from feature to main\" (pre-rebase)\ngit reset --hard ghi789\n\n# Recover a deleted branch\ngit reflog\n# Find the last commit on that branch\ngit branch recovered-branch abc123\n\n# Recover after reset --hard\ngit reflog\ngit reset --hard HEAD@{2}   # Go back 2 reflog entries\n\n# Recover a dropped stash\ngit fsck --unreachable | grep commit\n# or\ngit stash list  # if it's still there\ngit log --walk-reflogs --all -- stash  # find dropped stash commits\n```\n\n## Cherry-Pick\n\n### Copy specific commits to another branch\n\n```bash\n# Pick a single commit\ngit cherry-pick abc123\n\n# Pick multiple commits\ngit cherry-pick abc123 def456 ghi789\n\n# Pick a range (exclusive start, inclusive end)\ngit cherry-pick abc123..ghi789\n\n# Pick without committing (stage changes only)\ngit cherry-pick --no-commit abc123\n\n# Cherry-pick from another remote/fork\ngit remote add upstream https://github.com/other/repo.git\ngit fetch upstream\ngit cherry-pick upstream/main~3   # 3rd commit from upstream's main\n```\n\n### Handle conflicts during cherry-pick\n\n```bash\n# If conflicts arise:\n# 1. Resolve conflicts in the files\n# 2. Stage resolved files\ngit add resolved-file.ts\n# 3. Continue\ngit cherry-pick --continue\n\n# Or abort\ngit cherry-pick --abort\n```\n\n## Subtree and Submodule\n\n### Subtree (simpler — copies code into your repo)\n\n```bash\n# Add a subtree\ngit subtree add --prefix=lib/shared https://github.com/org/shared-lib.git main --squash\n\n# Pull updates from upstream\ngit subtree pull --prefix=lib/shared https://github.com/org/shared-lib.git main --squash\n\n# Push local changes back to upstream\ngit subtree push --prefix=lib/shared https://github.com/org/shared-lib.git main\n\n# Split subtree into its own branch (for extraction)\ngit subtree split --prefix=lib/shared -b shared-lib-standalone\n```\n\n### Submodule (pointer to another repo at a specific commit)\n\n```bash\n# Add a submodule\ngit submodule add https://github.com/org/shared-lib.git lib/shared\n\n# Clone a repo with submodules\ngit clone --recurse-submodules https://github.com/org/main-repo.git\n\n# Initialize submodules after clone (if forgot --recurse)\ngit submodule update --init --recursive\n\n# Update submodules to latest\ngit submodule update --remote\n\n# Remove a submodule\ngit rm lib/shared\nrm -rf .git/modules/lib/shared\n# Remove entry from .gitmodules if it persists\n```\n\n### When to use which\n\n```\nSubtree: Simpler, no special commands for cloners, code lives in your repo.\n         Use when: shared library, vendor code, infrequent upstream changes.\n\nSubmodule: Pointer to exact commit, smaller repo, clear separation.\n           Use when: large dependency, independent release cycle, many contributors.\n```\n\n## Sparse Checkout (Monorepo)\n\n### Check out only the directories you need\n\n```bash\n# Enable sparse checkout\ngit sparse-checkout init --cone\n\n# Select directories\ngit sparse-checkout set packages/my-app packages/shared-lib\n\n# Add another directory\ngit sparse-checkout add packages/another-lib\n\n# List what's checked out\ngit sparse-checkout list\n\n# Disable (check out everything again)\ngit sparse-checkout disable\n```\n\n### Clone with sparse checkout (large monorepos)\n\n```bash\n# Partial clone + sparse checkout (fastest for huge repos)\ngit clone --filter=blob:none --sparse https://github.com/org/monorepo.git\ncd monorepo\ngit sparse-checkout set packages/my-service\n\n# No-checkout clone (just metadata)\ngit clone --no-checkout https://github.com/org/monorepo.git\ncd monorepo\ngit sparse-checkout set packages/my-service\ngit checkout main\n```\n\n## Conflict Resolution\n\n### Understand the conflict markers\n\n```\n<<<<<<< HEAD (or \"ours\")\nYour changes on the current branch\n=======\nTheir changes from the incoming branch\n>>>>>>> feature-branch (or \"theirs\")\n```\n\n### Resolution strategies\n\n```bash\n# Accept all of ours (current branch wins)\ngit checkout --ours path/to/file.ts\ngit add path/to/file.ts\n\n# Accept all of theirs (incoming branch wins)\ngit checkout --theirs path/to/file.ts\ngit add path/to/file.ts\n\n# Accept ours for ALL files\ngit checkout --ours .\ngit add .\n\n# Use a merge tool\ngit mergetool\n\n# See the three-way diff (base, ours, theirs)\ngit diff --cc path/to/file.ts\n\n# Show common ancestor version\ngit show :1:path/to/file.ts   # base (common ancestor)\ngit show :2:path/to/file.ts   # ours\ngit show :3:path/to/file.ts   # theirs\n```\n\n### Rebase conflict workflow\n\n```bash\n# During rebase, conflicts appear one commit at a time\n# 1. Fix the conflict in the file\n# 2. Stage the fix\ngit add fixed-file.ts\n# 3. Continue to next commit\ngit rebase --continue\n# 4. Repeat until done\n\n# If a commit is now empty after resolution\ngit rebase --skip\n```\n\n### Rerere (reuse recorded resolutions)\n\n```bash\n# Enable rerere globally\ngit config --global rerere.enabled true\n\n# Git remembers how you resolved conflicts\n# Next time the same conflict appears, it auto-resolves\n\n# See recorded resolutions\nls .git/rr-cache/\n\n# Forget a bad resolution\ngit rerere forget path/to/file.ts\n```\n\n## Stash Patterns\n\n```bash\n# Stash with a message\ngit stash push -m \"WIP: refactoring auth flow\"\n\n# Stash specific files\ngit stash push -m \"partial stash\" -- src/auth.ts src/login.ts\n\n# Stash including untracked files\ngit stash push -u -m \"with untracked\"\n\n# List stashes\ngit stash list\n\n# Apply most recent stash (keep in stash list)\ngit stash apply\n\n# Apply and remove from stash list\ngit stash pop\n\n# Apply a specific stash\ngit stash apply stash@{2}\n\n# Show what's in a stash\ngit stash show -p stash@{0}\n\n# Create a branch from a stash\ngit stash branch new-feature stash@{0}\n\n# Drop a specific stash\ngit stash drop stash@{1}\n\n# Clear all stashes\ngit stash clear\n```\n\n## Blame and Log Archaeology\n\n```bash\n# Who changed each line (with date)\ngit blame src/auth.ts\n\n# Blame a specific line range\ngit blame -L 50,70 src/auth.ts\n\n# Ignore whitespace changes in blame\ngit blame -w src/auth.ts\n\n# Find when a line was deleted (search all history)\ngit log -S \"function oldName\" --oneline\n\n# Find when a regex pattern was added/removed\ngit log -G \"TODO.*hack\" --oneline\n\n# Follow a file through renames\ngit log --follow --oneline -- src/new-name.ts\n\n# Show the commit that last touched each line, ignoring moves\ngit blame -M src/auth.ts\n\n# Show log with file changes\ngit log --stat --oneline -20\n\n# Show all commits affecting a specific file\ngit log --oneline -- src/auth.ts\n\n# Show diff of a specific commit\ngit show abc123\n```\n\n## Tags and Releases\n\n```bash\n# Create annotated tag (preferred for releases)\ngit tag -a v1.2.0 -m \"Release 1.2.0: Added auth module\"\n\n# Create lightweight tag\ngit tag v1.2.0\n\n# Tag a past commit\ngit tag -a v1.1.0 abc123 -m \"Retroactive tag for release 1.1.0\"\n\n# List tags\ngit tag -l\ngit tag -l \"v1.*\"\n\n# Push tags\ngit push origin v1.2.0      # Single tag\ngit push origin --tags       # All tags\n\n# Delete a tag\ngit tag -d v1.2.0            # Local\ngit push origin --delete v1.2.0  # Remote\n```\n\n## Tips\n\n- `git rebase -i` is the single most useful advanced git command. Learn it first.\n- Never rebase commits that have been pushed to a shared branch. Rebase your local/feature work only.\n- `git reflog` is your safety net. If you lose commits, they're almost always recoverable within 90 days.\n- `git bisect run` with an automated test is faster than manual binary search and eliminates human error.\n- Worktrees are cheaper than multiple clones — they share `.git` storage.\n- Prefer `git subtree` over `git submodule` unless you have a specific reason. Subtrees are simpler for collaborators.\n- Enable `rerere` globally. It remembers conflict resolutions so you never solve the same conflict twice.\n- `git stash push -m \"description\"` is much better than bare `git stash`. You'll thank yourself when you have 5 stashes.\n- `git log -S \"string\"` (pickaxe) is the fastest way to find when a function or variable was added or removed.\n","tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":12899,"installsAllTime":460,"installsCurrent":124,"stars":5,"versions":1},"createdAt":1770158556308,"updatedAt":1778486013286},"latestVersion":{"version":"1.0.0","createdAt":1770158556308,"changelog":"Initial release: Interactive rebase, bisect, worktree, reflog recovery, cherry-pick, subtree/submodule, sparse checkout, conflict resolution, stash patterns, blame archaeology","license":null},"metadata":{"setup":[],"os":["linux","darwin","win32"],"systems":null},"owner":{"handle":"gitgoodordietrying","userId":"s17bsk9s8a501ckx95hd6m2b75885xxv","displayName":"gitgoodordietrying","image":"https://avatars.githubusercontent.com/u/116975874?v=4"},"moderation":null}