Rebasing is a Git command that helps you keep your code in sync with the latest changes in the upstream repository. In this article, we’ll cover what rebasing is, how to do it, and some tips for using it. What is rebasing? Rebasing is a Git command that helps you keep your code in sync with the latest changes in the upstream repository. When you rebase, Git updates your local copy of the code with the changes from the upstream repository. This makes it easy to track what changes have been made to your code since you last checked it out, and it also ensures that your local modifications are always consistent with the latest version of the code from the upstream repository. How do I do rebasing? There are two basic ways to do rebasing: manual and automatic. Manual rebasing involves editing your git commit history and using git rebase –interactive to update each commit with the changes from the upstream repository. Automatic rebasing uses a pre-defined strategy called a merge strategy, which determines how and when to update commits based on certain criteria (like whether or not a change conflicts with any other commits). We’ll discuss merge strategies later in this article. Some tips for using rebasing:

  1. Always use caution when performing rebases. Rebases can be dangerous if done incorrectly, leading to data loss or even corruption of your project’s source code. Make sure you understand all of the implications of any givenrebase before proceeding.
  2. Rebases should be used only when necessary; don’t try to force them onto projects that don’t need them. Rebases can introduce unwanted complexity into your project’s source code structure, making it harder to understand and maintain.
  3. Use git reflogs (or equivalent logging tools) to track which commits have been updated as a result of a rebase operation. This will help you avoid making mistakes during a rebase operation by ..

The Git Explosion

Frustrated with other version control systems and their slow updates and commits, Linus Torvalds, of Linux kernel fame, put aside a month in 2005 to write his own. He named it Git.

Sites like GitHub, GitLab, and BitBucket have symbiotically promoted and benefited from Git. Today Git is used globally, with a massive 98 percent of 71 thousand respondents in a 2022 survey using Git as the version control system.

One of Git’s main design decisions was speed. In particular, working with branches had to be as fast as possible. Branches are a fundamental part of version control systems. A project repository will have a main or master branch. This is where the project’s code base sits. Development, such as new features, takes place in segregated side branches. This stops the work done in branches from messing up the master branch, and it allows simultaneous development to happen in different parts of the code base.

As the developments in the side branches are completed, the changes are transferred to the master branch by merging the development branch into the master branch. In other version controls systems working with branches was difficult and computationally expensive. Working with branches in Git is very fast, and very lightweight. What was once a tedious and often avoided exercise in other systems, became trivial in Git.

The Git rebase command is another way of transferring the changes from one branch into another branch. The merge and rebase commands have similar objectives, but they achieve their ends in different ways and yield slightly different results.

What Is Git merge?

So what is the Git merge command for? Let’s say you’ve created a branch called dev-branch to work on a new feature.

You make a few commits, and test your new feature. It all works well. Now you want to send your new feature to the master branch. You must be in the master branch to merge another to it.

We can ensure we’re in the master branch by explicitly checking it out before we merge.

We can now tell Git to merge the dev-branch into the current branch, which is the master branch.

Our merge is completed for us. If you checkout the master branch and compile it, it’ll have the newly developed feature in it. What Git has actually performed is a three-way merge. it compares the most recent commits in the master and dev-branch branches, and the commit in the master branch immediately before the dev-branch was created. It then performs a commit on the master branch.

Merges are considered nondestructive because they don’t delete anything and they don’t change any of the Git history. The dev-branch still exists, and none of the previous commits are altered. A new commit is created that captures the results of the three-way merge.

After the merge, our Git repository looks like a timeline with an alternative line branching off and then returning to the main timeline.

The dev-branch branch has been incorporated into the master branch.

If you have a lot of branches in one project, the history of the project can become confusing. This is often the case if a project has many contributors. Because the development effort splits into many different paths, the development history is non-linear. Untangling the commit history becomes even more difficult if branches have their own branches.

Note that if you have uncommitted changes in the master branch, you’ll need to do something with these changes before you can merge anything to it. You could create a new branch and commit the changes there, and then do the merge. You’d then need to merge your temporary branch back into the master branch.

