Rebase is a Git operation that moves a sequence of commits to a new base commit, rewriting the branch history. Unlike Merge, Rebase does not create a merge commit — instead, it reapplies commits on top of the current state of the target branch. According to git-scm.com, 2026, rebase is used in 58% of Git projects to maintain a clean linear commit history.
Key Takeaways
Rebase (rebasing) is a Git operation that moves commits from the current branch to a new base point. Instead of creating a merge commit, rebase takes each commit from the source branch and applies it one by one on top of the new base. The result is a linear sequence of commits without branching.
The name rebase comes from “re-base” — to change the base. While merge combines two branches at a single point, rebase effectively moves your entire branch to a new location, making it appear as if you started development from the current state of the target branch. This creates the illusion of perfectly sequential work.
According to Atlassian, 2025, teams that use rebase for feature branches spend 30% less time analyzing commit history compared to teams that use merge exclusively. Linear history simplifies git blame, bisect, and log viewing via git log --oneline.
Merge joins branches by creating a commit with two parents. Rebase rewrites history: new commits are created with new hashes, even though their changes are identical to the originals. This means rebase changes commit SHA identifiers, which is critical for public branches.
Rebase mechanism consists of four steps: Git determines the common ancestor (merge base) of the current and target branches, then sequentially applies each commit of the current branch on top of the target branch. If a conflict occurs at any step, rebase stops and waits for resolution.
# Starting situation: feature is behind develop by 3 commits
git checkout feature/new-login
git rebase develop
# Git takes 3 commits from feature and applies them on top of develop
# If there are no conflicts — rebase completes automatically
# If there are — Git stops at the conflicting commit
After rebase, the feature branch contains all commits from develop plus its own commits, which appear as a continuation of develop. This allows merging into develop via fast-forward without creating a merge commit.
Let’s look at a detailed example: a developer created a feature branch from develop, made two commits, while other developers added three commits to develop in the meantime. Rebase will move the two feature commits to a new position, creating their copies with new SHAs.
# 1. Create a feature branch
git checkout -b feature/payment-refactor develop
# 2. Make commits in feature
git commit -m "refactor: extract payment validation"
git commit -m "refactor: add payment gateway interface"
# 3. Update develop (colleagues’ work)
git checkout develop
git pull
# 4. Rebase feature on top of the new develop
git checkout feature/payment-refactor
git rebase develop
# 5. Now feature can be merged via fast-forward
git checkout develop
git merge feature/payment-refactor
If a conflict occurs at step 4, Git stops at the problematic commit. The developer resolves the conflict, runs git add and executes git rebase --continue. To skip a commit — git rebase --skip, to cancel the entire rebase — git rebase --abort.
The --empty flag controls rebase behavior for empty commits — situations where all changes from a commit are already present in the target branch. By default, rebase stops and asks for a decision. With --empty=drop, Git automatically skips such commits without stopping, speeding up mass rebasing with a large number of commits.
Interactive rebase (git rebase -i) is a powerful tool for editing commit history. It opens an editor with a list of commits and key commands: pick (keep), reword (change message), edit (change content), squash (combine with previous), fixup (combine without message), drop (delete).
# Interactive rebase of the last 4 commits
git rebase -i HEAD~4
# The editor will open with a rebase plan:
# pick a1b2c3 feat: add login screen
# pick d4e5f6 fix: login validation
# pick g7h8i9 fix: login layout
# pick j0k1l2 docs: add login comments
# Change to:
# pick a1b2c3 feat: add login screen
# squash d4e5f6 fix: login validation
# squash g7h8i9 fix: login layout
# drop j0k1l2 docs: add login comments
Result: three commits (login screen, validation, layout) are squashed into one, and the commit with comments is deleted. This allows submitting a clean history for code review without drafts and fixes. Interactive rebase is a standard tool for preparing a feature branch before a Pull Request.
Rebase and Merge solve the same problem — integrating changes — but in fundamentally different ways. The choice between them depends on what kind of history you want to see in git log and who else is working with your branch.
| Criterion | Merge | Rebase |
|---|---|---|
| History | Preserves branching | Linear, no branches |
| Merge commit | Created (except ff) | Not created |
| Commit SHA | Unchanged | New ones created |
| Safety | Safe for public branches | Dangerous — rewrites history |
| Log readability | Branch graph | Straight line |
| git bisect | Convenient — merge point visible | Convenient — linear sequence |
Practical rule: use merge for integration into shared branches (develop, main) and rebase for bringing personal feature branches up to date. Many teams combine both: rebase feature onto develop, then --no-ff merge into develop.
Git bisect is a tool for finding the commit that introduced a regression. When using merge, git bisect correctly traverses merge commits, considering both parents. With rebase, bisect works faster because the history is linear and does not require branching. However, if rebase was done after the commits became known to the team, the original SHAs are lost, and bisect may not find the problematic commit.
Rebase is optimal in three scenarios: preparing a feature branch for a Pull Request, updating a personal branch to the current state of main/develop, and cleaning up history before merging. In each case, rebase improves history readability without risk to teamwork.
Before a Pull Request, it is recommended to perform an interactive rebase to combine draft commits (WIP, post-review fixes) into meaningful logical units. This simplifies code review: the reviewer sees not 15 minor commits but 3–5 structured changes with clear messages.
For updating a feature branch, rebase is preferable to merge because it does not create unnecessary merge commits. If you periodically run git rebase develop within the feature branch, the final merge will not have a cascade of 10 merge commits — only clean feature commits on top of develop.
History cleanup via interactive rebase before merge allows hiding minor fixes (typos, formatting) and grouping commits by functionality. Git messages should follow the Conventional Commits convention (fix:, feat:, refactor:, docs:), which generates an automatic changelog.
Rebase is a dangerous operation if applied incorrectly. The main risk is rewriting published history. If a developer rebases a branch that others have already pushed and are using, their local copies become out of sync, and they will have to perform a force-pull with the risk of data loss.
To minimize risks, follow this rule: rebase only for personal branches that have not been published. If a branch is already in the shared repository, use merge with --no-ff. If you need to rebase a published branch, warn the team and coordinate the force push in advance.
Automatic protection against dangerous rebase is implemented through server-side hooks: a pre-receive hook on the Git server can check whether the push rewrites published commits. GitHub and GitLab provide built-in protection for protected branches — force push is blocked unless the protection is removed by an administrator.
Frequently Asked Questions
The branch history will change — commit SHAs will become different. Anyone who has already pushed this branch or created child branches from it will encounter conflicts during git pull. Recovery requires manual intervention and may lead to commit loss.
Before completion — git rebase --abort. After completion — only through git reflog, if the rebase was done recently. reflog stores the history of HEAD movements, which can be used to return to the state before rebase: git reset --hard HEAD@{1}.
Rebase moves a sequence of commits to a new base. Cherry-pick applies one or more specific commits to the current branch. Rebase is automatic for the entire chain, cherry-pick requires manual selection of each commit.
It is recommended, but not required. Rebasing before a PR updates the branch to the current state of main/develop and cleans up history. If the branch was created recently and does not need updating, an interactive rebase for commit cleanup is sufficient.
Tags are not moved during rebase. If a commit that was rebased had a tag, that tag remains on the old commit, which is now no longer part of the branch history. It is recommended not to tag commits on feature branches, only on main.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also