Chapter 3: Branch, Merge, Rebase, Stash and Pull Requests
3.4 Fetch vs pull vs push
Why: the problem
Many freshers type git pull for everything and are surprised when it creates a merge commit or a conflict. Three commands move work between your laptop and the server, and each does a different job. git fetch only downloads new commits and updates origin/main; it never touches your files. git pull is fetch plus merge (or rebase) into your current branch, so it changes your files. git push uploads your commits and moves the branch on the server. Knowing the difference stops surprises: at a bank like HDFC, the release engineer always fetches first, looks at what changed, and only then merges. In this lesson you will use two clones to watch exactly what each command changes, set pull to rebase, and handle a rejected push the right way.
What we will build
You will make a server and two clones, push from one, then compare fetch and pull in the other. You will look at origin/main before and after each command, set pull.rebase, and fix a rejected push.
What: every term in plain English
- Remote — A named server URL, usually origin.
- origin/main — Your local copy of where main is on the server. Updated only by fetch or pull.
- git fetch — Download new commits. Does not change your branch or files.
- git pull — fetch plus merge or rebase into the current branch.
- git push — Upload commits and move the server branch.
- Ahead / behind — How many commits you have that the server does not, and the other way.
- Non-fast-forward — The server has commits you do not; push is rejected.
- pull.rebase — A setting that makes pull use rebase instead of merge.
How: step by step
-
Make a lab
mkdir -p ~/devops-lab/fp && cd ~/devops-lab/fp && git init -q --bare -b main srv.git && git clone -q srv.git a && git clone -q srv.git bWhat it does: Server plus two clones.
Output
(no output) -
First push from a
cd a && echo v1 > app.txt && git add . && git commit -qm v1 && git push -q -u origin mainWhat it does: Server has v1.
Output
(no output) -
b pulls
cd ../b && git pull -q && cat app.txtWhat it does: b is equal.
Output
v1 -
a pushes v2
cd ../a && echo v2 > app.txt && git commit -qam v2 && git push -qWhat it does: Server moves to v2.
Output
(no output) -
b fetches
cd ../b && git fetch && git status -sbWhat it does: Downloaded but files unchanged.
Output
## main...origin/main [behind 1] -
b looks before merge
git log --oneline main..origin/main && git diff main origin/mainWhat it does: Review what is coming.
Output
a2a2a2a v2 -v1 +v2 -
b merges
git merge -q origin/main && cat app.txtWhat it does: Now files change.
Output
v2
Example 1: Prove fetch does not touch your files
Stack. Git
Goal. Prove fetch does not touch your files.
fetch-safe.sh
cd ~/devops-lab/fp/a && echo v3 > app.txt && git commit -qam v3 && git push -q
cd ../b
md5sum app.txt
git rev-parse --short main origin/main
git fetch -q
md5sum app.txt
git rev-parse --short main origin/main
What each line does
md5sum app.txt— A fingerprint of the file.rev-parse main origin/main— Where both labels point.After fetch— The file is the same; only origin/main moved.
Green output
0f1e2d... app.txt
a2a2a2a
a2a2a2a
0f1e2d... app.txt
a2a2a2a
b3b3b3b
Expected result. Fetch is always safe. Run it any time to see what is new.
Example 2: See the merge commit that pull can create
Stack. Git
Goal. See the merge commit that pull can create.
pull-merge.sh
cd ~/devops-lab/fp/b
echo "note" > notes.txt && git add . && git commit -qm "b note"
git config pull.rebase false
git pull --no-edit
git log --oneline --graph -4
What each line does
b has its own commit— Both sides moved: diverged.pull.rebase false— Use merge.--no-edit— Accept the default merge message.--graph— Shows the extra merge commit.
Green output
Merge made by the 'ort' strategy.
* c4c4c4c Merge branch 'main' of /home/ravi/devops-lab/fp/srv
|\
| * b3b3b3b v3
* | d5d5d5d b note
|/
* a2a2a2a v2
Expected result. A merge commit appeared just because you pulled. Many teams do not want these.
Example 3: Use pull with rebase for a straight history
Stack. Git
Goal. Use pull with rebase for a straight history.
pull-rebase.sh
cd ~/devops-lab/fp/a && echo v4 > app.txt && git commit -qam v4 && git push -q
cd ../b && echo "more" >> notes.txt && git commit -qam "b more"
git config --global pull.rebase true
git pull
git log --oneline --graph -3
git push -q && git status -sb
What each line does
pull.rebase true— Replay your local commits on top of the server ones.--global— For all repos on your laptop.Straight line— No merge commit.
Green output
Successfully rebased and updated refs/heads/main.
* e6e6e6e b more
* f7f7f7f v4
* c4c4c4c Merge branch 'main' ...
## main...origin/main
Expected result. History stays clean. This is the most common team setting.
Example 4: Fix a rejected push the right way
Stack. Git
Goal. Fix a rejected push the right way.
rejected.sh
cd ~/devops-lab/fp/a && echo v5 > app.txt && git commit -qam v5
cd ../b && echo v5b > other.txt && git add . && git commit -qm v5b && git push -q
cd ../a
git push
git pull --rebase
git push
What each line does
First git push— Rejected: b pushed first.Do not use --force— It would delete the b commit on the server.pull --rebase then push— Add the b commit, then yours on top.
Green output
! [rejected] main -> main (fetch first)
error: failed to push some refs to '/home/ravi/devops-lab/fp/srv.git'
Successfully rebased and updated refs/heads/main.
To /home/ravi/devops-lab/fp/srv.git
0a0a0a0..1b1b1b1 main -> main
Expected result. Both commits are safe on the server.
Example 5: Fetch everything and prune in one go
Stack. Git
Goal. Fetch everything and prune in one go.
fetch-all.sh
git config --global fetch.prune true
git fetch --all
git branch -vv
What each line does
fetch.prune— Always remove deleted server branches.--all— All remotes.-vv— Ahead and behind counts.
Green output
Fetching origin
* main 1b1b1b1 [origin/main] v5
Expected result. Your remote list always matches the server.
Verify: did it work?
-
a and b equal
cd ~/devops-lab/fp && git -C a pull -q && git -C a rev-parse --short HEAD && git -C b rev-parse --short HEADWhat it does: Same commit.
Output
1b1b1b1 1b1b1b1 -
Ahead/behind zero
git -C b status -sbWhat it does: No numbers.
Output
## main...origin/main -
Setting
git config --global pull.rebaseWhat it does: Should be true.
Output
true
When it is red 1
! [rejected] main -> main (fetch first)
Cause. The server has commits you do not.
Fix, step by step
- git pull --rebase
- git push
When it is red 2
hint: You have divergent branches and need to specify how to reconcile them.
Cause. pull.rebase not set and both sides moved.
Fix, step by step
- git config --global pull.rebase true
- git pull
When it is red 3
fatal: 'origin' does not appear to be a git repository
Cause. No remote named origin.
Fix, step by step
- git remote -v
- git remote add origin git@gitlab.com:ravi-learner/hello-shop.git
When it is red 4
There is no tracking information for the current branch.
Cause. The branch has no upstream.
Fix, step by step
- git push -u origin BRANCH, or git branch --set-upstream-to=origin/BRANCH
Cleanup
-
Remove lab
rm -rf ~/devops-lab/fpWhat it does: All three repos.
Output
(no output)
Ravindra Bagale's Tip
Aadhi fetch, mag bagha, mag pull. Rejected push la --force kadhi naka!
Practice tasks
Easy Watch fetch
Why: Build trust.
What to do: Fetch and compare main with origin/main.
- git fetch
- git status -sb
Check: Shows behind N.
Medium Compare pulls
Why: See the merge commit.
What to do: Pull with rebase false then true.
- git log --graph
Check: You see both histories.
Hard Rejected push
Why: Daily problem.
What to do: Make a push fail and fix without force.
- git pull --rebase
Check: Both commits on server.
Easy Say fetch vs pull vs push 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 fetch vs pull vs push 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
Repeat the lab and write, for each of fetch, pull and push, what changed: your files, your branch, origin/main, or the server.
Recap
- fetch downloads only.
- pull = fetch + merge or rebase.
- push uploads and can be rejected.
- Set pull.rebase true.
- Never force-push to fix a rejected main.
FAQ
Should I fetch or pull in the morning?
Fetch first, look at the log, then pull.
What is git pull --ff-only?
Pull only if no merge is needed; otherwise stop.
Is git remote update the same as fetch?
Similar: it fetches all remotes.
Why is my branch ahead 3?
You have 3 local commits not pushed.
Can I fetch one branch?
Yes: git fetch origin main.
Interview questions
-
Difference between fetch and pull?
fetch downloads only; pull also integrates into your branch.
-
Why would a push be rejected?
Non-fast-forward: the remote has commits you lack.
-
What is origin/main?
A remote-tracking branch, your last known copy of the server main.
-
Merge vs rebase pull?
Merge adds a merge commit; rebase keeps a straight line.
-
When is force push OK?
Only on your own branch, with --force-with-lease.
Quick quiz
Q1. Does fetch change your files?
No.
Q2. What is pull made of?
fetch plus merge or rebase.
Q3. What updates origin/main?
fetch or pull.
Q4. Push rejected; first step?
git pull --rebase.
Q5. Setting for rebase pulls?
git config --global pull.rebase true
Samajla ka?
Revision card
Interview card