Working with remotes — clone, push, pull, and fetch
Everything so far has lived entirely on one machine. A remote is just another copy of the repository somewhere else — and push/pull/fetch are the specific ways two copies of the same history stay in sync.
3 min read
A remote is just another copy of the repository
Your laptop's repo <-----> GitHub's copy of the same repo
(local) (remote, named "origin")
Every clone of a Git repository — including one hosted on GitHub, GitLab, or a teammate's machine — is a genuinely complete copy, with the full commit history, exactly matching the "distributed" property from the first lesson in this domain. A remote is simply a name Git gives to one of these other copies, so commands can refer to it without retyping a full URL every time — origin is the conventional name for the remote a repository was originally cloned from, though it's just a label, not a special keyword.
git clone: getting a full local copy of a remote repository
git clone https://github.com/someuser/some-project.git
git clone downloads a remote repository's entire history and creates a local copy, automatically set up with that remote already configured as origin. This is normally the very first command run when starting to work on an existing project — after cloning, every earlier lesson in this domain (committing, branching, merging) works entirely locally, on this new local copy, exactly as if the repository had been created with git init from scratch.
git push: sending local commits to a remote
git push origin main
git push uploads commits that exist locally but not yet on the named remote — git push origin main sends the local main branch's commits to origin's copy of main. This is the point where local work (invisible to anyone else, per the branching lesson) actually becomes visible to whoever else has access to that remote — nothing is shared with a remote until it's explicitly pushed.
git pull: bringing a remote's new commits into the local branch
git pull origin main
git pull does the reverse — it fetches commits that exist on the remote but not yet locally, and merges them into the current local branch, in one combined step. If a teammate pushed commits to main since the last pull, git pull brings those commits down and merges them in — which can itself require the same conflict resolution covered in the branching lesson, if local and remote changes touched the same lines.
git fetch: seeing what's new, without merging it in yet
git fetch origin
git log origin/main -- see what's on the remote, without touching the local branch at all
git fetch downloads a remote's new commits but does not merge them into the current branch — it just updates Git's local knowledge of what the remote currently has (visible as origin/main, a separate reference from the local main). This is genuinely useful for reviewing what changed on the remote before deciding to merge it in — git pull is essentially git fetch immediately followed by a merge, and understanding fetch on its own is what makes clear exactly what pull is actually doing underneath.
Why push can be rejected: the remote has commits you don't
$ git push origin main
! [rejected] main -> main (fetch first)
error: failed to push some refs
Git rejects a push if the remote has commits the local branch doesn't have yet — pushing would otherwise silently discard whatever those remote commits were. The fix is to git pull first (bringing those remote commits down and merging or rebasing them in locally), then push again — this is Git actively protecting against one person's push accidentally erasing another person's already-shared work.
The mental model, put together
Every one of these commands is about reconciling two independent, potentially-diverging copies of the same history — the same underlying idea as merging two local branches (from the previous lesson), just applied between a local repository and a remote one instead of between two local branches.
Further reading
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What is a Git remote, conceptually?
2. What's the actual difference between git push and git pull?
3. Why is git fetch useful on its own, separate from git pull?
4. Why does git push sometimes get rejected with a 'fetch first' error?