Why do rebased commits get new SHA hashes?
A commit's SHA is computed from its content AND its parent's SHA. When you rebase, D's new parent is C instead of B — so D's SHA must change even though the code diff is identical. This is the precise meaning of "rewrites history": same work, new identity.
What exactly is a merge commit?
A merge commit has two parents — in this example, C and E. It's the point where two lines of history were joined. git log --graph shows both lines converging into M. The merge commit is permanent evidence that parallel work happened and was combined.
Can I fast-forward merge when branches have diverged?
No. Fast-forward only works when no new commits exist on the base since the branch was created. Here, main added C after the branch was created — so a fast-forward is impossible. You must either create a merge commit, or rebase first and then merge with --ff-only.
What does git pull --rebase do?
Instead of merging the remote's new commits into your local branch (creating a merge commit), it rebases your local commits on top of the remote's. History stays linear. Useful on branches with active collaboration where merge commits would clutter the log.
When should I use merge vs rebase?
Use merge for integrating public/shared branches — it's non-destructive. Use rebase to clean up a local feature branch before a PR — linear history is easier to review. The simplest rule: rebase branches you haven't pushed; merge everything else.
What is interactive rebase (git rebase -i)?
git rebase -i HEAD~N opens an editor where you can squash commits (combine multiple into one), reword commit messages, drop commits, or reorder them. Standard practice before opening a PR: squash your six "WIP" commits into two clean, logical units that tell the story of the change.