Merging & Rebasing
20 min
When Git merges two branches, it needs to know where they actually DIVERGED — the merge base (or lowest common ancestor): the most recent commit both branches share. Everything after that point is what each branch actually added independently.
def commit_history(commits, start):
history = []
current = start
while current is not None:
history.append(current)
current = commits.get(current)
return history
def find_merge_base(commits, a, b):
a_history = set(commit_history(commits, a))
current = b
while current is not None:
if current in a_history:
return current
current = commits.get(current)
return None
find_merge_base walks A's FULL history into a set (fast O(1) lookup), then walks B's history one step at a time until it hits something already in that set -- the same 'build a set, then scan' pattern from the Data Structures course's hash table module.
Merging creates a new commit with TWO parents, combining both branches' work while preserving exactly what happened (the diverged history stays visible). Rebasing instead REWRITES one branch's commits to sit on top of the other, producing a clean, linear history — as if that work had been done starting from the more recent commit all along.
The tradeoff: merging preserves true history (including exactly when and where branches diverged) at the cost of a messier, more tangled commit graph. Rebasing produces a cleaner, more readable linear history, but LITERALLY rewrites commits (new commit hashes) — which is why the cardinal rule is: never rebase commits that have already been pushed and shared with others, since rewriting shared history breaks everyone else's copy of it.
Using `commit_history` below, write `find_merge_base(commits, a, b)`: return the most recent commit shared by both `a`'s and `b`'s histories (the merge base / lowest common ancestor).
What is a 'merge base' (lowest common ancestor) between two branches?
You can find the merge base between two diverged branches, and understand the merge-vs-rebase tradeoff (preserved true history vs. clean linear history).