Git rebase: Under the hood

Like so many others who watch daily at my proverbial door for the next golden drop of Git wisdom to fall from my gilded lips, you've probably been waiting with breathless anticipation for me to talk about rebasing. (Or you're just here because you saw “git rebase” in the title and you're curious--I suppose anything is possible.)

In any case, your interest is understandable. There are few Git skills at once more fundamental and less understood than rebasing. And no wonder, really--it's basically magic, and magicians don't readily give up their secrets.

I've Googled hard, but I've sought in vain a good diagram that shows what's actually going on behind the scenes. Let's fix that, shall we?

Join me now, as we embark on a perilous journey to understand Git rebase, armed with nothing but a terminal and a dream...

And so it begins

First, we clone a repository for local development.

(you) $ git clone [remote]


I'll take that, thank you

Then we create a feature branch to work on a new issue.

(you) $ git checkout -b feature


So long, suckers!

We do some work and commit our changes.

(you) $ [code, commit, etc.]



But in the meantime, the upstream repository commits changes, too. Now we've diverged.

(you) $ git fetch [remote]


Let's do this thing!

Time to rebase.

(you) $ git rebase main


Shhh! This part's a secret

Under the hood, Git creates an invisible working branch and checks it out, putting us into a kind of magical in-between state.

(git fairies) $ git checkout -b REBASE main



Then it begins to “replay” the commits on the new branch. It finds the first one we have that our base branch doesn't and cherry-picks it.

(git fairies) $ git cherry-pick [A]


Oh noes, merge conflicts!

If there are merge conflicts, it stops and asks us to resolve them.


Okay, carry on

Once we do, we hand it back to Git to continue the process.

(you) $ git rebase --continue


Next, please

It proceeds to the next commit and cherry-picks it.

(git fairies) $ git cherry-pick [B]


More conflicts?! (facepalm)

If there are merge conflicts again, it stops and asks us to resolve them, just like before.


Grumble, grumble...

And, just like before, we do so and hand it back to Git to continue.

(you) $ git rebase --continue


You get the picture

The process continues until all of our commits have been copied over.

(you and the fairies) $ [...]


Order up!

Once it's finished, it overwrites our feature branch with the result and returns us to it.

(git fairies) $ git branch --force feature


I was never here...

Then it deletes the hidden REBASE branch.

(git fairies) $ git branch -D REBASE


fin (applause)

And we're done! Our commits now start from the current tip of the base branch, as if we had branched from there to begin with. Go ahead: take a bow.