This lesson on Rebase vs Merge is hands-on and example-driven. You will be able to execute both merging and rebasing strategies to integrate Git branches, understanding the profound impact each has on project history. You will learn how to choose the correct strategy based on whether the branch is local or shared, ensuring clean history without disrupting collaborators.
What You'll Be Able To Do
- Execute a three-way merge using the Git CLI, resolving conflicts as necessary.
- Determine the appropriate integration strategy (merge or rebase) based on branch visibility.
- Rewrite local branch history using
git rebaseto achieve a clean, linear commit log. - Force a merge commit using the
--no-fast-forwardflag for documentation purposes. - Identify the critical risk associated with rebasing branches that have been pushed publicly.
- Compare and contrast the history graph resulting from merging versus rebasing.
Detailed Concept Walkthrough
1. Three-Way Merge Mechanics
Merging integrates diverging branch histories by creating a new merge commit that accounts for changes from both branches and their common ancestor. This operation is non-destructive and maintains a complete chronological record.
- Mechanism: Git identifies the common ancestor, the branch tip, and the target tip, then combines the changes into a new merge commit object.
- Under the Hood: The resulting merge commit explicitly has two parent pointers, documenting the exact point where the two lines of development joined.
- Best Practice: Use the default merge strategy for integrating shared branches to ensure historical fidelity and avoid breaking collaborator workflows.
# Integrate changes from 'main' into the current feature branch
git checkout feature-branch
git merge main
Key Takeaway: Merging preserves all historical context but can result in a 'messy' history graph with many merge commits.
2. Rebase Mechanics and History Rewriting
Rebase moves a sequence of commits to a new base commit, effectively rewriting history to create a clean, linear progression. It makes the feature branch appear as if it started from the target branch's current tip.
- Mechanism: Git temporarily sets aside the feature branch commits, updates the branch to the target tip, and then replays the set-aside commits sequentially on top.
- Under the Hood: Rebase abandons the original commit objects and creates functionally identical new commit objects, resulting in different SHA-1 hashes.
- Execution Flow: Conflicts must be resolved sequentially as each commit is replayed onto the new base, potentially requiring multiple conflict resolution steps.
# Rebase the current feature branch onto 'main'
git checkout feature-branch
git rebase main
Key Takeaway: Rebase fundamentally alters project history by creating new commit objects, leading to a linear history ready for fast-forwarding.
3. The Golden Rule of Rebasing
Rebasing is a powerful tool for cleaning up local history, but it must never be used on branches that have been pushed and shared with collaborators. Rewriting shared history causes divergence and breaks collaboration.
- Best Practice: Only rebase local, private branches that no one else has based work upon or pulled down.
- Shared Branch Danger: If a collaborator is working on the original, abandoned commits, pulling the rebased branch will force them to deal with complex integration issues.
- History Immutability: Git treats all commits as immutable; rebase works by discarding the original immutable commits and creating functional copies with new hashes.
git log # Check history before rebasing to ensure commits are local
Key Takeaway: If a branch is public or shared, always use
git mergeto integrate changes; otherwise, use rebase for local cleanup.
Topics Covered in Rebase vs Merge
- Three-Way Merge (0:21 - 1:21) — The three-way merge integrates diverging histories by creating a new commit based on the common ancestor.
- Merging onto Feature Branch (1:21 - 2:22) — Merging is a non-destructive way to keep a feature branch up-to-date with the main branch changes.
- Fast-Forward Control (2:22 - 3:20) — A fast-forward merge moves the pointer forward without a merge commit unless the
--no-fast-forwardflag is used. - Rebase Mechanics (3:41 - 4:26) — Rebase rewrites history by replaying commits onto a new base, creating a clean, linear history.
- Rebase Risks (4:26 - 5:38) — Rebase fundamentally alters history by creating new commit objects with different hashes, requiring conflict resolution.
- The Golden Rule (5:38 - 6:33) — Never rebase branches that have been shared publicly because it causes divergent histories for collaborators.
Git Cheat Sheet
-
git merge <branch>— Integrates changes using a three-way merge commitgit merge main -
git rebase <branch>— Rewrites history by moving commits to a new basegit rebase main -
git merge --no-ff— Forces a merge commit even if fast-forward is possiblegit merge feature --no-ff -
Three-Way Merge— Integration using common ancestor, branch tip, and target tip -
git log— Displays commit history, useful for comparing hashesgit log --oneline
Comparison Table
| Feature | Merge | Rebase |
|---|---|---|
| History Type | Non-linear (graph) | Linear (straight line) |
| Commit Objects | Preserves originals | Creates new objects/hashes |
| Integration Commit | Always creates one | None (fast-forward possible) |
| Use Case | Shared/Public branches | Local/Private cleanup |
Common Pitfalls
- Mistake: Rebasing a branch that has already been pushed publicly. Avoid: Only rebase local branches that are private to your machine.
- Mistake: Assuming rebase is conflict-free magic. Avoid: You must still handle conflicts sequentially as each commit is replayed.
- Mistake: Forgetting to force a merge commit when history is linear.
Avoid: Use
git merge --no-fast-forwardfor documentation.
FAQs
- What is a fast-forward merge? It occurs when history is linear and the branch pointer can simply move forward. No merge commit is created, resulting in a perfectly straight history.
- Why does rebase change commit hashes? Rebase discards the original commits and creates new ones when replaying them onto the new base. Since commit hashes are based on content and parent history, the new commits get new hashes.
- When should I use
--no-fast-forward? Use this flag when you want to explicitly document the integration point of a feature branch, even if Git could perform a fast-forward merge. - What is the 'common ancestor' in a three-way merge? It is the last commit shared by both branches before they diverged. Git uses this anchor point to calculate the unique changes on each side.