Remotes: fetch, pull, push
Learn how commits travel between your laptop and GitHub — and how to get your teammates' work back without clobbering anyone.
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 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
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
| Command | What it does | Touches your files? |
|---|---|---|
git fetch | Downloads remote commits into origin/main | No |
git pull | Fetch + merge origin/main into your current branch | Yes |
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)