DEV Community

Cover image for Git Rebase Explained Simply
Jacob Herrington (he/him)
Jacob Herrington (he/him)

Posted on • Updated on

Git Rebase Explained Simply

Rebase might be the most misunderstood git command.

Nearly every junior developer I pair with is terrified of git rebase.

Ironically, rebase is one of the few git commands I find myself using almost daily. Generally speaking, I rebase at least once for every pull request I make on GitHub.

I rebase to ensure that my commit messages make sense and that my branch won't have any serious, unexpected merge conflicts.

Using the git rebase command doesn't have to be complicated or intimidating, once you've got a handle on how it works and why it is useful.

Imagine you have two branches.

The first one looks like this:

3def6294 One more change that I made
579db95b Another change I made
f261ebba Some change that I made
13363dd3 Rails 5.2 features: enable cache ...
73188cd8 Sidekiq: add test helpers (#5326)
ba424854 Enable cache logging in development if requested (#5330)
51df3255 Change MentionJob to MentionWorker ...
Enter fullscreen mode Exit fullscreen mode

The second one looks like this:

242c6eb5 Change from after_create to ...
c64bfdb6 Handle missing commentable ...
cb98b3b5 pages bust cache job sidekiq refactor (#5338) [deploy]
df042d6b Refactors ActiveJob ...
783d43b7 Change create first reaction job to worker (#5327) [deploy]
c1638cfd Create UpdateAnalyticsWorker to replace UpdateAnalyticsJob (#5331)
040b36bc Fix event propagation for click on tag rules in editor (#5280) [deploy]
ba230eca Allow language-xxx class detection on pre tags in ReverseMarkdown (#5299)
13363dd3 Rails 5.2 features: enable cache ...
73188cd8 Sidekiq: add test helpers (#5326)
ba424854 Enable cache logging in development if requested (#5330)
51df3255 Change MentionJob to MentionWorker ...
Enter fullscreen mode Exit fullscreen mode

If you're looking closely, you'll have noticed that these two branches are identical from their bases until 13363dd3, where they diverge.

The first branch, which I'll refer to from now on as our working branch, has three commits that don't exist in the second branch.

The second branch, which I'll call master in this example, has eight commits that don't exist in our working branch.

In reality, it's extremely easy to end up in this situation. You can easily replicate this by working on a project with many other developers (like DEV) when you create a feature branch.

If your feature branch exists for a few days, it's likely that master will change before you are able to merge your branch back into master.

In that case, it'd be really convenient if you could catch your feature branch back up to master and bump your changes to the top of the git history.

If we caught our working branch back up to master and put those three commits on top, it might look like this:

3def6294 One more change that I made
579db95b Another change I made
f261ebba Some change that I made
242c6eb5 Change from after_create to ...
c64bfdb6 Handle missing commentable ...
cb98b3b5 pages bust cache job sidekiq refactor (#5338) [deploy]
df042d6b Refactors ActiveJob ...
783d43b7 Change create first reaction job to worker (#5327) [deploy]
c1638cfd Create UpdateAnalyticsWorker to replace UpdateAnalyticsJob (#5331)
040b36bc Fix event propagation for click on tag rules in editor (#5280) [deploy]
ba230eca Allow language-xxx class detection on pre tags in ReverseMarkdown (#5299)
13363dd3 Rails 5.2 features: enable cache ...
73188cd8 Sidekiq: add test helpers (#5326)
ba424854 Enable cache logging in development if requested (#5330)
51df3255 Change MentionJob to MentionWorker ...
Enter fullscreen mode Exit fullscreen mode

Doing something like that would make a pull request against master much cleaner and help us avoid merge conflicts.

Luckily, that is effectively what rebasing a branch does!

Let's talk about the name of this command: Rebase. What does that mean?

If you think of these two git branch like a tree trunk (the tree metaphor is constant in git), you can imagine that we'd like to replace the base of our working branch with the base of our master branch.

In other words, we'd like to "re-base" the working branch with the master branch.

Let's walk through a rebase.

I almost always use the -i (aka interactive) flag when I rebase because it makes it easier to reword commit messages, squash commits, or resort the order of commits. Those features of the git rebase command are beyond what I want to get into in this article, so we'll skip that for now, but I encourage you to try out the interactive flag.

Instead, assuming we have working-branch checked out on our local machine, rebasing is this simple:

git rebase master
Enter fullscreen mode Exit fullscreen mode

You'll see some console output:

First, rewinding head to replay your work on top of it...
Applying: Some change that I made
Applying: Another change I made
Applying: One more change that I made
Enter fullscreen mode Exit fullscreen mode

You can see that git is "replaying" our work, like a recording, on top of the master branch. That's not a bad metaphor for understanding how rebase works either.

When we log out our git history, you'll see that our changes have been replayed on top of the master branch.

3def6294 One more change that I made
579db95b Another change I made
f261ebba Some change that I made
242c6eb5 Change from after_create to ...
c64bfdb6 Handle missing commentable ...
cb98b3b5 pages bust cache job sidekiq refactor (#5338) [deploy]
df042d6b Refactors ActiveJob ...
783d43b7 Change create first reaction job to worker (#5327) [deploy]
c1638cfd Create UpdateAnalyticsWorker to replace UpdateAnalyticsJob (#5331)
040b36bc Fix event propagation for click on tag rules in editor (#5280) [deploy]
ba230eca Allow language-xxx class detection on pre tags in ReverseMarkdown (#5299)
13363dd3 Rails 5.2 features: enable cache ...
73188cd8 Sidekiq: add test helpers (#5326)

...

Enter fullscreen mode Exit fullscreen mode

In other words, we "re-based" our branch with master.

If using rebase still scares you, try making a copy of your working branch before you run the rebase command, just to be safe!

There's more...

I'm writing a lot of articles these days, I run a podcast, and I've started sending out a newsletter digest about all of the awesome stories I'm hearing.

You can also follow me on Twitter, where I make silly memes and talk about being a developer.

Top comments (26)

Collapse
 
murrayvarey profile image
MurrayVarey

I still feel a nervous tension whenever I rebase. It seems to depend on the context. Sometimes rebase feels like the obvious thing to do, other times I just know rebase is going to break everything ... until it doesn't. Basically, git can sometimes be scary.

Loving the series, Jacob. Thanks!

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Git is terrifying. That's a big part of the reason I chose to write about it.

These tools don't have to be scary, and hopefully writing about them in simple terms helps to dispel some of the mystery about them.

Collapse
 
murrayvarey profile image
MurrayVarey

Git is terrifying.

Yup! But I couldn't work without it.

For me, you're doing exactly that. Keep up the good work.

Collapse
 
harkinj profile image
harkinj

Great article. Can u confirm that u would typically pull the master branch (to ensure u have the latest master) before doing a 'git rebase master' as mentioned in article to rebase 'master onto a branch'. Thanks for your time.

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Yeah, generally that would be my workflow. 👍

Collapse
 
ryansmith profile image
Ryan Smith

Good stuff, this is an easy to understand explanation. For me, git rebase was an imposter-inducing concept because a lot of the information out there is so nonchalant ("just rebase") or so technical (a complex web with arrows everywhere) that it was hard to establish when to use it and how in a practical example, so thank you for that.

"Always Sunny in Philadelphia" meme of the character standing in front of an investigation board and a conspiracy-theorist look in his eyes

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Cool, I'm glad it was easy to understand; that was my primary goal.

Which is why the example is so simple (but a common problem nonetheless).

I'll probably do a follow up going over the -i flag and some more creative things you can do with rebase to make your life easier.

Collapse
 
thumbone profile image
Bernd Wechner

I'm one of the many who are nervous about rebase. And while I enjoyed this piece as one of the easier to read and digestible presentations of what is going on, it also exemplifies the source of my discomfort. It creeps into every tutorial I've read to date at some level or another and can be stated in one phrase: presumed knowledge.

That threw me reading this:

  1. What is the chronological order of the commits in your first two branch commit lists? I mean I could conclude (infer that they are most recent at top, oldest at bottom, by making the visual comparison you suggested, but I would still recommend stating it clearly).

  2. When in working-branch (with that branch checked out) you do git rebase master, it is worth stating up front the direction and end result. I infer the direction is that the checked-out branch is being "replayed" onto the branch mentioned in rebase. So that git rebase might be understood as git rebase current branch onto.

But I'm still left puzzled about (and maybe I'm just slow but I give the ubiquity of rebase fear I wonder ...):

a) what happened to the working-branch? Does it still exist, or does it disappear, all its commits now replayed onto master? Again from inference and other reads, I can infer it still exists but the parent of the first commit on that branch is now the head of main,

b) what does "replay" actually mean, if I imagine my commit as a delta then applying that to a new parent commit raises the risk of merge conflicts.

c) if there are merge conflicts, these may take time to resolve, time during which master may have new commits added to it. If working-branch is in fact the only thing being changed (that is important to say if so) and it stays around simply when a new parent then this is inconsequential I guess.

d) what exactly are the risk, what is being changed? I might infer that the whole git rebase master never touches or risks anything on master, only asks that the head of master be the new parent for the current branch and that we adjust the commits (with a merge tool as needed) to make that possible.

e) are there any GUI rebase tools or wizards for people not so comfortable with the CLI

Collapse
 
rhymes profile image
rhymes

I was terrified of rebase too for a long time

I think it's a failure in git's communication strategy 😂

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

I agree, it has a bit of a public perception problem. 😬🙃

Collapse
 
uuykay_1337 profile image
William

To be honest I'm still confused. What is the need for rebase, if you can merge master into the working branch?

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

For one thing, merging creates a merge commit which can clutter the git history. I don't feel as strongly about that as a lot of people do, but it's the most common argument for rebasing over merging.

Personally, I prefer rebasing because of the -i flag which allows you to re-order commits, reword their messages, squash, and manipulate commits in a bunch of cool ways!

Collapse
 
john2220 profile image
John Raptis

Great post. Explained simply indeed. I can't recall how many times I googled what rebase 'really' does and not just trusting stack overflow. Btw I love your podcast. Keep it up.

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

You talked me into it:

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Glad to hear it. Hopefully I get some new episodes up soon.

Collapse
 
mjtredoble profile image
Michael Joseph Redoble

Finally a simple and easy to understand article about git rebase.

At first I was terrified doing rebase but now its my daily habit on maintaining feature branch.

Collapse
 
harkinj profile image
harkinj

Great article. Would u typically do a 'git pull master' to ensure master is up to date before git rebase master? Thanks for your time.

Collapse
 
briankgarland profile image
Brian Garland

Ok, just so I’m clear:
From branch, checkout master.
Pull from origin to get master changes.
Go back to branch.
Run: Git Rebase Master

Like that?