git rebase: moving commits on top of someone else's

Updated July 31, 2026

git rebase rewrites your commits as if you had started work after your colleague finished theirs. Instead of a fork and a merge commit you get one straight line.

A merge keeps the history as it happened: two lines meet in a merge commit, and git log --graph shows who branched off what. Rebase gives a different result: other people's commits first, yours after, no forks. Many teams find that easier to read.

$ git log --graph --oneline --all
* 01393b3 style the search box
* 14b6745 add search box
| * a66eee4 bob fixes typo
|/
* df02c61 alice adds a note
$ git switch feature-search
$ git rebase main
Successfully rebased and updated refs/heads/feature-search.

$ git log --graph --oneline
* 1ba6e8c style the search box
* 22eded3 add search box
* a66eee4 bob fixes typo
* df02c61 alice adds a note

Look at the hashes: 14b6745 became 22eded3. Nothing was actually moved. Git created new commits with the same content but a different parent, and abandoned the old ones.

The golden rule

Do not rebase anything that is already on the server and has been fetched by other people. They are left holding a history that no longer exists, and their next git pull brings duplicated commits and conflicts out of nowhere. Your own branch that nobody fetched is fine. A shared main is off limits.

The check is built into git itself: a plain git push after a rebase is rejected, because the server branch is no longer an ancestor of yours. Only --force gets it through, and that is your cue to stop and remember who else has seen this branch. The gentler --force-with-lease refuses to run if someone else's commits have appeared on the server in the meantime.

Conflicts and undo

Rebase applies commits one at a time, so a conflict stops it halfway:

$ git rebase main
CONFLICT (content): Merge conflict in conf.txt
error: could not apply 042569a... alice edits line1
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".

From there it goes like any conflict: fix the file, git add, then git rebase --continue. Change your mind at any point and git rebase --abort puts the branch back exactly where it was before the command.

There is also an interactive mode, git rebase -i HEAD~5. The list of your last five commits opens in an editor, and you can reorder the lines, fold them together (squash), rewrite a message (reword), or drop one (drop). It is how you tidy your own history before pushing: five typo fixes become one commit. The rule about shared branches applies here just the same.

Common mistakes

Treating rebase as the "more correct" replacement for merge. It is a choice of history style, not of technique: git merge keeps the course of work as it was, rebase straightens the line. A team picks one and sticks to it.

One more: git pull --rebase is the same machinery, applied to the commits coming from the server. The rule about already published work covers it too.

Where this is in the book

The "What comes next" section of the final project. Why teams dislike a force push is covered in Chapter 7. How teams actually use git.

To practise it by hand, open the Sandbox: a real terminal with git and step checks.