That works, but Git has a command that achieves the same thing, without having to create new branches. The stash command stores your uncommitted changes for you, and lets you call them back with stash pop .

You’d use them like this:

The end result is a merged branch, with your unsaved changes restored.

What Is Git rebase?

The Git rebase command achieves its aims in a completely different way. It takes all of the commits from the branch you’re going to rebase and replays them onto the end of the branch you’re rebasing onto.

Taking our previous example, before we performed any action our Git repository looks like this. We have a branch called dev-branch and we want to move those changes to the master branch.

After the rebase , it looks like a single, completely linear timeline of changes.

The dev-branch has been removed, and the commits in the dev-branch have been added to the master branch. The end result is the same as if the commits in the dev-branch had actually been directly committed to the master branch in the first place. The commits aren’t just tacked onto the master branch, they’re “replayed” and added fresh.

This is why the rebase command is considered destructive. The rebased branch no longer exists as a separate branch, and the Git history of your project has been rewritten. You can’t determine at some later point which commits were originally made to the dev-branch.

However, it does leave you with a simplified, linear, history. Compared to a repository with dozens or even hundreds of branches and merges, reading the Git log or using a graphical git GUI to look at a graph of the repository, a rebased repository is a breeze to understand.

How to Rebase Onto Another Branch

Let’s try a git rebase example. We’ve got a project with a branch called new-feature. We’d rebase that branch onto the master branch like this.

First, we check that the master branch has no outstanding changes.

We checkout the new-feature branch.

We tell Git to rebase the current branch onto the master branch.

We can see that we have still got two branches.

We swap back to the master branch

We merge the new-feature branch into the current branch, which in our case is the master branch.

Interestingly, we’ve still got two branches after the final merge.

The difference is, now the head of the new-feature branch and the head of the master branch are set to point to the same commit, and the Git history doesn’t show there used to be a separate new-feature branch, apart from the branch label.

Git Rebase vs. Merge: Which One Should You Use?

It’s not a case of rebase vs. merge. They’re both powerful commands and you’ll probably use them both. That said, there are use cases where rebase doesn’t really work that well. Unpicking mistakes caused by mistakes using merge are unpleasant, but unpicking errors caused by rebase is hellish.

If you’re the only developer using a repository, there’s less chance of you doing something with rebase that is disastrous. You could still rebase in the wrong direction for example, and rebase your master branch onto your new-feature branch. To get your master branch back, you’d need to rebase again, this time from your new-feature branch to your master branch. That would restore your master branch, albeit with an odd-looking history.

Don’t use rebase on shared branches where others are likely to work. Your changes to your repository are going to cause problems to a lot of people when you push your rebased code to your remote repository.

If your project has multiple contributors, the safe thing to do is only use rebase on your local repository, and not on public branches. Likewise, if pull requests form part of your code reviews, don’t use rebase. Or at least, don’t use rebase after creating the pull request. Other developers are likely to be looking at your commits, which means that those changes are on a public branch, even if they’re not on the master branch.

The danger is that you are going to rebase commits that have already been pushed to a remote repository, and other developers might have already based work on those commits. Your local rebase will make those existing commits vanish. If you push those changes to the repository you’re not going to be popular.

Other contributors will have to go through a messy merge to get their work pushed back to the repository. If you then pull their changes back to your local repository, you’re then faced with unpicking a mess of duplicated changes.

To Rebase, or Not to Rebase?

Rebase might be outlawed in your project. There may be local, cultural objections. Some projects or organizations consider rebase as a form of heresy, and an act of desecration. Some people believe the Git history should be an inviolable, permanent record of what has happened. So, rebase might be off the table.

But, used locally, on private branches, rebase is a useful tool.

Push after you’ve rebased, and restrict it to branches where you’re the only developer. Or at least, where all development has stopped, and no one else has based any other work off your branch’s commits.

Do that and you’ll avoid any issues.

RELATED: How to Check and Update Your Git Version