Chapter 3: Branch, Merge, Rebase, Stash and Pull Requests
3.8 Rebase when it is safe — and when to merge instead
Why: the problem
Rebase takes your branch commits and replays them on top of another commit, usually the newest main. The result is a straight history, as if you started your work today. It is great for your own branch before an MR. But rebase creates new commits with new hashes. If you rebase a branch that teammates already pulled, their copy no longer matches and they get duplicate commits and confusion. The golden rule: rebase only commits that only you have. In this lesson you will rebase a hello-shop branch onto main, handle a conflict during rebase, clean up commits with interactive rebase using fixup and autosquash, see the hashes change, and recover with ORIG_HEAD and reflog if it goes wrong.
What we will build
You will rebase feature/offers on new main, solve a rebase conflict, squash fix commits with --autosquash, compare hashes before and after, and undo a bad rebase.
What: every term in plain English
- Rebase — Replay your commits on top of another base.
- Upstream base — The commit you rebase onto, usually origin/main.
- New hashes — Rebased commits are new commits.
- git rebase --continue — After fixing a conflict, go on.
- git rebase --abort — Stop and go back.
- Interactive rebase — git rebase -i: reorder, squash, edit commits.
- fixup! commit — A commit meant to be squashed into another by --autosquash.
- ORIG_HEAD — Where the branch was before the rebase.
How: step by step
-
Branch from main
cd ~/devops-lab/hello-shop && git switch -q main && git switch -qc feature/offersWhat it does: Your branch.
Output
(no output) -
Two commits
echo "offer=10" > offers.txt && git add . && git commit -qm "Add offers" && echo "offer_max=50" >> offers.txt && git commit -qam "Cap offer"What it does: Your work.
Output
(no output) -
Main moves
git switch -q main && echo "tax=18" > tax.txt && git add . && git commit -qm "Add GST" && git switch -q feature/offersWhat it does: Teammate work.
Output
(no output) -
Note old hash
git rev-parse --short HEADWhat it does: Before.
Output
6f6f6f6 -
Rebase
git rebase mainWhat it does: Replay.
Output
Successfully rebased and updated refs/heads/feature/offers. -
New hash
git rev-parse --short HEADWhat it does: Different.
Output
8a8a8a8 -
Straight line
git log --oneline -4What it does: Your commits after Add GST.
Output
8a8a8a8 Cap offer 7b7b7b7 Add offers 1c1c1c1 Add GST ...
Example 1: A conflict during rebase
Stack. Git
Goal. A conflict during rebase.
rebase-conflict.sh
git switch -q main && echo "offer=5" > offers.txt && git add . && git commit -qm "Default offer 5"
git switch -q feature/offers
git rebase main
git status -s
printf 'offer=10\noffer_max=50\n' > offers.txt
git add offers.txt
GIT_EDITOR=true git rebase --continue
git log --oneline -3
What each line does
main adds offers.txt too— Same file, same line.Rebase stops— Fix one commit at a time.git add + --continue— Go to the next commit.GIT_EDITOR=true— Keep the message without opening an editor.
Green output
CONFLICT (add/add): Merge conflict in offers.txt
error: could not apply 7b7b7b7... Add offers
AA offers.txt
Successfully rebased and updated refs/heads/feature/offers.
9c9c9c9 Cap offer
0d0d0d0 Add offers
2e2e2e2 Default offer 5
Expected result. In a rebase, fix, add, continue. Repeat until done.
Example 2: Clean commits with fixup and autosquash
Stack. Git
Goal. Clean commits with fixup and autosquash.
autosquash.sh
echo "# offers config" >> offers.txt && git commit -qam "Add comment"
sed -i 's/offer_max=50/offer_max=40/' offers.txt
git commit -q -a --fixup=HEAD~1
git log --oneline -3
GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash main
git log --oneline -3
What each line does
--fixup=HEAD~1— Make a commit named fixup! Cap offer.--autosquash— Moves and squashes it into Cap offer.GIT_SEQUENCE_EDITOR=true— Accept the plan without an editor.
Green output
3f3f3f3 fixup! Cap offer
4a4a4a4 Add comment
9c9c9c9 Cap offer
5b5b5b5 Add comment
6c6c6c6 Cap offer
0d0d0d0 Add offers
Expected result. Reviewers see clean commits, and the fix is inside the commit it belongs to.
Example 3: Undo a bad rebase
Stack. Git
Goal. Undo a bad rebase.
undo.sh
git rev-parse --short HEAD
git rebase -q main
git reset --hard ORIG_HEAD
git reflog -5
What each line does
ORIG_HEAD— Saved before the rebase.reset --hard ORIG_HEAD— Back to before. Lab only on your branch.reflog— Every place HEAD has been; another way back.
Green output
5b5b5b5
HEAD is now at 5b5b5b5 Add comment
5b5b5b5 HEAD@{0}: reset: moving to ORIG_HEAD
5b5b5b5 HEAD@{1}: rebase (finish): returning to refs/heads/feature/offers
Expected result. A rebase is never a dead end on your laptop.
Example 4: See why you must not rebase a shared branch
Stack. Git
Goal. See why you must not rebase a shared branch.
shared.sh
git push -q -u origin feature/offers
git rebase -q --force-rebase HEAD~2
git push
git status -sb
What each line does
Pushed earlier— Teammates may have it.--force-rebase— Makes new hashes.push rejected— The server has the old hashes.status— You diverged from your own server branch.
Green output
! [rejected] feature/offers -> feature/offers (non-fast-forward)
## feature/offers...origin/feature/offers [ahead 2, behind 2]
Expected result. On your own branch, use --force-with-lease. On a shared branch, merge instead.
Example 5: Rebase with autostash in one command
Stack. Git
Goal. Rebase with autostash in one command.
autostash.sh
echo "tmp" >> offers.txt
git rebase --autostash main
git status -s
What each line does
--autostash— Stash before, pop after.status— Your edit is still there.
Green output
Created autostash: 1f1f1f1
Applied autostash.
Successfully rebased and updated refs/heads/feature/offers.
M offers.txt
Expected result. No need to stash by hand.
Example 6: Reword an old commit message with interactive rebase
Stack. Git
Goal. Reword an old commit message with interactive rebase.
reword.sh
GIT_SEQUENCE_EDITOR="sed -i '1s/^pick/reword/'" GIT_EDITOR="sed -i '1s/.*/feat: add offers file (SHOP-220)/'" git rebase -i main
git log --oneline main..
What each line does
reword— Change only the message.GIT_SEQUENCE_EDITOR— Edits the todo list for you.GIT_EDITOR— Writes the new message.
Green output
6c6c6c6 Cap offer
1d1d1d1 feat: add offers file (SHOP-220)
Expected result. Messages fixed before the MR, without touching code.
Verify: did it work?
-
Straight history
git log --oneline --graph -4What it does: No joins.
Output
* 6c6c6c6 Cap offer ... -
No fixup left
git log --oneline main.. | grep -c fixupWhat it does: Zero.
Output
0 -
No rebase running
git status | head -1What it does: Normal branch.
Output
On branch feature/offers
When it is red 1
CONFLICT (content): Merge conflict in offers.txt / could not apply 7b7b7b7
Cause. Rebase hit a conflict.
Fix, step by step
- Fix the file
- git add FILE
- git rebase --continue
When it is red 2
fatal: It seems that there is already a rebase-merge directory
Cause. A rebase is still open.
Fix, step by step
- git rebase --continue or git rebase --abort
When it is red 3
! [rejected] feature/offers (non-fast-forward)
Cause. You rebased a pushed branch.
Fix, step by step
- If only you use it: git push --force-with-lease.
- If shared: reset to origin and merge instead.
When it is red 4
error: cannot rebase: You have unstaged changes.
Cause. Dirty tree.
Fix, step by step
- Commit or git stash first, or use --autostash.
Cleanup
-
Back to main
git switch -q mainWhat it does: Leave branch.
Output
(no output)
Ravindra Bagale's Tip
Rebase fakt aaplya branch var. Shared branch var rebase kela tar team la traas hoto!
Practice tasks
Easy Simple rebase
Why: Straight history.
What to do: Rebase onto moved main.
- git rebase main
Check: log is straight.
Medium Conflict
Why: Real case.
What to do: Fix a rebase conflict.
- --continue
Check: Rebase finishes.
Hard Autosquash
Why: Clean MR.
What to do: Squash a fixup commit.
- --fixup
- --autosquash
Check: No fixup in log.
Easy Say rebase in two lines
Why: If you can say it simply, you understand it. Interviewers want the short version first.
What to do: Write two short lines about rebase for a fresher who knows only basic Linux.
- Write the problem it solves.
- Write one real command or file that shows it.
- Read it aloud to a friend.
Check: A fresher understands it without asking a question.
Easy Make a safe lab folder
Why: Practice needs a place you can throw away. Then mistakes cost nothing.
What to do: Create a lab folder for this chapter and work only inside it.
- mkdir -p ~/devops-lab && cd ~/devops-lab
- Run every command of this lesson from here.
- Check with pwd before you delete anything.
Check: All lab files live in ~/devops-lab.
Medium Repeat it in a container
Why: Your laptop is not the server. A clean Ubuntu container shows what a fresh server needs.
What to do: Run the main steps of this lesson again inside an Ubuntu container.
- docker run --rm -it -v "$PWD":/lab -w /lab ubuntu:24.04 bash
- apt update and install what is missing.
- Note every missing tool.
Check: Same result inside the container, or a list of what you had to install.
Medium Break it on purpose
Why: You must know the red message by face. In an outage there is no time to read slowly.
What to do: Cause one error from the "When it is red" part of this lesson and fix it.
- Follow the error section.
- Copy the exact message into your notes.
- Write the fix in one line.
Check: You fixed it using only the steps, without searching the web.
Medium Write a one-page runbook
Why: At 2 a.m. nobody remembers the right command. A short page saves the on-call person.
What to do: Write a runbook page for this lesson.
- Title, when to use, exact command, how to check, how to undo.
Check: A teammate can follow it alone.
Hard Explain it like an interview
Why: Interviewers want real stories, not definitions.
What to do: Record a 60 second answer about this lesson.
- Say the problem, the command or file you used, and one error you hit.
Check: Your answer has a real command and a real error message.
Hard Draw the flow top to bottom
Why: A drawing shows who does what and in which order.
What to do: Draw this lesson as boxes from top to bottom.
- Start at the developer laptop, end at the user on the website.
Check: Each box matches a real thing you ran.
Homework: try at home
Try at home
Rebase a branch with three commits onto a moved main, create one conflict on purpose, and squash a fixup with --autosquash.
Recap
- Rebase replays commits on a new base.
- New hashes every time.
- Only rebase your own commits.
- fixup + autosquash cleans an MR.
- ORIG_HEAD and reflog undo it.
FAQ
Merge or rebase?
Rebase your own branch; merge shared ones. Follow team rules.
What is git pull --rebase?
fetch plus rebase on the upstream.
What is --autostash?
Stash and unstash for you around a rebase.
Can I rebase main?
Do not rebase a shared main.
What does git rebase -i let me do?
pick, reword, squash, fixup, drop and reorder commits.
Interview questions
-
What is git rebase?
Moving commits to a new base by replaying them.
-
When should you not rebase?
On commits that are public or shared.
-
Rebase vs merge?
Rebase gives linear history and new hashes; merge keeps history and adds a merge commit.
-
How do you squash commits?
git rebase -i and mark them squash or fixup.
-
How do you recover from a bad rebase?
git reflog and reset to the old commit or ORIG_HEAD.
Quick quiz
Q1. What does rebase change?
The base and the hashes of your commits.
Q2. Golden rule?
Do not rebase commits others have.
Q3. After fixing a conflict?
git add, then git rebase --continue.
Q4. How to undo?
git reset --hard ORIG_HEAD or use reflog.
Q5. Safe push after rebase?
git push --force-with-lease
Samajla ka?
Revision card
Interview card