Humans have always tried to rewrite history, and it didn’t always end well. Your mind is probably going to certain emperors and politicians, but developers do it too. One of the ways this is done is through Git rebase.
Prerequisites
To understand this article, you should have basic knowledge of Git, and understanding of commits, staging, and repositories.
What is Git rebase?
Git rebase is an operation that moves the commits from one branch so they are replayed on top of a different base commit on the target branch. Suppose your history looks like this,
gitGraph
commit id: "A"
commit id: "B"
branch feature
checkout feature
commit id: "C"
commit id: "D"
checkout main
commit id: "E"
commit id: "F"It’ll become like this:
gitGraph
commit id: "A"
commit id: "B"
commit id: "E"
commit id: "F"
branch feature
checkout feature
commit id: "C'"
commit id: "D'"During a rebase, Git doesn’t simply move the existing commits. Instead, it creates new commits (C’ and D’) that contain the same changes as C and D, but are based on the latest commit from the target branch (F in this example).
Because commits are snapshots of a project’s state rather than just a list of changes, the new commits C’ and D’ include the updates introduced by commits E and F, along with the changes originally made in C and D.
The base commit is the commit on which another commit is built. For example, commit B was created from the project state in commit A, so A is the base of B. During a rebase, Git changes the base of your branch from an older commit (such as B) to a newer one (such as F).
How do we rebase?
First switch to the branch you want to rebase:
git checkout feature
Then replay its commits on top of the main branch:
git rebase main
Git temporarily removes the commits unique to the feature branch, moves it to the tip of the main branch and reapplies those commits.
Rebasing keeps your commit history linear by avoiding unnecessary merge commits. This makes the project’s history easier to read, but it comes with an important caveat.
When you rebase, Git won’t allow you perform a normal push because your local branch’s history has diverged from the remote branch. To overwrite the remote history, you must perform a force push (typically push - - force-with-lease) which is why shared branches should be rebased with care.

When you encounter such an error, don’t do a git pull. That will do a git fetch and git merge which will merge the old branch from remote into your new local branch, thereby duplicating code changes in multiple commits. That will defeat the purpose of the rebase in the first place.
Also, if you push to the remote repository after rebasing, people whose work are based on the old commits will have divergent local Git histories from the remote repository, because those commits have been replaced with new ones (with new commit IDs). They would have to resolve those histories. Remember, you changed history. You impacted the world; just negatively.
gitGraph
commit id: "A"
commit id: "B"
branch feature
checkout feature
commit id: "C"
commit id: "D"
checkout main
commit id: "E"
checkout feature
commit id: "F"Parse error on line 1: gitGraph commit id: "A" --------^ Expecting ':', 'DIR', got 'NL'
Interactive rebase
With the normal git rebase command, git just replays commits in the order which they originally were made. It doesn’t interact with you or ask you how you want the rebase done.
However, you may want to pick which commits get replayed, or rearrange the order of the commits (why would you do that?), edit commits, or even drop some commits. Git provides you with an interactive rebase for such operations.
git rebase -i main
For example, to pick only the last four commits, you would run:
$ git rebase -i HEAD~4
With Git rebase, you have six keywords you can use:
pick– This is used to include the commit. The order of the picking determines the new order of the commits.reword– This is used to alter the commit message.edit– This is used to edit the contents of a commit; so you can add files or change code in a particular commit.squash– This allows you to combine two or more commits into one. You can then give that a new commit message.fixup– The same thing as squash, but it automatically takes the commit message of the earliest commitexec– This helps you run arbitrary shell commands.
Whenever you start an interactive rebase, it pauses the rebase operation and allows you to make your changes.
Then, you use this command to continue and finish the rebase operation:
git rebase - - continue
The Network Bits Newsletter
Get the latest articles on networking, cloud, DevOps, and infrastructure delivered straight to your inbox.
Git rebase vs merge
Both rebase and merge rewrite Git history, and update branches, but they do it in different ways. How do you know which one to use, and when?
Git rebase
Git rebase is a destructive operation, meaning it removes something when you run it. It removes the pointer from the already existing commits in a branch, leaving them hanging (orphaned). It can mess up the commit history, and make it impossible for others to follow the code changes.
Git merge
This follows a different approach. Git merge adds a new commit on the target branch, called a merge commit. This commit has all the changes from previous commits, and merges or combines them with the changes in the current branch. This is non-destructive and safe, but it messes up the commit history.
gitGraph
commit id: "A"
commit id: "B"
branch feature
checkout feature
commit id: "C"
commit id: "D"
checkout main
commit id: "E"
commit id: "F"
merge feature id: "merge commit"Handling conflicts
Let’s say you’re working on an e-commerce website. Another developer has built a product page, and you created another branch to add a discount badge for discounted prices. On the same file on the main branch, the other developer improves the formatting of prices.
gitGraph
commit id: "A: Add product page"
branch feature-discount
checkout feature-discount
commit id: "B: Add discount badge"
checkout main
commit id: "C: Format prices"
checkout feature-discountNow, if you want to rebase, there’ll be a conflict because the file you added your code to is no longer the same as it was when you branched out to edit it. The final code you’re trying to push has code that was changed in commit C, but you want to bring it back in your rebased commit as a commit after commit C. So, which one does Git choose? The previous version plus your new line, or the new version minus your new line?
In case of a conflict, the git rebase will pause, and you’d have to select what the final code should be. Git adds conflict markers to the code so you know where the conflict is.
<<<<<<< HEAD
<p>Price: $${product.price.toFixed(2)}</p>
=======
<p>Price: ${product.price}</p>
<p>10% OFF!</p>
>>>>>>> Add discount badge
When you’re done editing, you stage it and continue.
git add ProductCard.js
git rebase --continue
Conclusion
Git rebase is a powerful tool for keeping your commit history clean, linear, and easy to understand. By replaying commits onto a new base, it helps you incorporate the latest changes from another branch while keeping a linear history. Git rebase should, however, be used with caution.
If you enjoyed the article, subscribe to get more articles delivered directly to your inbox.

Leave a Reply