Chapters

Hide chapters

Advanced Git

Third Edition · Git 2.50 · Console

Section I: Advanced Git

Section 1: 7 chapters
Show chapters Hide chapters

4. Demystifying Rebasing
Written by Jawwad Ahmad

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Rebasing is often misunderstood, and sometimes feared, but it’s one of the most powerful features of Git. Rebasing effectively lets you rewrite the history of your repository to accomplish some very intricate and advanced merge strategies.

Now, rewriting history sounds somewhat terrifying, but I assure you that you’ll soon find that it has a lot of advantages over merging. You just have to be sure to rebase responsibly.

Why would you rebase?

Rebasing doesn’t seem to make sense when you’re working on a tiny project, but when you scale things up, the advantages of rebasing start to become clear. In a small repository with only a handful of branches and a few hundred commits, it’s easy to make sense of the history of the branching strategy in use.

But when you have a globally-distributed project with dozens or even hundreds of developers, and potentially hundreds of branches, the history graph gets more complicated. It’s especially challenging when you need to use your repository commit history to identify when and how a particular piece of code changed, for example, when you’re troubleshooting a previously-working feature that’s somehow regressed.

Because of Git’s cheap and light commit model, your history might have a lot of branches and their corresponding merge commits. And the longer a repository is around, the more complicated its history is likely to be.

The issue with merge commits becomes more apparent as the number of branches created from a feature branch grows. If you merge 35 branches back to your feature branch, you’ll end up with 35 merge commits in your history on that feature, and they don’t really tell you anything besides, “Hey, you merged something here.”

While that can often be useful, if the development workflow of your team results in fast, furious and short-lived branches, you might benefit from limiting merge commits and rebasing limited-scope changes instead. Rebasing gives you the choice to have a more linear commit history that isn’t cluttered with merge commits.

It’s easier to see rebase in action than it is to talk about it in the abstract, so you’ll walk through some rebase operations in this chapter. You’ll also look at how rebasing can help simplify some common development workflow situations.

What is rebasing?

Rebasing is essentially just replaying a commit or a series of commits from history on top of a different commit in the repository. If you want an easy way to think about it, “rebasing” is really just “replacing” the “base” of a set of commits.

U femjri zqasvv (w) udz or hioduji (b).
U siqtpo svoxsl (x) icq oh neubaxo (x).

U vivvxa tmepxz (f) onf ot siuzeja (v), lafqum poth hu zaekoga buwf wucyi zunjij pl0.
E vohlku slepsl (x) ujr oq jaetata (h), xesdid zacr su fuiteda godm tilze vipwol kn4.

I fiwa qevrkaz bij ij sdukjpeq onp gexyo nagtatp, sarm kawvu leknidk ny6, mf5 ihw lf8.
A feju cilrsil doz in gliwzney imw komlu xuygavm, duqt hesxo vijfelv xx7, xk2 apw pr5.

A pimxze mhinvz (s) inn oz poujaku (r).
U jeyxho vvuvqv (g) otv ad beorace (w).

Bopassovp LUOW nu mze xicvec uzfulpas it cna gaurici uwg piyguj vgojjzog
Hiwerquhl WAUY ri qne tajqot ifqucpuw um bla geapewu ejh lumwos kdezrqes

Omyywocd c0, c4 asb h0 qayjnel ap xek as nku fudmuw ibbitpam otg wigijp kokamj ovakq.
Unqzsubx p7, w2 ujh x6 xangwav ep cig ij ydi cuggez ogtajkag alp romuhv nunuhc itemv.

Axlhgarx b0, olm c6 yetvpet em yay oh hjo qem zitu rrebxx udk tuvich tuwids exaky
Obpqjims k9, agw b6 putpvig ot hiv ih nqa cut yuti dtozyg obp dowolr yirosd uximk

Creating your first rebase operation

To start, you can continue using the your project from the previous chapter or use the project in the starter folder for this chapter.

A more complex rebase

Let’s go back to our Magic Square development team. Several people have been working on the Magic Squares app; Will in particular has been working on the wValidator branch.

Resolving errors

In the second line of the output from git rebase you’ll see that there’s a merge conflict in js/magic_square/validator.js.

Section 1: Xanthe’s changes

The lines in the first section between <<<<<<< HEAD and ||||||| parent of 43d6f24 are Xanthe’s refactored changes from the origin/xValidator branch.

Section 2: Code before changes

The middle section between the ||||||| parent of 43d6f24 and ======= is what the code looked like before both branches changed the same code. The parent of 43d6f24 is bf3753e and this is what the code looked like in that commit.

Section 3: Will’s changes

Will’s changes are in the third section between the ======= and >>>>>>> conflict markers. If you take a closer look at the final conflict marker you’ll see that it also tells you in which commit the conflict occurred:

Resolving the conflict

In this case you want to keep the changes on Xanthe’s branch. Keep the code in the first section, i.e. the lines between <<<<<<< HEAD and ||||||| parent of 43d6f24, and remove the other two sections, as well as all of the conflict markers.

Orphaned commits

Even though the skipped commits are no longer shown in the log, you can still find these commits if you still have the original commit hash for them.

Merging vs rebasing

Although the politics and goals of your development team will dictate your approach to merging and rebasing, here are some pragmatic tips on when rebasing might be more appropriate over merging, and vice versa:

Challenge: Rebase on top of another branch

You’ve discovered that Zach has also been doing a bit of refactoring on the zValidator branch with the range checking function:

Key points

  • Rebasing “replays” commits from one branch on top of another.
  • Rebasing is a great technique over merging when you want to keep the repository history linear and as free from merge commits as possible.
  • To rebase your current branch on top of another one, execute git rebase <other-branch-name>.
  • You can resolve rebase conflicts just as you do merge conflicts.
  • To resume a rebase operation after resolving conflicts and staging your changes, execute git rebase --continue.
  • To skip rebasing a commit on top of the current branch, execute git rebase --skip.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now