What Does git rebase Actually Do?

What Does git rebase Actually Do?

A deep, intermediate-level walkthrough of how rebasing rewrites history, why teams use it deliberately, and where it can go wrong if handled carelessly.

Imagine you’re telling a story out loud, and partway through, you realize a small side comment you made a few sentences ago would actually flow better if it came right before the ending instead. You could either leave it exactly where it fell in the moment, or you could retell the whole story from that point onward, placing that comment exactly where it now makes the most sense. Rebasing in Git is that second option, applied to your project’s history. Instead of accepting commits in whatever order they happened to occur, rebasing lets you take a set of commits and replay them, one at a time, onto a new starting point — effectively rewriting the story of how your work came together, as if it had happened in a cleaner, more deliberate order from the very start. This post goes deep into what rebase actually does internally, why experienced teams reach for it, and the very real risks that come with rewriting something as fundamental as history.

1What Problem Does Rebase Solve?

To understand rebase, we first need to see the messy situation it was built to address.

The problem: history that reflects timing, not intent

When multiple people work on a shared project at the same time, their commits naturally interleave based on when each person happened to save their work — not based on what actually makes logical sense as a readable story. One developer’s three small commits fixing a typo might end up scattered awkwardly between another developer’s much larger feature work, purely because of when each commit happened to be made. Left alone, a project’s history can end up reflecting the chaos of real-time collaboration rather than a clean, understandable narrative of how the project actually evolved.

The solution: replaying commits onto a new base

Rebase addresses this by letting you take a sequence of commits and move them, as a whole, onto a different starting point — most often, the latest version of the branch you’re eventually planning to merge into. Rather than merging two diverging histories together as they are, rebase effectively asks: “what if these commits had been made starting from right here, instead of from wherever they originally started?” It then reconstructs that alternate reality, one commit at a time.

Simple Analogy

Picture building a small tower out of blocks on one table, while a friend builds a much taller tower on a second table nearby. If you wanted to combine your tower onto theirs, you have two choices. You could glue your entire tower, as a separate unit, onto the side of theirs — messy, but fast, and it visibly shows two towers joined together. Or, you could carefully pick up your blocks one at a time, and re-stack them directly on top of your friend’s tower, in the same order you originally placed them, as though you’d been building on their table all along. The second approach is what rebase does with commits — it picks them up one at a time and re-stacks them on a new foundation.

Term

Commit

A single, permanent snapshot in a project’s history, with its own message and unique identifier.

Term

Base

The commit a sequence of other commits is built on top of — the “starting point” for a branch’s history.

Term

Rebase

The act of moving a sequence of commits so they now build on top of a different base commit.

Term

History Rewriting

Changing the recorded sequence of commits, rather than simply adding new ones on top of what already exists.

2Merge vs Rebase: Two Different Ways to Combine Work

Rebase is almost always discussed alongside its closest relative, merging, since both exist to solve the same underlying goal in fundamentally different ways.

Merging takes two separate lines of history and combines them by creating a brand-new commit with two parents, one pointing back into each original line. Nothing about either original line of history is changed — the merge commit simply sits on top, tying them together. Rebasing, by contrast, doesn’t create a joining commit at all. Instead, it takes one line of commits and moves them entirely, rewriting them so they appear to have been built directly on top of the other line from the very beginning.

flowchart TD
    subgraph Merge
    A1["main"] --> A2["main"]
    A2 --> A3["merge commit"]
    B1["feature"] --> B2["feature"]
    B2 --> A3
    end
    subgraph Rebase
    C1["main"] --> C2["main"]
    C2 --> D1["feature (replayed)"]
    D1 --> D2["feature (replayed)"]
    end
        
FIG 1 — Merging joins two histories with a new commit; rebasing rewrites one history to sit directly on top of the other
AspectMergeRebase
Original commitsLeft completely unchangedRewritten as new, different commits
Resulting history shapeBranching, with joining points visibleA single, straight line
Extra commit createdYes, a dedicated merge commitNo new joining commit
Safety on shared branchesGenerally safe for everyoneRisky if others already have the original commits
i
Neither Is “Better” in Every Case

Merge and rebase aren’t a simple better-or-worse choice — they produce genuinely different kinds of history, suited to different goals. Merge preserves exactly what happened, including the branching itself. Rebase produces a cleaner, linear story, at the cost of the original commits no longer technically existing.

3What Actually Happens During a Rebase

Understanding rebase’s internal mechanics removes a lot of the mystery around why it behaves the way it does.

When you rebase a branch onto a new base, Git doesn’t simply relabel or move the existing commits — it genuinely creates brand-new commits, one for each original commit being rebased, applying the same changes on top of the new base instead of the old one. Because a commit’s unique identifier is calculated from its content, including its parent, a commit built on a different base is, by definition, a completely different commit, even if the actual code change it introduces is identical.

