Rebase
Method
Moving your own commits on top of the latest mainline so it looks as though you had been working from there all along.
Why it exists
Cut a branch — a line of work split off from the mainline — and spend three days building a feature, and the mainline moves forward while you are gone, because four colleagues merged their own work into it. Your commits now sit on a base that no longer matches anything the mainline points at.
Closing that gap with a merge records the fact of the merge itself. Once or twice that is perfectly readable. With eight people on the repository the history turns into a net. The shape becomes a problem exactly when you need it most: during an incident, working backwards to find the cause. If the last two weeks contain forty merge records, there is no way to read the order in which individual changes actually landed.
The history is often untidy in a smaller way as well. Building one feature leaves commits reading "fix typo", "fix again", and "actually fix it this time." To the author that is a work log. To whoever reads the code in six months it is noise.
Rebase addresses both. Before merging, your commits get detached and reapplied onto the current end of the mainline, so the result looks like work that started from there. It is like uncoupling rail cars and hitching them behind a different locomotive: the cargo is unchanged, and what changed is which engine they sit behind.
How to run it
Fetch the latest mainline, then reapply your commits onto it one at a time. In Git this is a single command, but five things happen inside it.
- Fetch the mainline. Whatever it points at now becomes the base your work gets stacked on.
- Start the rebase on your branch. Your five commits get set aside, then replayed one by one starting from the mainline's tip.
- When a conflict appears, the process stops at that commit. A conflict means you and a colleague changed the same lines of the same file differently. A merge collides once, at the moment of merging; a rebase replays commit by commit, so it can collide repeatedly at the same spot. Resolve it, tell the process to continue, and it moves to the next commit.
- Tidy the commits if you want to. Run it interactively and you can squash three commits into one or rewrite their messages. Those three typo commits become one here.
- Push. Rebasing a branch already on the remote creates new commit identifiers, so it will not push normally and has to be forced. This is the step where accidents happen, and whether the force-push is harmless depends entirely on who else holds that branch.
Which is why fixing an order helps. Tidy before opening a pull request, and after opening it, add commits rather than rebasing. If lines a reviewer already read get rewritten wholesale, the comments left in code review no longer point at anything identifiable.
When it fits and when it doesn't
Three situations suit it: tidying a branch nobody else is on, polishing commits before opening a pull request, and checking that your work still functions on top of a mainline that has moved a long way ahead.
Four limits are worth knowing.
- Never use it on a branch or mainline several people share. New commits get created, which means divergence from the copy anybody else already has. When they fetch again, either the same change arrives twice or their own work disappears.
- Conflicts repeat. Replaying ten commits can mean stopping four separate times in the same file, and the longer a branch has been left sitting, the worse it gets — a day-old branch collides on two or three lines, a three-week-old one on ten whole files.
- The fact of merging leaves no record. The history straightens out, and with it goes any clear marker of which batch of work landed together and when.
- Reverting is more work. Undoing one merge record removes the whole batch, whereas commits that arrived by rebase are scattered as individual commits and have to be picked out one at a time.
Choosing which of the two the team uses is the real work around this term. Where branches never live longer than two days, as in trunk-based development, rebase is the natural fit. Where feature branches are kept for weeks, the merge records get used for tracing. Mixing both means everyone reads history by a different rule.
How it sounds at work
"Rebase and squash before you open it — there are three typo commits in there."
A request to tidy for whoever has to read the history.
"Mainline has moved a lot. Let's rebase and run the tests once."
Confirming in advance that the work holds up on the current state.
"I'm on that branch too. If you rebase it, my copy diverges."
Restating the rule that shared branches are off limits.
At Pagedeck, Theo tidies commits before opening a pull request. During the work he records whatever comes to mind; just before opening, he squashes them into two or three meaningful units and rewrites the messages. After opening, he leaves them alone and addresses review comments in new commits.
There was an incident behind that rule. Two people were sharing a branch, one of them rebased it and force-pushed, and the other lost half a day of work fetching the result. Since then the team has it written down that branches with more than one person on them do not get rebased.
What people get wrong
The most common error is reading rebase as the better of the two methods. The pitch you hear first is that it keeps history clean, which invites that conclusion. But both do the same job and the resulting code is identical. The only difference is the shape of the record. The basis for choosing is not better or worse but what the history is used for. If it mostly gets read backwards to find causes, a straight line is easier. If you need to see which feature landed as one batch and when, the merge record is what tells you.
The second error is believing rebase deletes history, or the opposite, that it is a safe operation. Both misreadings come from the same place. Rebase does not relocate existing commits; it creates new ones with the same content and attaches those. The content survives, the identifiers change. That is why nothing is lost on a branch only you are using, and why a shared branch diverges from the copies other people hold. Whether it is safe is determined by how many people are watching that branch, not by the operation itself.
Easily confused with
| Term | Shape left in history | How it differs |
|---|---|---|
| Merge | The split and the rejoin both stay visible | Adds one record of the merge and leaves existing commits untouched. It is usable on shared branches, and conflicts are faced once, at the moment of merging |
Where to go next
- Version control
see where operations sit among the seven groupings and what they pair with
- Merge
the other way to do the same job, so the pair is what gives you a basis for choosing
Last updated 2026-09-16