Git & GitHub Fundamentals · Module 07 of 12

Remotes, fetch, pull and push

Understand remote-tracking references and exchange commits with a shared repository without confusing fetch, pull and push.

Learning objectives

By the end of this module, you should be able to:

  • Add and inspect a remote.
  • Explain fetch versus pull.
  • Push a branch and understand upstream tracking.

A remote is a named repository location

origin is only a conventional remote name. A clone usually creates it automatically, but any repository can have zero, one or many remotes.

fetch downloads; pull integrates

git fetch updates remote-tracking references such as origin/main without changing your current branch. git pull performs a fetch and then integrates according to configuration/options, so teams should choose merge, rebase or fast-forward policy deliberately.

push updates a remote reference

git push sends reachable objects and asks the remote to update a reference. The remote can reject the update because of permissions, non-fast-forward history or repository rules.

Worked examples

See the idea in practice.

Simulate a shared remote locally

git init --bare ../remote.git
git remote add origin ../remote.git
git push -u origin main
git fetch origin
git branch -vv
  • A bare repository can act as a remote without a working tree.
  • -u records upstream tracking for later status/push/pull behavior.
Hands-on lab

Lab — Push and fetch through a bare remote

Goal: Create a local bare remote, push main, clone it elsewhere, add a commit and fetch it back.

Before you start

  • Git 2.23 or newer is recommended so the labs can use git switch and git restore.
  • Run labs in a disposable working directory; the included validator creates and removes its own temporary repository.
STEP 1

Create remote and primary clone

mkdir -p ~/gnu-git-labs/module07 && cd ~/gnu-git-labs/module07
git init --bare remote.git
git clone remote.git work-a
cd work-a
git switch -c main
git config user.name "GNU Learner A"
git config user.email "a@example.invalid"
printf "one\n" > shared.txt
git add shared.txt && git commit -m "Initial shared content"
git push -u origin main
STEP 2

Create second clone

cd ~/gnu-git-labs/module07
git clone remote.git work-b
cd work-b
git switch main
git config user.name "GNU Learner B"
git config user.email "b@example.invalid"
printf "two\n" >> shared.txt
git commit -am "Extend shared content"
git push
STEP 3

Fetch without changing work-a

cd ~/gnu-git-labs/module07/work-a
git fetch origin
git log --oneline --decorate --all --graph
STEP 4

Fast-forward explicitly

git merge --ff-only origin/main
cat shared.txt

Verify

  • origin/main advances after fetch.
  • work-a main does not advance until explicit integration.
  • After fast-forward, shared.txt contains both lines.

Expected outcome

  • Learners can observe remote-tracking state independently from the local branch.

If it fails

  • If cloning an empty bare repository warns about HEAD, create/switch main explicitly as shown.
  • If push is rejected, fetch and inspect divergence before using force.
Real-world connection

This is the core transport model behind GitHub collaboration even though the remote URL is local in the lab.

Avoid these traps

Common mistakes

  • Thinking origin is a special server type.
  • Assuming fetch modifies the working tree.
  • Using force push to bypass a rejection without understanding why it occurred.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1What does git fetch normally update?

Remote-tracking references and downloaded objects, not the current branch content.

2What extra behavior does git pull add after fetching?

It integrates the fetched branch according to merge/rebase/fast-forward policy.

3What does git push -u origin main add?

It pushes main and records origin/main as its upstream tracking branch.