1

Git identifies the commits to be moved

It determines exactly which commits, starting from where your branch diverged from the new base, need to be replayed.

2

Git temporarily sets those commits aside

It essentially remembers the changes each commit introduced, without keeping them attached to their original position.

3

Git moves the branch to the new base

The branch pointer is temporarily placed at the commit you’re rebasing onto, ready to build forward from there.

4

Git replays each commit’s changes, one at a time

For every original commit, in order, Git applies that same change on top of the new base, creating a brand-new commit each time.

5

Git handles any conflicts along the way

If a change can’t be applied cleanly because the new base has diverged too much, the rebase pauses so the conflict can be resolved before continuing.

6

The branch now points at the final replayed commit

Once every commit has been successfully replayed, your branch reflects an entirely new, straight-line history built on the new base.

!
Common Misconception

A frequent misunderstanding is that rebase simply “moves” the existing commits, like picking up furniture and setting it down elsewhere. In reality, every rebased commit is a brand-new object with its own new identity — the originals still technically exist for a while in Git’s internal storage, but your branch no longer points to them.

4The Architecture of a Rebase: Commits, Patches, and Replays

A closer look at the pieces involved helps explain why rebase behaves the way it does under the hood.

Conceptually, Git treats each commit being rebased as a “patch” — a description of what changed, independent of exactly where it originally sat in history. Replaying a commit means applying that patch’s changes on top of whatever the new base currently looks like, then wrapping the result up as a new commit, carrying over the original author information and message, but generating a fresh identifier and a fresh parent link pointing at the newly rebased position.

Component

Original Commit

The commit as it existed before the rebase, still technically present in Git’s storage for a period of time.

Component

Patch

The conceptual “difference” a commit introduces, extracted so it can be reapplied elsewhere.

Component

New Base

The commit that the sequence of patches will now be applied on top of.

Component

Replayed Commit

The brand-new commit created after successfully applying a patch onto the new base.

Simple Analogy

Think of each commit as a recipe step written on its own index card — “add two eggs,” “stir for one minute.” Rebasing is like taking that whole stack of index cards and re-performing every step, in the same order, but starting from a different, updated set of ingredients on the counter. The written instructions stay conceptually the same, but you’re physically redoing each step fresh, against a new starting situation.

5Data Flow and Lifecycle of a Rebase Operation

Tracing a rebase from start to finish shows exactly how your branch transforms at each stage.

sequenceDiagram
    participant You
    participant Branch as Your Branch
    participant Base as New Base
    participant History as Rebased History
    You->>Branch: Start rebase onto new base
    Branch->>Base: Identify divergence point
    Base-->>Branch: Confirm commits to replay
    loop For each original commit
        Branch->>History: Apply patch onto current tip
        History-->>Branch: New commit created
    end
    Branch->>You: Branch now points to final new commit
        
FIG 2 — The lifecycle of a rebase, from start through each replayed commit to completion

Before the rebase begins

Your branch and the target base have diverged — meaning both contain commits the other doesn’t have. Your branch’s own commits sit on top of an older point in the target’s history, rather than its current, latest state.

During the rebase

Git works through each of your branch’s unique commits in order, temporarily pausing the process if any commit’s changes can’t be applied automatically due to a conflicting change already present in the new base.

After the rebase completes

Your branch now consists entirely of new commits, each built directly on top of the new base, forming one continuous, linear sequence with no branching point visible at all — as though your work had been written starting from that exact point in history all along.

6Interactive Rebase: Editing History Deliberately

Beyond simply moving commits to a new base, rebase also offers a mode for actively reshaping the commits themselves.

Interactive rebase presents you with an editable list of the commits about to be replayed, and lets you decide, for each one individually, exactly what should happen to it. You might choose to keep a commit exactly as it is, combine it with the commit before it, reword its message, reorder it relative to other commits, or drop it from history entirely.

Action

Keep

Replay the commit exactly as it is, with no modification at all.

Action

Reword

Keep the commit’s changes, but replace its message with an improved one.

Action

Squash

Combine the commit’s changes into the commit immediately before it, merging them into a single, unified commit.

Action

Drop

Remove the commit entirely, as though its change had never been made in the first place.

Action

Reorder

Change the position of a commit relative to the others in the sequence being replayed.

Cleaning Up Before a Pull Request

A very common use of interactive rebase is tidying up a messy sequence of small, exploratory commits — “fix typo,” “actually fix it,” “oops” — into a small number of clear, meaningful commits before opening the work up for review.

“Interactive rebase turns your commit history from a diary of everything you tried into a polished story of what actually mattered.”

7Advantages and Trade-offs of Rebasing

