Key Takeaways:
- Many developers hear about Git Rebase with a warning that it can “ruin commit history,” which makes some avoid it.
- When used correctly, Git Rebase is safe and very powerful for maintaining a clean project history.
- Rebase reapplies your commits on top of the latest branch updates, creating a linear history instead of multiple merge commits.
- The main caution is that rebase rewrites commit history. Running it on the wrong branch or without care can cause conflicts or lost work.
- It’s most useful when you want a straightforward, readable history without extra merge clutter.
- Rebase is not a replacement for merging but a complementary tool for keeping branches up to date before integration.
- Use it carefully when collaborating with others—especially avoid rebasing public/shared branches.
- Following a step-by-step approach ensures safe usage and helps maintain consistency across the project.
- With practice, Git Rebase becomes a powerful ally for clean workflows and effective collaboration.
Table of Contents:
What is Git Rebase?
Git Rebase is a Git command that reapplies commits from your current branch onto the tip of another branch (or any target commit). Instead of creating a merge commit, it rewrites the branch history so it appears as if your work started from the newest version of the target branch.
“Git Rebase is a Git command used to integrate changes from one branch into another by moving your commits to the latest commit (tip) of the target branch”.
Unlike git merge, which creates a new merge commit and keeps the branching structure intact, rebase rewrites commit history. So, it looks as if your work started from the most recent state of the target branch.
The result is a clean, linear project history without unnecessary merge commits. The code itself remains the same, but the sequence of commits is reorganized. Since rebase creates new commit hashes, it should be used carefully. It should be avoided on public branches that others may already be using.
Git Rebase Syntax
git checkout <feature-branch>
git rebase <base-branch>
- <feature-branch>: branch that contains the commits to move.
- <base-branch>: branch onto which the commits will be reapplied, often main or master.
This updates the feature branch so its commits sit directly on top of the latest commit in the base branch.
When to Use Git Rebase
Git rebase is useful when you want to update your branch with the latest work from the main branch while maintaining a linear history. Instead of merging, which adds an extra commit, rebase moves your changes so they appear as if they were created after the newest commits on the target branch. Let’s understand it with an example.
How Git Rebase Works
Suppose you are building a search feature while your teammate updates the main branch with a security fix. Your branch is now behind the latest version of the project. Rebasing helps you move your commits on top of the updated main branch.
Visual Working of Git Rebase with Example
Before Rebase
- M1 → M2 → M3 → M4 are commits on the main branch.
- F1 → F2 are commits on the feature branch created from M2.
- At this point, the feature branch is outdated because main has moved ahead (M3, M4).
Run Rebase:
git checkout feature
git rebase main
After Rebase
Main: M1 → M2 → M3 → M4 → F1′ → F2′
- Commits F1 and F2 are replayed on top of M4.
- They become new commits F1′ and F2′.
- The history is now linear, making it look as if the feature branch was based on the latest main branch.
What Happens Internally
- Git finds the common ancestor (M2).
- Temporarily removes your commits (F1, F2).
- Updates the branch to the latest main (M3, M4).
- Reapplies your commits as new
Types of Git Rebase
Git rebase can run in two modes: Standard and Interactive. The difference comes down to whether you use the -i flag, while we have a third type, too. Let’s discuss them first to understand Git Standard vs Git Interactive Rebase.
1. Interactive Rebase (git rebase -i)
Interactive rebase allows you to edit your commit history before it’s finalized. You can reorder commits to follow a logical sequence, git squash several commits into one, or adjust commit messages for clarity. This is especially useful when you want your branch history to look polished before merging it into the main branch. Instead of just replaying commits, you can decide what happens to each one.
With it, you can:
- Reorder commits to arrange them in a logical sequence.
- Git Squash commits to combine multiple small commits into one.
- Edit commit messages to fix typos or add more clarity.
- Drop commits that are no longer relevant.
Example:
git checkout branch_x
git rebase -i master
This opens a commit list in your editor where you can choose actions. It’s often used before pushing a branch to clean up “work in progress” commits and present a structured sequence of commits.
2. Standard (Non-Interactive) Rebase
This is the default git rebase <branch> workflow. It simply reapplies your commits on top of another branch without any prompts or editing steps. Think of it as moving your entire branch forward so it sits on the latest commit of the target branch.
Example:
git checkout branch_x
git rebase master
This takes the commits from branch_x and places them on top of the latest master commit. The result is a clean, linear history without extra merge commits.
3. Auto-Merge Rebase
During a rebase, Git will try to apply each commit automatically. If your changes don’t overlap with updates in the target branch, Git will merge them without asking. However, if a conflict arises, Git will pause the process, allowing you to resolve it manually using git rebase –continue.
This type of rebase works best when you regularly rebase your feature branch. Frequent rebasing reduces the risk of large, messy conflicts later.
Common Git Rebase Commands
Here are some of the most frequently used commands when working with git rebase:
- git rebase master
Reapplies the commits from your current branch on top of the latest master.
- git rebase –continue
Resumes the rebase after you’ve fixed merge conflicts.
- git rebase –abort
Stops the rebase and resets the branch back to its original state.
- git rebase –skip
Skips the commit that caused a conflict and continues rebasing the rest. Use cautiously, since it may drop important changes.
- git rebase -i HEAD~3
Starts an interactive rebase for the last three commits, letting you reorder, squash, or edit commit messages.
Configuration Options in Git Rebase
Git rebase comes with several options that let you adjust how it works:
- –interactive or -i – Runs an interactive rebase so you can edit, squash, or reorder commits.
- –onto <newbase> – Moves a branch onto a different base commit. Useful when you need to rebase off something other than the original parent.
- –no-verify – Skips pre-commit and commit-msg hooks during rebase.
- –autosquash – Automatically squashes commits that were marked with fixup! or squash!.
Undoing a Rebase
If a rebase goes wrong and you want to roll back, use:
git reset --hard <branch-name>
This resets your branch to its state before the rebase started.
Recovering Lost Commits After a Rebase
Sometimes commits may appear “lost” after a rebase. They’re usually recoverable with these steps:
- Check the reflog
git reflog
This shows a history of commits, including ones that were moved or replaced.
- Create a new branch from the commit
git branch <new-branch> <commit-id>
- Cherry-pick the lost commits
git cherry-pick <commit-id>
- Resolve conflicts if needed
git add <file>
git rebase –continue
- Push the recovered branch
git push -u origin <new-branch>
With this process, even after an upstream rebase or a mistake, your work can be restored safely.
Handling Git Rebase Conflicts
Conflicts are common when rebasing, especially if both branches changed the same parts of a file. Here’s how to deal with them.
- Detecting conflicts
When a conflict occurs, Git will pause the rebase and mark the files that need attention.
- Resolve conflicts
Open the conflicted file(s).
Edit to keep the correct changes.
Stage the fixes:
git add <file>
Continue the rebase:
git rebase –continue
- Skip a commit
If a specific commit isn’t needed, you can skip it and continue:
git rebase –skip
- Abort the rebase
To cancel and return to the state before rebasing:
git rebase –abort
Note: In most cases, resolving and continuing is the right approach. Skipping or aborting should only be used if you’re sure the commit can be dropped or you want to start over.
Pushing Changes After a Rebase
When you rebase, Git rewrites commit history. That means the commits on your local branch no longer match the ones on the remote branch. If you try a normal git push, it will fail because Git thinks your branch is “behind.”
Why Push Fails
Rebase creates new commits (with new IDs), so the remote branch doesn’t recognize them as the same history.
Fixing It with –force-with-lease
Instead of overwriting blindly with git push –force, use:
git push --force-with-lease
This updates the remote branch but first checks if someone else pushed changes after your last fetch. It’s safer because it prevents you from accidentally deleting their work.
Best Practices for Git Rebase
- Always pull (git fetch) before pushing after a rebase.
- Use –force-with-lease instead of –force.
- Communicate with teammates before force-pushing to shared branches.
- Rebase local work only – don’t rewrite public history.
- Use interactive rebase to squash or reorder commits before pushing.
- Rebase often to keep your branch updated and avoid big conflicts.
- Check history with git log –oneline –graph after rebasing.
- Abort if stuck (git rebase –abort) and recover with git reflog if needed.
Git Rebase vs Merge: Which Should You Choose?
Both git merge and git rebase are used to integrate changes from one branch into another, but they handle history differently.
- Merge: Combines the histories of two branches by creating a new merge commit. The original commit structure is preserved, which can lead to a branching history with additional merge points.
- Rebase: Moves the commits from your branch onto the tip of another branch, rewriting commit history into a straight line. This avoids extra merge commits and produces a linear history.
Git rebase vs merge – Example:
- Using git merge, the history shows both branches and a merge commit.
- Using git rebase, the same commits appear as if they were created sequentially on top of the target branch.
When to use each Git rebase vs merge:
- Use merge when you want to preserve the exact history of how changes were integrated.
- Use rebase when you want a simplified, linear history that is easier to read and trace.
Table: Difference between Git rebase and merge
Context |
Rebase |
Merge |
Commit History |
Creates a clean, linear history by replaying commits on top of another branch. |
Preserves the full history, including branch points, and adds a merge commit. |
Workflow |
Ideal for updating a feature branch with the latest changes before merging. |
Suitable for combining work while keeping the complete development history. |
Commit IDs |
Rewrites commit IDs because it creates new commits during replay. |
Keeps original commit IDs intact. |
Collaboration |
Best for local branches that haven’t been pushed to a shared repository. |
Safer for shared branches since it doesn’t rewrite history. |
FAQs on Git Rebase
Q1. What is the difference between git rebase and git pull --rebase?
git rebase moves your branch commits onto another branch, while git pull –rebase updates your branch by rebasing it on top of the remote branch instead of creating a merge commit.
Q2. Can I undo a git rebase?
Yes. Use git rebase –abort to stop an ongoing rebase, or git reflog with git reset –hard to recover previous commits after a rebase.
Q3. Is rebase better than merge?
Rebase creates a clean, linear history by replaying commits, while merge preserves the true history with merge commits. Use rebase for a tidy project history, and merge for transparency of all branch activity.
Q4. How to squash commits using rebase?
Run git rebase -i HEAD~n and replace pick with squash (or s) for commits you want to combine. This merges multiple commits into one.
Q5. What happens if I rebase a shared branch?
Rebasing a shared branch rewrites its commit history, which can break others’ work. Avoid rebasing public or team-shared branches.
Q6. Why developers use git rebase?
Developers use Git Rebase to create a clean and linear commit history by placing their work on top of the latest changes from another branch. This makes the project history easier to read, reduces unnecessary merge commits, and simplifies debugging. Git Rebase is often used to update feature branches before merging them into the main branch.