datarekha

Remotes: fetch, pull, push

Learn how commits travel between your laptop and GitHub — and how to get your teammates' work back without clobbering anyone.

9 min read Intermediate Git Lesson 12 of 15

What you'll learn

  • What a remote is and why `origin` is the default name
  • The critical difference between `git fetch` (safe download) and `git pull` (download + merge)
  • How to handle a rejected push when the remote has commits you don't have yet

Before you start

The last chapter ended on exactly this realization: everything you have made so far lives only on your laptop, and the whole point was a team. This lesson is the handshake that ends the isolation. It rests on one new idea — a remote, a named address for another copy of your repo — and three verbs for moving commits across it: push, fetch, pull.

The distributed model in one sentence

Every git clone is a complete copy of the repository — history and all. There is no “master server” that holds the only real version. GitHub is just another copy that happens to be reachable over the internet and never goes to sleep.

Remotes are how Git tracks the addresses of other copies. A remote is nothing more than a named URL pointing to another repo. The convention is to call the first one origin — that is the copy you cloned from or the one you pushed to when you first shared your project.


Listing and adding remotes

After a clone, git remote -v shows the stored URLs:

git remote -v
origin  https://github.com/yourname/my-project.git (fetch)
origin  https://github.com/yourname/my-project.git (push)

Two lines per remote: one URL for downloading (fetch) and one for uploading (push). They are almost always identical.

If you started a repo locally with git init and now want to connect it to GitHub, add the remote by hand:

git remote add origin https://github.com/yourname/my-project.git

origin is just a name — you could call it github or upstream. But sticking to origin saves confusion with every tutorial and error message you will ever read.


Cloning: copy + wire up in one step

git clone https://github.com/yourname/my-project.git

git clone does three things at once: downloads the entire repository, creates a local directory, and automatically sets origin to the URL you gave it. After a clone you are ready to push and pull immediately.


The diagram: two repos, three arrows

Your Laptoplocal branch (main)origin/main (tracking)GitHub (origin)remote branch (main)git pushgit fetch / pull

git push sends your commits to origin. git fetch downloads theirs without touching your files. git pull fetches then merges.


Remote-tracking branches

After a fetch, Git stores what it downloaded in a remote-tracking branch — a read-only local reference like origin/main. You can inspect it:

git log origin/main --oneline

Your own main and the remote-tracking origin/main are separate pointers. They converge when you push or pull. This distinction is what makes git fetch safe: it updates origin/main without touching your working files or your local main.


Pushing for the first time: setting the upstream

git push -u origin main

The -u flag (short for --set-upstream) tells Git: “from now on, when I say git push or git pull on this branch, default to origin/main.” After that one-time setup you can type the short forms:

git push       # same as: git push origin main
git pull       # same as: git pull origin main

fetch vs pull — the key distinction

CommandWhat it doesTouches your files?
git fetchDownloads remote commits into origin/mainNo
git pullFetch + merge origin/main into your current branchYes

git fetch is the safer reflex: download first, look around, then decide how to integrate. git pull is the shortcut when you trust that the incoming changes will merge cleanly.

# safe pattern
git fetch
git log main..origin/main --oneline   # see what arrived
git merge origin/main                  # integrate when ready
# shortcut
git pull

For a linear history (no merge commit), use:

git pull --rebase

This replays your local commits on top of the fetched commits instead of creating a merge commit.


The rejected push: non-fast-forward



Putting it all together: a typical day

# morning: get the team's latest work
git fetch
git log main..origin/main --oneline   # see what came in overnight
git pull                               # merge it into your branch

# do your work, commit as usual
git add feature.py
git commit -m "add search filter"

# end of day: share your commits
git push

Quick reference

git remote -v                         # list remotes and their URLs
git remote add origin <url>           # connect a new remote called origin
git clone <url>                       # clone a repo (sets origin automatically)
git push -u origin main               # first push; sets upstream
git push                              # subsequent pushes (upstream already set)
git fetch                             # download remote commits, do not merge
git pull                              # fetch + merge
git pull --rebase                     # fetch + rebase (linear history)

In one breath

A remote is just a named URL for another copy of the repo; the first one is origin by convention, and git clone wires it up automatically. Three verbs move commits across it: git push sends your commits up (the first time, git push -u origin main sets the upstream so later you can type bare git push/git pull); git fetch downloads the remote’s commits into a read-only remote-tracking branch (origin/main) without touching your files — which is why it is the safe reflex; and git pull is fetch plus a merge into your current branch (--rebase for a linear one). If a teammate pushed first, your push is rejected as non-fast-forward — and the fix is always pull-then-push, never --force on a shared branch.

Practice

Before the quiz, work the rejection: you commit locally, run git push, and Git replies ! [rejected] ... (non-fast-forward). Explain in one breath what that message proves about origin/main versus your local main, the two-command fix that resolves it safely, and why reaching for git push --force here could quietly erase a teammate’s commit.

Quick check

0/3
Q1What does `git fetch` do that `git pull` does not?
Q2You run `git push` and get a 'non-fast-forward' rejection. What is the right next step?
Q3Your company has a monorepo on GitHub. You want to review a colleague's overnight commits before deciding whether to merge them into your feature branch. Which command is safest?

A question to carry forward

You can now move commits in both directions — but look closely at what this lesson quietly assumed: that you push straight to main. On a real team, almost nobody does. Pushing finished work directly onto the branch everyone depends on, with no second pair of eyes, is how bugs and bad ideas slip in. So the actual workflow wraps everything you just learned in one more step: you push your feature branch instead, then open a pull request — a formal “please review and merge this” — where teammates read your diff, comment, approve, and only then does it join main. That social layer on top of push and pull is the GitHub flow, and it is the next lesson — the one that ties this whole section together.

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Related lessons

Explore further

Glossary terms
Cheat sheets
Skip to content