Skip to main content
Back to Articles

Git Advanced Workflows: Rebasing, Cherry-Pick & Flow (Complete Guide)

Master Git rebase, cherry-pick, git flow, maintain clean history, prevent merge disasters in production.

March 7, 20268 min readBy Mathematicon

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:

  1. Rebase - Clean linear history for feature branches
  2. Cherry-pick - Apply specific bugfixes
  3. Git Flow - Professional team workflow
  4. Merge - For public/shared branches
  5. Stash/Reflog - Safety nets

Understand when to use each, and you'll never lose code or create merge disasters.


Learn More

Share this article

Related Articles

Git Advanced Workflows: Rebase, Cherry-Pick, Git Flow (2026) | Mathematicon