Git Advanced Workflows: Rebasing, Cherry-Pick & Flow (Complete Guide)
The Problem You're Solving
Your Git history is a mess:
* Merge branch 'feature-2'
|\
| * Fix typo
| * WIP: implement feature
| * Oops, wrong approach
| * Actually this time
|/
* Merge branch 'feature-1'
That difference = readable history vs impossible to debug production issues 6 months later.
Git mastery appears in 24% of technical interviews and prevents merge conflicts from becoming catastrophic.
Git Fundamentals Review
Objects: Tree of Content
Commit (abc123)
āāā Tree (points to files)
ā āāā file1.js
ā āāā file2.js
ā āāā folder/
ā āāā file3.js
āāā Parent commit (def456)
āāā Author, message, timestamp
References: Pointers to Commits
HEAD ā main (currently on main)
ā
abc123 (latest commit)
main ā abc123 (branch points to commit)
feature-1 ā def456 (branch points to commit)
tag v1.0 ā abc123 (tag points to commit)
Rebase: Rewrite History
Problem: Messy Merge Commits
* Merge pull request #123 (merge commit)
|\
| * Fix typo in docs
| * Implement new feature
|/
* Previous work
Solution: Rebase Before Merging
# On feature branch
git rebase main
# Replay commits on top of main
* Implement new feature (replayed)
* Fix typo in docs (replayed)
* Previous work on main
Interactive Rebase: Reorganize Commits
# Edit last 3 commits
git rebase -i HEAD~3
Opens editor:
pick abc123 Add user auth
pick def456 Fix login bug
pick ghi789 Add tests
# Change 'pick' to:
# reword - Change commit message
# squash - Combine with previous
# fixup - Combine (discard message)
# drop - Remove commit
Example: Squash Multiple Commits
git rebase -i HEAD~4
Editor shows:
pick abc123 WIP: user auth
pick def456 Fix typo
pick ghi789 Fix another bug
pick jkl012 Actually working now
# Change to:
pick abc123 WIP: user auth
squash def456 Fix typo
squash ghi789 Fix another bug
squash jkl012 Actually working now
# Result: 1 commit instead of 4
Cherry-Pick: Apply Specific Commits
Use Case: Deploy Specific Bugfix
# Bugfix on develop branch
git log
# abc123 Fix critical database bug
# def456 Update docs
# ghi789 Clean up code
# On main branch, want ONLY bugfix
git cherry-pick abc123
# Now main has the bugfix commit
Cherry-Pick Multiple Commits
git cherry-pick abc123 def456 ghi789
# Or range
git cherry-pick abc123~2..ghi789 # abc123~2 to ghi789 (inclusive)
Handle Cherry-Pick Conflicts
# Cherry-pick fails due to conflicts
git cherry-pick abc123
# ā CONFLICT: file.js
# Resolve conflicts
vim file.js # Fix conflicts
# Continue
git cherry-pick --continue
# Or cancel
git cherry-pick --abort
Git Flow: Professional Workflow
Branches
main (production, always stable)
ā
āā release-1.0 (release candidate, bugfixes only)
ā
āā develop (next version, feature integration)
ā
āā feature/auth (new features)
āā feature/payment (new features)
āā bugfix/login (bugfixes)
Git Flow Workflow
# Start feature
git flow feature start auth
# Creates: feature/auth from develop
# Work on feature
git add .
git commit -m "Add authentication"
# Finish feature
git flow feature finish auth
# Merges feature/auth ā develop
# Deletes feature/auth
# Release
git flow release start 1.0.0
# Creates: release-1.0.0 from develop
# Only bugfixes allowed
# Finish release
git flow release finish 1.0.0
# Merges release-1.0.0 ā main
# Tags: v1.0.0
# Merges back ā develop
Rebase vs Merge: Choose Your Path
Merge (Creates Merge Commit)
git merge feature-branch
Result:
* Merge commit
|\
| * Feature commit
| * Feature commit
|/
* Main commit
History: Shows full branch history (branching points visible)
Pros: Preserves history, safe, shows branching Cons: Cluttered history with merge commits
Rebase (Rewrites History)
git rebase main
Result:
* Feature commit (replayed)
* Feature commit (replayed)
* Main commit
History: Linear, clean (no merge commits)
Pros: Clean history, linear Cons: Rewrites commits (don't rebase pushed commits!)
When to Use Each
Public shared branch (main): Use MERGE (don't rewrite)
Personal feature branch: Use REBASE (clean history)
Pulling latest changes: Use REBASE (linear history)
Merging PR: Use MERGE (preserves contribution)
Unpushed commits (local): Use REBASE (safe to rewrite)
Advanced Techniques
Stash: Temporarily Save Work
# Save uncommitted changes
git stash
# Work on something else
git checkout main
git fix-bug
# Restore saved changes
git stash pop
# Or list/apply specific stash
git stash list
git stash apply stash@{0}
Reflog: Recover Lost Commits
# Accidentally deleted branch?
git reflog
# abc123 checkout: main
# def456 reset: HEAD~1
# ghi789 rebase: interactive
# Recover
git checkout ghi789
git branch recovered-branch
Bisect: Find Breaking Commit
# Binary search to find bug
git bisect start
git bisect bad HEAD # Current commit broken
git bisect good v1.0 # This version works
# Git checks out middle commit
# You test...
git bisect good # This one is OK
# Continues narrowing down...
git bisect bad # This one breaks it
# Eventually finds exact commit that broke it
Real-World Workflow: Fix Production Bug
# Bug reported in production (v1.5)
git checkout main
# Create hotfix
git checkout -b hotfix/critical-bug
vim bug-fix.js
git add .
git commit -m "Fix critical database bug"
# Test locally
npm test
# Merge back to main
git checkout main
git merge --no-ff hotfix/critical-bug
git tag v1.5.1
# Also merge to develop (don't leave branch behind)
git checkout develop
git merge hotfix/critical-bug
# Cleanup
git branch -d hotfix/critical-bug
git push origin main develop --tags
Common Mistakes
ā Mistake 1: Rewriting Pushed Commits
# WRONG - Rewrites public commit history
git rebase main # If already pushed
git push --force # Force-pushing public commits!
# CORRECT - Use merge for public commits
git merge main
# Exception: If team agrees (like squashing PR before merge)
git rebase -i HEAD~3
git push --force-with-lease origin feature-branch
ā Mistake 2: Cherry-Pick Instead of Merge
# WRONG - Creates duplicate commits
git cherry-pick abc123 # On main
# Later...
git merge feature # Commit abc123 exists twice!
# CORRECT - Use merge
git merge feature
ā Mistake 3: Forgetting to Squash Before Merging
# WRONG - Commits merge message in history
git merge feature # 50 "WIP" commits appear
# CORRECT - Squash locally first
git rebase -i main # Squash 50 ā 1
git merge --ff-only feature # Fast-forward merge
FAQ: Git Mastery
Q1: How do I undo a commit that's already pushed?
A: Use revert (creates new commit).
git revert abc123 # Creates new commit that undoes abc123
# OR reset (rewrite history - only if not pushed)
git reset --hard abc123^ # Reset to before abc123
Q2: How do I rename a branch?
A: Use branch -m.
# Rename current branch
git branch -m new-name
# Rename other branch
git branch -m old-name new-name
# Push after rename
git push -u origin new-name
Q3: Interview Question: Fix a complex merge conflict.
A: Here's the approach:
# Conflict during rebase
git rebase main
# CONFLICT: file.js
# 1. See all versions
git show :1:file.js # Base version
git show :2:file.js # Our version
git show :3:file.js # Their version
# 2. Edit conflicts
vim file.js
# Fix manually or use tool
git mergetool
# 3. Mark resolved
git add file.js
# 4. Continue
git rebase --continue
# OR abort if it's too messy
git rebase --abort
Q4: What's --force-with-lease?
A: Safer force push.
# WRONG - Blindly overwrites everything
git push --force
# CORRECT - Only overwrites if remote hasn't changed
git push --force-with-lease
# If someone pushed while you were rebasing, it fails
# (safer than --force which always overwrites)
Conclusion
Master Git workflows:
- Rebase - Clean linear history for feature branches
- Cherry-pick - Apply specific bugfixes
- Git Flow - Professional team workflow
- Merge - For public/shared branches
- Stash/Reflog - Safety nets
Understand when to use each, and you'll never lose code or create merge disasters.