Back to Git: Branching, Merge, Rebase
Q1Question 1 of 6

`git merge` vs `git rebase`, and what `stash` and `cherry-pick` do

Key Concepts
  • git merge creates a merge commit with two parents, preserving the true branching history without rewriting anything.
  • git rebase replays commits onto a new base, creating new commits with new hashes for a clean linear history.
  • Merge is non-destructive and safe for shared branches; rebase rewrites history and is safe only on private branches.
  • git stash temporarily shelves uncommitted changes so you can switch branches for urgent work, then pop them back.
  • git cherry-pick copies one specific commit from any branch as a new commit on your current branch.
  • Cherry-pick is best for targeted hotfix propagation; overuse across long-lived branches creates duplicated commits.
  • The rule: rebase private branches for clean history, merge shared branches for honest history.

Definition

Merge joins histories with a merge commit; rebase replays commits for a linear history; stash shelves uncommitted work; cherry-pick copies one specific commit.
  • git merge -- integrates one branch into another by creating a new merge commit with two parents, preserving the true branching history.
  • git rebase -- integrates by replaying commits one at a time onto a new base, producing new commits and a clean linear history.
  • Merge commit -- a special commit with two parents that records where two lines of work joined.
  • git stash -- temporarily shelves uncommitted changes (staged and unstaged) so your working tree is clean.
  • git stash pop -- reapplies the most recently stashed changes and removes them from the stash stack.
  • git cherry-pick -- copies one specific commit from any branch and applies it as a new commit on your current branch.

Think of two ways to combine ledger corrections at National Bank of India. Merge is like stapling both sets together with a cover note saying these two streams were combined on this date -- the history honestly shows two parallel efforts joining. Rebase is like rewriting your corrections as if you started from the other set, so everything reads as one straight sequence. Stash is like sweeping half-finished draft forms into a labeled tray so your desk is clear for an urgent task. Cherry-pick is spotting one correction in another officer's batch and copying just that single correction into your own.

Understanding the Concepts

How does git merge work?

Merge brings branches together by creating a merge commit with two parents -- the tip of your branch and the tip of the branch you merged in. Nothing is rewritten. All original commits keep their hashes. The graph honestly shows that two lines diverged and joined.

BASH
# Merge main into feature branch
git checkout feature/emi-calculation
git merge main
TEXT
# Before merge:
# main:    A -- B -- C
# feature:      \-- D -- E

# After merge:
# main:    A -- B -- C
# feature:      \-- D -- E -- M (merge commit, parents: E and C)
BASH
git log --oneline --graph
TEXT
*   f4e5d6 Merge branch 'main' into feature/emi-calculation
|\  
| * c3d4e5 fix: correct rounding in fee calculation
* | b2c3d4 feat: add EMI edge case test
* | a1b2c3 feat: add EMI calculation
|/
* 901234 initial commit

How does git rebase work?

Rebase takes your commits, sets them aside, fast-forwards to the tip of the target, and replays your commits on top one at a time. The result is a straight line with no merge commits. The commits get new hashes because their parent changed.

BASH
# Rebase feature onto main
git checkout feature/emi-calculation
git rebase main
TEXT
# Before rebase:
# main:    A -- B -- C
# feature:      \-- D -- E

# After rebase:
# main:    A -- B -- C -- D' -- E'
# D' and E' are NEW commits
BASH
git log --oneline --graph
TEXT
* e6f7g8 feat: add EMI edge case test
* d5e6f7 feat: add EMI calculation
* c3d4e5 fix: correct rounding in fee calculation
* 901234 initial commit

When should you use merge vs rebase?

Merge is safe for shared branches because it does not rewrite history. Rebase is for private branches where you want a clean linear history. The rule: rebase private branches, merge shared branches.

| Scenario | Use Merge | Use Rebase |
|---|---|---|
| Integrating feature into main | Merge (or squash-merge) | -- |
| Updating private feature from main | Either | Rebase (cleaner) |
| Shared branch others have pulled | Merge always | Never rebase |
| Cleaning up local commits | -- | Interactive rebase |

JAVA
package com.bank.loans;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * This class was developed on a feature branch.
 * Rajesh rebased it onto main for clean history,
 * then merged to main with a squash-merge.
 */
public class EmiCalculator {

    public BigDecimal calculate(
            BigDecimal principal, BigDecimal rate, int months) {
        BigDecimal r = rate.divide(
            BigDecimal.valueOf(1200), 10, RoundingMode.HALF_UP);
        BigDecimal factor = BigDecimal.ONE.add(r).pow(months);
        return principal.multiply(r).multiply(factor)
            .divide(factor.subtract(BigDecimal.ONE),
                2, RoundingMode.HALF_UP);
    }
}
TEXT
EMI for principal=1000000, rate=8.5%, months=240
Result: 8678.23

