One way to integrate branch updates and changes into the master is through a merge. Another way is to perform a master to branch rebase. The benefit of the latter is the clean, linear, non-branched commit history that elutes.
The drawback is the fact that changes to the commit history of the master branch are often rejected by tools like GitLab and GitHub due to the possibility that a master git rebase can negatively impact the ability of team members to push and pull from the central repository. In this example of how to git rebase master to any branch, we will not only show you how to do it, but explain the dangers of doing so as well.
The git rebase master process
In this git rebase example, we will take the master branch and rebase it onto the tip of the develop branch.
The develop branch split from master at commit C. Master and develop both contain files a.html, b.html and c.html. (View the image below for a visual reference.)
Commits D and E on the master branch happen after the develop branch split out on its own. This means master has files name d.html and e.html while the develop branch does not.
Two commits also occurred on the develop stream after the branch occurred. This means develop has two files master does not: f.html and g.html.
Git rebase master overview
After a successful rebase of master onto the develop branch:
- The files in the develop branch will not change
- The master branch will get files f.html and g.html from the develop branch
- The master stream’s branch point will change to the tip of develop.
- The new commit history will make it look like master branched off develop following commit G
- Before the master rebase, it was actually the develop branch which split from master
Master rebase git command
The operation to perform a Git rebase of master to the develop branch is fairly simple. To rebase master onto develop the syntax would look like this:
git rebase develop master
Caution: Do not use the rebase onto switch in this operation. The onto switch will cause commits to be lost and the commit points of both branches to reference each other. It is a common mistake developers often make, incorrectly thinking the –onto switch is required. It is not.
Before rebasing, both the master and develop branches had five files.
After the Git master rebase, the master branch file count is seven. The master branch has retained its original files and gained two new ones from develop. Note the file count in develop is the same as before the master git rebase branch operation was performed.
Do not be confused into thinking the develop branch would come away from the rebase operation with seven files as well. The master git rebase onto a branch operation will update the master branch, but the target of the rebase will stay unchanged.
Git rebase dangers
Note that after a rebase, the commit ids of the rebased branch are new. A rebase is not simply a moving of commits around in the history. Git actually creates brand new commits with new commit ids and permanently deletes the old commits. This is why a rebase can cause problems. If other developers are currently working on branches that stem from those deleted commits, they will not be able to push their changes back to origin, and a significant amount of work will be required to get their development efforts back into the central repository.
GitLab and GitHub rebase rejections
If you rebase a branch that was pulled from GitHub or GitLab, and then push it back, the server will reject it. In normal circumstances, the –force switch can be used to compel the server to accept the change. However, Git and GitHub typically employ some form of branch protection on master that forbids any forced pushes.
git push origin master --force
As such, without administrative privileges to the GitLab or GitHub master branch, you will not be able to forcefully push your master git rebase back to the server.
The git rebase master to branch operation is a dangerous one. Typically you should only clean up Git branches local to your workstation, not branches pulled from a central repository, as master typically is. Instead of a git master rebase, you might want to look at the git rebase branch to master operation instead. This allows you to squash Git commits and manipulate the history of branches that interact with master, while at the same time leaving the mater branch’s commit history alone.
You can find the code used in this example on GitHub.