1. Overview
While working with git as our Version Control System (VCS), we may follow any of the branching strategies, but eventually, we may need to integrate changes from one of the feature branches to the main or main branch.
In this tutorial, we’ll look at the two different ways in which we can integrate changes from one branch to another.
2. Git Rebase
To put it simply, git rebase takes your entire feature branch and moves it to the tip of the main branch. It creates brand new commits for each commit in the original feature branch.
Let’s create a new repository and a feature branch in the repository to understand how to rebase works:
git clone <your_repository_here>
git branch testBranch1
git branch testBranch2
Let’s create a new file in the testBranch1 feature branch and commit the changes:
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch1
git log
Executing these commands will give us the output below:
Now, let’s try to rebase this branch on the main branch:
git rebase main
This will result in the following message:
Since there are no commits in the main branch, we shouldn’t expect any changes, as evident above.
Now, let’s merge the feature branch onto the main branch:
git checkout main
git merge testBranch1
git push
git log
These commands will output the following:
There is no change to the commit ids from the feature branch while merging to the main branch. This is similar to what happens with fast-forward merge.
Since we have already merged testBranch1 to the main branch, testBranch2 is missing the commits from where it was cut.
Let’s take a look at how testBranch2 is rebased and merged.
Let’s create a new file in the testBranch2 feature branch and commit the changes:
git checkout testBranch2
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch2
git log
And after these command’s completion, we’ll see:
Now let’s try to rebase this branch on the main branch:
git rebase main
And this should give us a different message from the previous case:
Since there are some commits on the main branch, the feature branch was rebased on it. Now let’s merge the featureBranch2 on the main branch. We should expect the commit ids to be different for featureBranch2 before and after rebase:
git checkout main
git merge testBranch2
git push
git log
These commands will output the following:
The commit ids are different as expected, and if we take a look at the git log graph, we will see that the repo has a linear history:
git log --graph --oneline
The above command shows a graph structure displaying commit info in a single line:
3. Git Merge
Git merge will take the two branches we are merging, find the common base commit and then play the commit sequence from the two branches on the base commit to merge the branches.
Let’s create a new repository and a couple of feature branches to understand how merge works:
Clone the repository in your local machine and create a new feature branch:
git clone <your_repository_here>
git branch testBranch1
git branch testBranch2
Let’s create a new file in the testBranch1 feature branch and commit the changes:
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch1
git log
Executing these commands will give us the output below:
Now let’s merge this feature branch onto the main branch using the merge command:
git checkout main
git merge testBranch1
git push
git log
These commands will output the following:
We can notice that the latest commit ids are the same as the previous image, but the HEAD pointer is pointing to the main branch.
The above was a simple merge wherein there were no changes in the main branch while we were working on our feature branch.
Let’s look at another scenario where there are changes in both main and feature branches and how git handles them.
Let’s create a new file in the testBranch2 feature branch and commit the changes:
git checkout testBranch2
git add .
git commit -m "<Commit_Message_Here>"
git push --set-upstream origin testBranch2
git log
And after these command’s completion, we will get the following:
Now let’s merge this feature branch onto the main branch using the merge command:
git checkout main
git merge testBranch2
git log
We can then see it in the terminal:
There is a separate merge commit on which the HEAD is pointing now while the original commits are present for both the feature branches. The topmost commit also has an additional information key, “Merge”, which has the commit ids for both the branches.
We can also check the branch graph and verify the history of the repository:
git log --graph --oneline
The above command shows a graph structure displaying commit info in a single line:
4. Use Cases
Whenever we require our repository history to be linear, we should go for rebasing. But we should be careful about using rebase instead of merging on commits outside our repositories as other collaborators may have their own work based on the existing commits.
Rebasing already pushed commits on a public repo will result in different commit ids, which might make git think that the other developers’ main branch and your rebased main branch have diverged. This could create a potentially difficult situation for merging/syncing if there are multiple collaborators.
5. Conclusion
In this article, we covered the basic difference between git merge and git rebase which every developer should know while working with git VCS.