How does git stash work?

Stash shelves all uncommitted changes -- both staged and unstaged -- saves them on a stack, and reverts your working directory to the last commit. You handle the urgent task, then pop to get your changes back.

BASH
# Rajesh is halfway through EMI changes when a production alert fires
git stash push -m "WIP: emi calculation refactor"
TEXT
Saved working directory and index state On feature/emi-calculation:
  WIP: emi calculation refactor
BASH
# Switch to fix the production issue
git checkout main
git checkout -b hotfix/transfer-timeout
# ... fix the issue, commit, push, PR ...

# Come back and restore the shelved work
git checkout feature/emi-calculation
git stash pop
TEXT
On branch feature/emi-calculation
Changes not staged for commit:
  modified:   src/main/java/com/bank/loans/EmiCalculator.java
Dropped refs/stash@{0} (abc1234)
BASH
# List all stashes
git stash list
TEXT
stash@{0}: On feature/emi-calculation: WIP: emi calculation refactor
stash@{1}: On feature/sip-returns: WIP: return percentage formula

How does git cherry-pick work?

Cherry-pick takes one commit by its hash and applies the same change as a new commit on your current branch. It does not bring the whole branch -- it copies one specific commit. The classic use is applying a hotfix to multiple branches.

BASH
# A hotfix was committed on the release branch
git log release/2.4 --oneline -1
TEXT
abc1234 hotfix: prevent transfer double-counting
BASH
# Cherry-pick that one fix onto main
git checkout main
git cherry-pick abc1234
TEXT
[main def5678] hotfix: prevent transfer double-counting
 1 file changed, 5 insertions(+)

The new commit (def5678) has a different hash because its parent differs. The change is the same, but the commit is a distinct object.

What are common mistakes?

Overusing cherry-pick across long-lived branches leads to duplicated commits. Using rebase on shared branches causes history divergence. Using stash as a long-term storage instead of committing or branching.

BASH
# WRONG -- cherry-picking the same fix into 5 branches
# Creates 5 duplicate commits, confusing git blame

# CORRECT -- cherry-pick for targeted hotfix propagation only
git checkout main
git cherry-pick abc1234
# Then let normal merge flow propagate to other branches

What are common interview follow-up questions?

  • What is interactive rebase and when would you use it?
  • How do you resolve a rebase conflict versus a merge conflict?
  • What is the difference between git stash pop and git stash apply?
  • How does git reflog help recover from a bad rebase?

What should a senior engineer know?

A senior engineer uses all four tools appropriately: rebase for clean personal history, merge for integrating shared work honestly, stash as a quick temporary shelf (not long-term), and cherry-pick as a scalpel for one-off hotfix propagation. They know that merge preserves the audit trail auditors require, while rebase makes personal branch history reviewable.

Visual Overview

DIAGRAM
  Merge vs Rebase
  ───────────────

  MERGE (preserves branching history):
  main:     A ── B ── C ──────── M
                 \              /
  feature:        D ── E ──────
  M = merge commit with two parents

  REBASE (linear history):
  main:     A ── B ── C ── D' ── E'
  No merge commit, straight line
  D' and E' = new commits (new hashes)

  STASH (temporary shelf):
  ┌──────────┐    stash push    ┌──────────┐
  │ Dirty     │────────────────▶│ Stash     │
  │ working   │                 │ Stack     │
  │ directory │◀────────────────│ @{0}      │
  │           │    stash pop    │ @{1}      │
  └──────────┘                  └──────────┘

  CHERRY-PICK (copy one commit):
  release: A ── B ── X (hotfix)
  main:    A ── B ── C ── D ── X' (cherry-picked)
  X' = same change, new hash, new parent

Key Takeaway

Merge and rebase are two ways to integrate branches, and they differ in what the history looks like. Merge creates a merge commit with two parents, preserving the true branching graph, which is ideal for shared branches and audit trails. Rebase replays commits onto a new base for a clean linear history, but rewrites commit identities, so it must only be used on private branches.

Stash solves the problem of needing a clean working directory urgently. It shelves all uncommitted changes on a stack, lets you handle the emergency, and then pops them back. Cherry-pick is a scalpel that copies one specific commit from any branch, which is perfect for propagating a single hotfix.

The rule is straightforward: rebase private branches to keep history clean and reviewable, merge shared branches to preserve the honest branching history, use stash as a quick temporary shelf, and cherry-pick only for targeted hotfix propagation.

Remember one sentence: merge preserves true history for auditors, rebase gives clean linear history for reviewers, stash shelves work-in-progress temporarily, and cherry-pick copies one commit surgically.

---

Share
Use ← → arrow keys to navigate