Understanding Git Rebase Basics

Shane Kins
5 min readMar 31, 2022

Git rebasing is the process of rewriting your git history by changing the point of origin of the branch you’re working on. It’s helps you avoid complicated merge conflicts which can wreak havoc on your git log history.

Check out the official git docs for a deeper technical insight into how it works: https://git-scm.com/docs/git-rebase

Take this scenario for example: You’re developing a feature branch, and you’re missing some essential updates that have been recently added to the master branch. Your feature works, but you’re missing some commits from master that you want to test your feature on top of…

Git rebase can help you! While not screwing up your git history!!

What about git merge?

Git merge is arguably the easiest way to get the latest changes from your master branch into your feature branch, and is a valid way of getting the updates you need.

You’re checked out to your feature branch, and run git merge master— and Voilà! Your branch now has the latest updates from master.

But depending on how often you do this, your git history could be plagued with merge pull requests—rendering your git history unreliable and a chore to read…

- Merge pull request #123 from project/master
- Merge pull request #124 from project/master
- feat(Component): create new component
- Merge pull request #125 from project/master

While running a git merge is easier, it will be at the expense of the quality of your git history.

Rebase can be more complicated in some ways, but when done correctly, it keeps your logs clean and organised.

Some Examples

Before we start…

With my feature development process, I try to focus on continuous integration. I always start a new feature branch forking from master, and merge it right back in when I’m done.

If you prefer to use a different approach to organising your branches. For example, git-flow where you are using a develop branch for your features instead of master, these steps will still help you with what you need. You’ll just need to swap master with develop (or whatever branch you want to use).

I’m also using npm commands in these examples for test scripts. Maybe you are using a different package manager? Maybe you don’t have a test suite? In which case, you can leave these steps out.

Assuming we have a master branch, a feature branch, and maybe an other-feature branch:

SCENARIO 1 :: My feature is several commits behind master. I want to update my feature branch with the latest changes on master.

What I have…

feature incorporates both A and B commits, but not C and D. Commits C and D were created at some point after feature branch was created.

I want feature branch to incorporate commits C and D before I merge my branch into master, so I can ensure the feature works with the current state of master:

What I want!

SCENARIO 2 :: My feature was branched from another feature branch. I want to change this so my feature starts from master branch instead.

feature incorporates both A, B, E, and F commits, but not C and D. Commits C and D were created at some point after other-feature branch was created, and probably long before feature was created.

I want feature to be based directly on master, not other-feature. I don’t want commits E and F on my branch, and instead want to base feature on master, and encorporate commits C and D:

The goal of both scenarios are the same—We want feature to have all of the latest updates from master, and master alone, with a clean feature git history.

Rebase Preparation (master)

  • run git checkout master
  • run git pull to get the latest changes from remote
  • run npm test to ensure tests are passing.
  • If yours tests are failing here on master, it’s advised to resolve these issues before you rebase feature onto master.

Rebase Preparation (feature)

  • run git checkout feature
  • run git pull to get the latest changes from remote

Find the common ancestor with master using git-merge-base

  • run git checkout feature
  • run git merge-base master feature to find the most recent commit both branches have in common.
  • This will generate a long commit ID string looking something like this: abcdef1234567890abcdef.

Run git-rebase

  • NOTE: If you run into any issues, you can run git rebase --abort to cancel the entire process. Rebasing can be instantaneous when no conflicts are found, but if you’re rebasing a feature branch that is missing tens/hundreds or commits from master, expect a long process of fixing conflicts.
  • run git rebase --onto master abcdef1234567890abcdef. Replace the long ID string with the ID string generated on your end.
  • If conflicts are found, resolve any files and run git add . when done to stage the changes. Then run git rebase --continue to continue the process.
  • Eventually the process will complete, and your feature branch will now contain a clean record with all of the latest from master.
  • If your pre-rebased branch was pushed to upstream, you’ll need to run git push --force to overwrite the pre-rebased branch with your new clean rebased branch.

Conclusion

I’ve worked on a lot of projects in the past were git usage was used for little more than stage->commit->push and merge, with no regard for the quality of the project’s git history. Git becomes a useless tool for debugging, it’s tells you nothing meaningful about the project’s history, and results in gradual development slowdown over time…

You should ask yourself how important your git history is to your project. Having the ability to go back through a clean history where every commit is readable and means something is something that is easy to take for granted.

References

Git rebase: https://git-scm.com/docs/git-rebase
Git merge-base: https://git-scm.com/docs/git-merge-base
Attlasian: https://www.atlassian.com/git/tutorials/merging-vs-rebasing

--

--

Shane Kins
Shane Kins

Written by Shane Kins

Just another Fullstack Javascript/Typescript guy! With a focus on clean architecture and TDD. Currently based in Bangkok, Thailand.