Remotes
By the end of this lesson
Push, pull and fetch, and explain the difference between the last two.
A remote is a name for another copy of the repository, usually one hosted somewhere everybody can reach. Cloning sets one up automatically and calls it origin.
Naming it matters because your clone and the remote are two independent repositories that happen to share history. Neither is automatically aware of what the other has done. Every exchange between them is a command you run.
Three terms that explain most confusing remote behaviour:
- origin
- The conventional name for the remote you cloned from. It is a name, not a keyword — a repository can have several remotes with any names you like.
- Remote-tracking branch
- A local pointer recording where a remote branch was the last time you contacted it. You see them written as origin/main. You cannot commit to one; it is your cached note about their state.
- Upstream branch
- The remote branch your local branch is paired with. Once set, push and pull know where to go without being told. git push -u sets it the first time.
Fetch and pull are not the same command with different spellings
This is the distinction most worth getting right, because one of them changes your files and the other does not:
| git fetch | git pull | |
|---|---|---|
| What it does | Downloads new commits and updates origin/main | Runs fetch, then merges the result into your current branch |
| Touches your working files? | No | Yes |
| Can it cause a conflict? | No | Yes |
| Can it fail partway? | No — either it downloads or it does not | Yes, leaving you mid-merge |
| Safe to run at any moment? | Yes, including with uncommitted work | Not while you have uncommitted changes to the same files |
# What remotes does this repository know about?
git remote -v
# Download everything new. Your files do not change.
git fetch origin
# What have they done that I do not have?
git log --oneline main..origin/main
# What have I done that they do not have?
git log --oneline origin/main..main
# Happy with what you saw? Now bring it in.
git pull
# Send your commits, setting the upstream the first time
git push -u origin add-expense-export- git fetch is the one remote command with no capacity to disrupt your work. It updates origin/main and stops there.
- The two dots in main..origin/main mean "commits in the second that are not in the first". Reading it both ways tells you exactly how far the two have diverged.
- git pull is fetch followed by a merge into your current branch. Everything that can go wrong with a merge can go wrong here.
- git push sends your commits to the remote. It never changes anyone's working files — their next fetch or pull is what brings your work to them.
Summary
- A remote is a named reference to another copy of the repository; origin is the conventional name for the one you cloned
- origin/main is your cached note of where the remote branch was at your last fetch, not a branch you can commit to
- fetch downloads commits and changes nothing in your working directory
- pull is fetch plus a merge, so it can conflict and leave you partway through
- A rejected push means the remote has commits you lack — integrate them rather than forcing
Practice
Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.
Try it yourself
Watch fetch do nothing to your files
On a repository with a remote, note the output of git log --oneline. Run git fetch origin, then run git log --oneline again.
Now run git log --oneline origin/main. Explain why the two logs can differ even though you only ran one command in between.
Show solution
Your branch log is unchanged, because fetch did not touch your branch. The origin/main log may show commits you have never had, because fetch updated that pointer.
This is the whole idea in one observation. After a fetch you know what the remote has, and your own work is exactly where you left it. Merging is a separate, deliberate step.
Think about it
Think about it
Your push is rejected with a message saying the remote contains work you do not have locally. What has happened, and what are your options?
Show solution
Someone pushed commits to that branch after you last fetched. Your branch and the remote branch have diverged, so accepting your push as-is would mean discarding their commits.
The options are to fetch and merge their work into yours, or to fetch and rebase yours on top of theirs, then push. Which you choose depends on your team's convention.
The option that is not on the list is forcing the push. Git rejected it to protect commits you have not seen, and overriding that protection is how work goes missing.
Knowledge check
Nothing is recorded and there is no score. The explanation appears either way.
Saved in this browser only.