Like any powerful tool, rebase brings genuine benefits alongside real costs worth understanding clearly.

Advantages

  • Produces a clean, linear, easy-to-follow history
  • Removes unnecessary joining commits cluttering the log
  • Lets you reshape and tidy commits before sharing them
  • Makes it easier to isolate exactly which commit introduced a problem

Trade-offs

  • Original commits are replaced, not preserved
  • Dangerous if used on commits others have already built upon
  • Can require resolving the same conflict repeatedly across many commits
  • History no longer reflects exactly when and how work actually happened
!
The Golden Rule of Rebase

A widely shared principle among experienced Git users is to never rebase commits that have already been shared with, or built upon by, other people. Doing so effectively pulls the rug out from under anyone else already relying on those original commits, forcing them to untangle a confusing mismatch between their history and yours.

8Security and Safety Considerations When Rewriting History

Because rebase fundamentally alters history rather than simply adding to it, it carries a distinct category of risk worth treating seriously.

Since rebased commits are brand-new objects with different identifiers, updating a shared branch after a rebase requires forcefully overwriting whatever was there before, rather than the normal, additive update. This is inherently a destructive operation from the perspective of anyone who already has a copy of the original commits — their local history will no longer match, and reconciling the two can range from a minor inconvenience to a genuinely confusing mess.

The specific danger of shared history

If someone else has already based their own new work on top of the original commits, and you then rebase and force-update the shared branch, their work now technically builds on commits that no longer exist in the shared history at all. This can lead to duplicated changes, confusing conflicts, and a significant cleanup effort to sort out whose history should actually be considered correct.

A Safer Default: Rebase Only Local, Unshared Work

The safest and most common practice is to only rebase commits that exist solely on your own local branch, before anyone else has seen or built upon them — commonly used to tidy up work-in-progress before opening it for review, rather than rewriting anything already shared.

9Design Patterns: When and How Teams Use Rebase Well

Used deliberately, rebase fits neatly into several well-established, healthy team workflows.

Keeping a Feature Branch Up to Date

Instead of repeatedly merging the latest changes from the main branch into a feature branch, some teams prefer rebasing the feature branch onto the latest main, keeping the eventual history clean and linear once the feature is finally merged.

Cleaning Up Before Review

Using interactive rebase to consolidate a messy sequence of exploratory commits into a small, coherent set, before ever sharing the branch, makes the eventual review far easier for teammates to follow.

Maintaining a Linear Project History

Some projects deliberately enforce a policy where every contribution must be rebased before merging, specifically to keep the entire project’s history as one clean, readable line, free of merge commits entirely.

gitGraph
   commit id: "main: setup"
   commit id: "main: config update"
   branch feature
   checkout feature
   commit id: "feature: draft"
   commit id: "feature: cleanup"
   checkout main
   commit id: "main: hotfix"
   checkout feature
   commit id: "feature: rebased draft"
   commit id: "feature: rebased cleanup"
   checkout main
   merge feature id: "clean, linear merge"
        
FIG 3 — A feature branch rebased onto the latest main before merging, producing a clean, linear result

10Anti-Patterns: Common Rebase Mistakes and Misuse

Just as clearly as there are healthy patterns, there are well-known ways rebase gets misused, often with painful consequences.

ANTI-PATTERN-01 Avoid
Problem

Rebasing a branch that other teammates have already pulled and built additional work on top of, then force-updating the shared copy.

Why It’s Harmful

Everyone else’s local history now conflicts with the rewritten shared history, often resulting in duplicated commits, confusing merge attempts, and significant time spent untangling what should be considered the “true” history.

Correct Approach

Reserve rebase for commits that are still entirely local and unshared, and rely on merging once work has already been shared with others.

ANTI-PATTERN-02 Avoid
Problem

Using interactive rebase to squash together commits that actually represent distinct, meaningful changes, purely for the sake of having “fewer commits.”

Why It’s Harmful

It destroys useful granularity in history, making it harder later to isolate exactly which specific change introduced a bug, since multiple unrelated changes are now bundled into one commit.

Correct Approach

Squash only commits that genuinely represent the same logical change, such as a fix to a typo made earlier in the same piece of work, and preserve distinct, meaningful commits as separate entries.

ANTI-PATTERN-03 Avoid
Problem

Rebasing a very long-lived branch against a rapidly changing base, over and over, resolving the same or similar conflicts repeatedly each time.

Why It’s Harmful

Frequent, painful, repeated conflict resolution signals a deeper structural problem, often that the branch has been kept separate for far too long and has drifted too far from the base it needs to eventually rejoin.

Correct Approach

Favor smaller, shorter-lived branches that are integrated back frequently, reducing how far any single branch can drift before rebasing becomes painful.

11Best Practices for Rebasing Safely

