Git Rebase and Merge

🧩 Git Merge Methods Explained

πŸ”Έ 1. Fast-Forward Merge

πŸ“Œ What:

Moves the branch pointer forward because there’s no divergent history.

πŸ§ͺ Example:

git checkout main
git merge feature-branch

βœ… If main is behind feature-branch but has no new commits, Git just moves main forward β€” no merge commit is created.

πŸ“Š Result:

  • No extra commit.
  • Clean history.
  • Only possible when histories are linear (no parallel commits).

πŸ”Έ 2. Three-Way Merge (Default)

πŸ“Œ What:

Used when branches diverged β€” Git creates a merge commit.

πŸ§ͺ Example:

git checkout main
git merge feature-branch

πŸ”„ If both main and feature-branch have new commits, Git creates a merge commit to tie them.

πŸ“Š Result:

  • Merge commit created.
  • Retains full history of both branches.
  • Good for preserving commit context.

πŸ”Έ 3. Squash Merge

πŸ“Œ What:

Combines all commits from the feature branch into a single commit on the target branch.

πŸ§ͺ Example:

git checkout main
git merge --squash feature-branch
git commit -m "Add feature X"

πŸ“ All feature-branch commits are flattened into one.

πŸ“Š Result:

  • Clean, single commit.
  • Good for simplifying history.
  • Loses detailed history of feature-branch.

πŸ”Έ 4. Rebase + Fast-Forward

πŸ“Œ What:

Rewrites feature branch history onto base branch β€” keeps history linear and avoids merge commits.

πŸ§ͺ Example:

git checkout feature-branch
git rebase main
git checkout main
git merge --ff-only feature-branch

πŸ“ˆ Keeps history tidy and linear.

πŸ“Š Result:

  • No merge commits.
  • Linear history.
  • Can be risky if rebasing shared branches (changes commit hashes).

πŸ”Έ 5. No-Fast-Forward Merge (--no-ff)

πŸ“Œ What:

Forces Git to always create a merge commit, even if a fast-forward is possible.

πŸ§ͺ Example:

git merge --no-ff feature-branch

πŸ”— Use this to clearly show a branch was merged, even if no divergence.

πŸ“Š Result:

  • Always a merge commit.
  • Good for clear separation of features in history.

πŸ” Summary Table

Merge MethodMerge CommitHistory TypeUse Case
Fast-Forward❌ NoLinearSimple updates
Three-Way Mergeβœ… YesDivergedDefault for complex merges
Squash Merge❌ One commitSimplifiedClean history, single logical change
Rebase + FF❌ NoLinearClean history before merge
No-FFβœ… YesAlways visibleAlways document a merge explicitly

🧠 Best Practices

  • βœ… Use squash for feature branches in solo/team projects to simplify history.
  • βœ… Use no-ff in protected/main branches for clear audit trails.
  • βœ… Use rebase to clean up local commits before merging.

πŸ” Understanding git rebase

πŸ”Ή What is git rebase?

git rebase is used to move or combine a sequence of commits to a new base commit. It is often used to maintain a cleaner, linear project history.

Unlike merge, which creates a new commit, rebase re-applies commits on top of another branch.


πŸ”Ή Syntax

git rebase <upstream-branch>

Example:

git checkout feature
git rebase main

This reapplies your feature branch commits on top of the latest main.


πŸ”Ή Common Use Case: Updating Feature Branch

# Assume you're on feature branch
git checkout feature/login
git fetch origin
git rebase origin/main

βœ… This puts your feature branch on top of the latest main, as if it was created from it.


πŸ”Ή Resolving Conflicts During Rebase

If conflicts occur:

# After editing the file to fix conflicts
git add <resolved-file>
git rebase --continue

To skip the current commit:

git rebase --skip

To abort the rebase and return to the previous state:

git rebase --abort

πŸ”„ Interactive Rebase

Use this to edit, squash, or reword commits.

git rebase -i HEAD~3

Example interactive menu:

pick 3f5e1f9 Added login form
pick 89d2ac3 Fixed typo in login
squash d14e7a3 Updated form styles

Change pick to:

  • reword β€” change the commit message
  • squash β€” combine commits into one
  • edit β€” pause to change code during rebase

πŸ†š Rebase vs Merge

Featuregit mergegit rebase
HistoryKeeps history with a merge commitCreates a linear history
Commit GraphMay look like a treeLooks like a straight line
Use WhenYou want to preserve all changesYou want a clean history

🚫 Don’t Rebase Shared Branches

⚠️ Avoid using git rebase on branches that others are working on (i.e., already pushed/shared), unless you coordinate with your team.


πŸ”§ Example: Clean Up Before Merge Request

git checkout feature/payment
git rebase -i HEAD~5
# squash into a single commit

Then:

git push -f origin feature/payment

πŸ’‘ Tip: Use git log --oneline --graph before and after rebase to visualize the change.