Skip to main content
Git & GitHub · lesson 5 of 12
Git & GitHub beginner Lesson 5 of 12

Remotes: Fetch, Pull, Push, and Tracking Branches

Push to a real shared remote, have a second clone push a commit, then fetch and pull to see exactly what a tracking branch reports before and after merging.

By SkillByExample · Published

git remotes fetch pull

A remote is just another repository Git knows a URL for. This lesson uses a real second clone to simulate a colleague, so fetch and pull have something genuine to retrieve.

1) Register a remote and push with tracking

$ git remote add origin ../origin.git
$ git push -u origin main
branch 'main' set up to track 'origin/main'.
To ../origin.git
 * [new branch]      main -> main

-u does two things at once: pushes main, and records that local main tracks origin/main — the link that later lets plain git status, fetch, and pull work without spelling out remote and branch names.

2) A colleague clones and pushes their own commit

$ git clone origin.git colleague && cd colleague
$ # ...append version() to app.py...
$ git commit -am "Add version() helper"
$ git push origin main
$ git log --oneline -1
6d0fc2d Add version() helper

This is a second, independent clone of the same remote — a stand-in for a teammate’s machine. Its push updates the shared origin.git, but the original demo clone doesn’t know yet.

3) Fetch downloads without touching your branch

$ # ...back in the original demo clone...
$ git fetch origin
$ git status
From ../origin
   c489307..6d0fc2d  main       -> origin/main
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean

git fetch updated the remote-tracking ref origin/main to 6d0fc2d, but local main and the working directory are untouched — git status compares the two refs and reports the gap without merging anything.

4) Pull merges the fetched commit in

$ git pull
$ git log --oneline -2
Updating c489307..6d0fc2d
Fast-forward
 app.py | 4 ++++
 1 file changed, 4 insertions(+)
6d0fc2d Add version() helper
c489307 Urgent: add farewell test

git pull is git fetch followed by git merge origin/main (or rebase, if configured). Because local main hadn’t diverged from origin/main, the merge is another fast-forward — the same mechanism from the branching lesson, just against a remote-tracking branch instead of a local one.

Practice

  1. Run git branch -vv after the pull above to see which local branches track which remote branches, and whether they’re ahead/behind.

    Solution
    * main 6d0fc2d [origin/main] Add version() helper

    [origin/main] with no ahead/behind annotation means the two are in sync.

  2. Make a commit in demo and have the colleague clone push a different commit, so the two diverge. Run git pull and observe it now performs a real merge (or refuses, depending on your pull strategy config) instead of a fast-forward.

  3. Run git fetch origin then inspect origin/main directly with git log origin/main --oneline -1 before pulling, to confirm you can see incoming history without merging it.

  4. Push a new branch (not main) with git push -u origin feature/x, then in the colleague clone run git fetch and git checkout feature/x to confirm a fetch makes remote branches checkoutable locally.

  5. Run git remote show origin and read its summary of local branches, their tracked remote counterparts, and whether each is up to date.

Frequently Asked Questions

What's the actual difference between git fetch and git pull?
git fetch downloads new commits and updates your remote-tracking branch (origin/main) but never touches your own branch or working directory. git pull does a fetch and then immediately merges (or rebases) the result into your current branch. fetch lets you look before you merge; pull does both in one step.
What does 'Your branch is behind origin/main by 1 commit' actually mean?
It means your local main and origin/main (the remote-tracking branch, last updated by your most recent fetch) have diverged, and specifically that origin/main has a commit yours doesn't. It's Git comparing two local refs — no network call happens to print that message.
Why did git push -u matter, not just git push?
-u (--set-upstream) records that local main tracks origin/main, which is what lets plain git fetch/pull/push work afterward without naming the remote and branch every time, and is what makes git status able to report 'behind by N commits' at all.
Is origin a special name Git recognizes?
No — it's just the conventional default name for 'the remote you cloned from.' git remote add origin <url> could just as easily name it upstream or anything else; origin is a convention, not a keyword.