A handful of consistent habits keep rebase a genuinely useful tool rather than a source of team-wide headaches.

1

Only rebase commits that are still local and unshared

Treat anything already pushed and visible to teammates as effectively permanent, and rely on merging from that point onward.

2

Communicate clearly if a shared rebase is genuinely necessary

In rare cases where rewriting shared history is unavoidable, make sure every affected teammate knows exactly what happened and how to reconcile their own local copy.

3

Rebase in small, frequent steps rather than one giant one

Keeping branches short-lived and rebasing often avoids the pain of resolving a huge backlog of conflicts all at once.

4

Use interactive rebase thoughtfully, not automatically

Only squash or reorder commits when doing so genuinely improves clarity, rather than treating “fewer commits” as an automatic goal on its own.

5

Double-check the result before forcefully updating anything shared

Review the rebased history carefully to confirm it looks correct before overwriting any branch other people might rely on.

12Rebase in the Real World

Rebase plays a distinct, deliberate role in the workflows of many serious, high-quality software projects.

Large, disciplined open-source projects — including some of the most heavily contributed-to codebases in the world — commonly require contributors to rebase their work before it’s accepted, specifically to maintain a clean, linear project history that’s easier to review and reason about over the project’s entire lifetime. Individual engineers frequently use local, unshared rebasing purely as a personal tidying step, cleaning up their own exploratory commits into a clear, professional-looking sequence before ever opening a pull request.

Widely required
By many disciplined open-source projects before merging contributions
Local-first
Most safe, everyday use happens on unshared, personal work
Policy-driven
Many teams codify exactly when rebasing is, and isn’t, allowed

Linear-History Projects

Some projects deliberately maintain a strict, merge-commit-free history, relying entirely on rebase to integrate every single contribution as a clean, linear sequence.

Personal Commit Hygiene

Individual developers commonly rebase their own local, unshared branches purely to present a clean, professional set of commits before requesting review from teammates.

13Frequently Asked Questions

Q1Does rebase delete my original commits immediately?

Not immediately. The original commits typically remain in Git’s internal storage for a period of time, even though your branch no longer points to them, meaning recovery is often still possible shortly after a rebase if something goes wrong.

Q2Why do the commit identifiers change after a rebase?

Because a commit’s identifier is calculated from its full contents, including its parent commit, replaying a commit onto a different parent inevitably produces a different identifier, even if the actual code change is identical.

Q3Is rebase always the “cleaner” choice compared to merge?

It produces a cleaner-looking, linear history, but “cleaner” doesn’t automatically mean “better” — merging preserves exactly what happened, including genuine branching, which some teams value more than a simplified, linear story.

Q4What happens if a conflict occurs partway through a rebase?

The rebase pauses at that specific commit, letting you resolve the conflict directly, after which the process continues replaying the remaining commits in sequence.

Q5Can I stop a rebase partway through and go back to how things were?

Yes. Rebase operations can typically be aborted partway through, restoring your branch to exactly the state it was in before the rebase began.

Q6Is it ever acceptable to rebase a branch other people are also using?

It’s generally discouraged, since it forces everyone else to reconcile their local history with the rewritten version. When genuinely necessary, it should be done deliberately, with clear communication to everyone affected beforehand.

Q7Does interactive rebase let me change what a commit actually contains, not just its message?

Yes. Beyond rewording messages, interactive rebase allows editing a commit’s actual changes, combining it with others, reordering it, or removing it entirely from the sequence.

14Summary and Key Takeaways

Rebase gives you the power to reshape history itself — taking a sequence of commits and rebuilding them, one at a time, on top of a new starting point, producing a clean, linear story instead of a tangle of joined branches. That power comes with real responsibility: because rebased commits are entirely new objects, using rebase on anything already shared with others can create genuine confusion and conflict across a team. Used thoughtfully, on local, unshared work, rebase is one of the most valuable tools for producing a readable, professional project history. Used carelessly, on commits others already depend on, it becomes a source of exactly the kind of chaos it was meant to prevent.

Key Takeaways

  • Rebase replays commits onto a new base — creating brand-new commits rather than moving the original ones.
  • It produces a clean, linear history — unlike merging, which preserves branching with a dedicated joining commit.
  • Rebased commits get new identifiers — since a commit’s identity depends on its parent, which has now changed.
  • Interactive rebase allows deliberate editing — rewording, combining, reordering, or dropping commits before sharing them.
  • Never rebase already-shared commits carelessly — doing so can create serious confusion for anyone who already built on them.
  • Short-lived branches make rebasing painless — the longer a branch drifts, the more conflict resolution a rebase can require.
  • Rebase and merge solve the same goal differently — choosing between them depends on whether your team values a clean linear history or a fully preserved, branching one.