Remotes explained
A remote is a named reference to another copy of the repo, usually called origin. Remote-tracking branches like origin/main are read-only local mirrors updated only by git fetch. The key distinction: your local main versus origin/main, your last-known snapshot of the remote.
You clone a project from GitHub, make a commit, and run git status. It says Your branch is ahead of 'origin/main' by 1 commit. What is origin? What is origin/main, and why is it different from the main you are standing on? People wave these names around as if they are obvious, but they name three different things, and confusing them is the root of most “why won’t it push” confusion.
By the end of this lesson you will be able to explain what a remote is, what a remote-tracking branch like origin/main actually holds, and why it only changes when you ask it to.
After this lesson you can explain that a remote is a named URL to another copy of the repository, that origin/main is a read-only local mirror of the remote’s branch updated only by git fetch, and how that differs from your own local main.
A remote is just a saved name for the URL of another copy of your repository. Git does not hard-wire “the server” into a project. Instead it stores short names that point at full copies of the repo living elsewhere — on GitHub, GitLab, a colleague’s machine, or another folder on disk. List them with -v (verbose) to see the URLs:
git remote -v
# origin git@github.com:acme/app.git (fetch)
# origin git@github.com:acme/app.git (push)origin is the only thing here that is special — it is the conventional default name git gives the remote you cloned from. Nothing about the word “origin” is magic; you could rename it.
You add and inspect remotes with git remote. A repo can have many remotes — common when you forked a project and want both your fork and the upstream original:
git remote add upstream https://github.com/original/app.git
git remote -v # now shows both origin and upstream
git remote rename origin gh
git remote remove upstreamgit remote add <name> <url> simply records a name → URL mapping. It does not download anything yet. Fetching is a separate, explicit step.
origin/main is a remote-tracking branch — a read-only local mirror of a branch on the remote. This is the part beginners miss. When you clone, git creates two distinct things:
main— your local branch. You commit on it; it moves when you commit.origin/main— a remote-tracking branch. It is git’s local record of wheremainwas on the remote the last time you talked to the server.
You cannot commit onto origin/main. It is read-only. It is a bookmark, not a workspace.
git branch -a
# * main
# remotes/origin/main▸Why this works
Why keep a separate local copy of the remote’s branches at all? Because git is distributed and works offline. origin/main lets you answer “what was on the server last time I checked?” and compare it to your local work — git log main..origin/main — without any network call. The cost is that this mirror can be stale: it reflects your last sync, not the live server. Updating it is the job of git fetch, and nothing else moves it.
Only git fetch updates your remote-tracking branches. Editing files, committing, switching branches — none of it touches origin/main. The mirror moves forward only when you contact the server:
git fetch origin
# downloads new commits from the remote and
# advances origin/main to match the server — your
# local main is left exactly where it wasgit clone does this setup for you in one shot: it copies the whole history, creates the origin remote, creates origin/main, and checks out a local main already configured to track it.
Reading “ahead by 1 commit” correctly.
You clone acme/app. Right after cloning, main and origin/main point at the same commit c3. You write a fix and git commit — now local main points at your new commit c4, but origin/main is still at c3, because you have not contacted the server. git status reports “ahead of ‘origin/main’ by 1 commit” — it is comparing your branch to its last-known snapshot of the remote.
Meanwhile a teammate pushes their own commit c5 to the real remote. Your origin/main does not notice — it still says c3. Only when you run git fetch origin does git download c5 and move origin/main to it. Now git status can tell you the truth: your branch and the remote have diverged (you have c4, they have c5). The lesson: origin/main is a snapshot you control, not a live feed.
▸Common mistake
A frequent mistake is thinking git fetch changed your work because git status suddenly says “behind by 3 commits”. It changed nothing of yours — it only refreshed origin/main to the real server state, so git can finally report the true relationship. Your files and your local commits are untouched. Fetch is the safest remote command precisely because it only writes to remote-tracking branches, never to your working tree.
You just ran git commit locally. A teammate then pushed two commits to the GitHub remote. Before you run any other command, what does origin/main point at?
A remote is a saved name (default origin) for the URL of another full copy of the repository; git remote -v lists them and git remote add records new ones without downloading anything. A remote-tracking branch like origin/main is a read-only local mirror of a branch on the remote — git’s memory of where the server was the last time you synced. It moves only when you run git fetch, never when you commit, so your local main and origin/main routinely point at different commits. git clone wires all of this up automatically. Next you will learn how to actually move commits across that gap — git push and git pull.
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.