Rebase - a Cleaner History

git rebase

You already know one way to bring two branches together: merge, which joins two histories with a merge commit that has two parents. Rebase does the same end result - your feature's changes end up combined with main's - through a completely different mechanism: it replays your branch's commits one by one, as if you'd written them starting from main's latest commit instead of wherever you actually branched from. The result is a straight, linear history with no merge commit at all.

Before:   A─B─C  (main)
               \
                D─E  (feature)

After rebase onto main:   A─B─C─D'─E'  (feature)  ← linear, no merge commit

Notice the D' and E' - not D and E. Rebase doesn't literally move the old commits; it creates brand-new commits with the same changes and messages, but new parents (and therefore new hashes). This is the crucial difference from merge, and the reason for the golden rule below.

$ git switch feature
$ git rebase main
MergeRebase
Preserves the exact original commits + adds a merge commitRewrites your commits into new ones for a clean, straight line
Safe to run on shared/pushed branchesOnly for local, unpushed commits
Danger: The golden rule of rebase: never rebase commits you've already pushed and that others have based their own work on. Because rebasing creates new commits with new hashes, anyone who already has the old versions now has history that has permanently diverged from yours - Git has no way to reconcile "the same work under two different hashes" automatically. Rebase local, not-yet-shared work; merge (or git pull using merge) for anything already shared.
Tip: Interactive rebase (git rebase -i HEAD~3) lets you squash, reorder, reword, or drop your last few local commits - great for tidying a messy branch ("wip", "fix typo", "actually fix") into a clean, readable story before opening a PR. The dedicated "Interactive Rebase" section later covers this in depth.
Warning: Rebase can hit conflicts too, one commit at a time, just like a merge can - Git will pause on the offending commit and ask you to resolve it the same way (edit, git add, then git rebase --continue). If it gets messy, git rebase --abort puts you back exactly where you started, just like git merge --abort.