Dualo
Git & GitHub

Merge vs rebase

Two ways to integrate changes from one branch into another. Merge preserves history as it happened (with a merge commit). Rebase rewrites your branch on top of another, producing a linear history.

1 min read

Merge creates a commit with N parents (usually 2, sometimes more for octopus merges). The merge commit's tree is the result of the 3-way merge between main tip, feature tip, and their common ancestor. Topology preserves the branching shape.

Fast-forward merge: when main hasn't moved since feature branched off, Git just moves main's ref forward to feature's tip — no merge commit needed. Linear result. git merge --no-ff forces a merge commit even when fast-forward is possible (some teams want the visual marker).

Rebase doesn't merge — it re-applies. For each commit on feature (since the divergence point), Git: (1) generates a patch, (2) checks out main tip, (3) applies the patch, (4) creates a new commit (different SHA, same author/message). Original commits become unreachable (recoverable via reflog).

Why rebase changes SHAs: a commit's SHA is over its content + parent SHA. Re-parenting means a new commit. If you rebased a branch you've pushed, force-push (git push --force-with-lease) is required — anyone else who pulled the old branch sees diverged history.

Conflict resolution differs: merge resolves once at the merge commit. Rebase resolves at each commit being replayed — can be tedious if many commits conflict, but produces cleaner per-commit diffs. git rebase --abort cancels and restores the original branch.

Interactive rebase (git rebase -i HEAD~5) lets you reorder, squash, edit, drop, or reword the last 5 commits. Universal commit-cleanup tool: collapse 'fix typo' commits into the original, split a fat commit, polish messages before opening a PR.

Practice

You're on `feature`. Type the command to replay your commits on top of `main`.

Practice

You're in the middle of a rebase and you've resolved the conflicts. Type the command to continue.

Practice

Choose the right tool:

Cleaning up local commits before a PR: . Bringing a finished feature into a shared `main` while preserving the merge point: .

Grounded on https://git-scm.com/book/en/v2/Git-Branching-Rebasing

Next up

Resolving merge conflicts

Two branches changed the same lines? Git pauses, marks the conflict in the file, and waits for you to choose. Edit, stage, continue.