Start with the mental model
Rebase moves a line of commits so it appears to start from a different base commit. It can create a cleaner history, but because it rewrites commit identities, it should be used deliberately.
Main contains A → B → C. Your private feature branch started at B and added D → E. If you rebase the feature onto C, do D and E keep the same commit IDs?
Reveal the reasoning
No. Git replays the changes from D and E after C, so the new commits have different parents and therefore different identities—think D′ and E′. The patch can be equivalent while the commit objects are new.
Rebase is safest when the commits being rewritten are still private or the team has explicitly agreed that those published commit IDs may change.
Before you run it
- Run git status and make sure unrelated working-tree changes will not complicate recovery.
- Inspect git log --graph --oneline --decorate --all and identify the branch tip plus the exact upstream commit or remote-tracking branch.
- Confirm whether teammates already depend on the commits you are about to rewrite.
- State the intended graph in words before running the command: “Replay these local commits after this newer base.”
- Know that a Git branch name points to a commit rather than containing a separate copy of files.
- Be comfortable with git status, git log, commits, and switching branches.
- Understand that changing a commit creates a new commit ID even when the file content looks similar.
Options and the decision behind them
-i, --interactiveOpen a todo list so commits can be reordered, edited, squashed, or dropped.
Use it when: Cleaning a local feature branch before review.--continueContinue a paused rebase after conflicts are resolved and staged.
Use it when: After fixing files reported as conflicted during a rebase.--abortStop the rebase and restore the branch to its pre-rebase state.
Use it when: When the conflict set is surprising or you want to reconsider the approach.--skipOmit the currently replayed commit and continue.
Use it when: Only when you have verified that the commit is genuinely unnecessary, often because its change already exists upstream.Worked examples
Situation: Your feature branch has two local commits while main has advanced by one commit. You want your feature commits to sit after the new main commit.
git switch feature/login
git rebase main Git finds the commits that are unique to feature/login, temporarily removes them, moves the branch base to main, and then replays those feature commits in order. The replayed commits receive new IDs.
Typical output:
Successfully rebased and updated refs/heads/feature/login. Situation: You are about to open a pull request and want to incorporate the latest remote main without adding a merge commit to your local feature history.
git fetch origin
git rebase origin/main Fetching first updates your remote-tracking references without changing your working branch. Rebasing onto origin/main then uses the exact remote state you just fetched as the new base.
Situation: A feature works, but the history contains temporary fixup commits and an unclear message.
git rebase -i HEAD~4 Interactive rebase opens a todo list for the selected commits. Use actions such as reword, squash, fixup, or drop only after you understand how each commit contributes to the final change. This rewrites every affected commit from the first changed point onward.
When rebase pauses, recover from evidence—not conflict-marker guesswork
A paused rebase means one replayed change does not apply cleanly to the new base. Git is asking you to reconcile old intent with newer history one commit at a time.
Read the state
Use git status to identify the current replay step and conflicted paths.
git statusInspect the replayed change
Review the commit Git is trying to apply so you know the behavior it intended to introduce.
git rebase --show-current-patchResolve and verify intent
Edit the conflicted files into the behavior that should exist on the new base, then run focused tests or checks before staging.
Continue deliberately
Stage the resolved files and continue only after the result makes sense.
git add <resolved-files> git rebase --continueAbort when the plan is wrong
If the conflict set reveals that this rebase was the wrong integration strategy, restore the pre-rebase branch instead of forcing progress.
git rebase --abort
Common mistakes and why they fail
Treating rebase as a harmless visual rearrangement
A rebase does not merely redraw the graph. Replayed commits are new objects with new parent relationships and therefore new commit IDs.
Safer response: Before rebasing important work, confirm the branch state with git status and git log. If a rebase is going wrong, git rebase --abort is usually the safest immediate exit.
Rebasing commits that teammates already use
If other people have based work on the old commit IDs, rewriting those commits can create duplicate-looking histories and painful reconciliation.
Safer response: Prefer merging for shared published history unless the team has explicitly agreed on a rebase workflow.
Resolving conflicts without checking the resulting behavior
A conflict resolution can produce syntactically valid files while accidentally changing intent. The fact that Git can continue does not prove the program is correct.
Safer response: After resolving and staging conflicts, run focused tests or inspect the affected behavior before git rebase --continue.
Using --skip because a conflict is inconvenient
Skipping discards the currently replayed commit from the new history. That can silently remove required behavior.
Safer response: Skip only after proving the change is already represented or intentionally obsolete.
Guided practice
Your private feature branch has three local commits. origin/main moved forward while you were working. What sequence updates your view of the remote first and then replays only your private work onto that exact remote state?
Hint
Separate “learn the newest remote state” from “rewrite my local branch.” The first operation should not merge anything.
Tutor answer
git fetch origin
git rebase origin/maingit fetch updates origin/main without modifying your current branch. The rebase then has an explicit, inspectable target and rewrites only the feature commits that are unique to your branch.
Independent practice
Create a disposable repository with main and a private feature branch. Make main advance after the branch point, then add two feature commits. Draw the graph before rebasing, predict the new graph, run the rebase, inspect git log --graph --oneline --decorate --all, then use git reflog to locate the feature branch’s pre-rebase tip.
Related commands to keep nearby
git statusgit log --graph --oneline --decorategit fetchgit refloggit mergeKeep the working set small enough that each command has a clear job: inspect state, update remote knowledge, compare changes, integrate history, or recover from mistakes.
Frequently asked questions
Is rebase better than merge?
Neither is universally better. Rebase is useful for preparing a clean local line of work; merge preserves the true branch topology and is often safer for shared history. Choose based on collaboration rules and the history you need to preserve.
Why did my commit hashes change?
A commit ID includes information about its parent. Rebasing changes the parent chain, so the replayed commits become new commits even if their patches look identical.
What should I do when a rebase conflicts?
Read git status, resolve one conflicted file at a time, stage the resolved files, test the result where practical, then run git rebase --continue. Use git rebase --abort if the new history is not what you intended.
Can I undo a completed rebase?
Often yes if the earlier tip is still reachable through the reflog. Recovery is easier if you stop and inspect before doing additional destructive operations. Treat reflog recovery as a safety net, not the normal workflow.