Working with Remotes
Table of Contents
- Three Copies of One Project
- origin/main: Your Last Look at GitHub
- Push from the Second Computer
- git fetch: Look Before You Leap
- git pull: Fetch and Merge
- Editing on GitHub Itself
- When Your Push Is Rejected
- Never Force-Push a Shared Branch
- Everyday Habits
- Try It Yourself
1. Three Copies of One Project
After the last chapter, your project exists in three places:
~/my-site ──push──► GitHub (origin) ◄──push── ~/my-site-laptop
◄──pull── ──pull──►
Each one is a full repository with its own history. They don't sync automatically. A commit you make in one place stays there until you push it, and nobody else sees it until they pull it.
That's exactly how a team works: every developer has their own clone,
and GitHub is the shared meeting point in the middle. In this chapter,
~/my-site-laptop plays the part of "another computer" — your laptop
at home, or a teammate.
2. origin/main: Your Last Look at GitHub
In ~/my-site, run:
git log --oneline --all -3
e2c4a91 (HEAD -> main, origin/main) Add README
a7f2c19 Merge branch 'new-title'
4d81e0b Use full name in page title
You've met main before. origin/main is new: it's your
repository's memory of where main was on GitHub, the last time
you talked to GitHub. It's called a remote-tracking branch.
The important word is memory. origin/main doesn't update by itself
— only when you push, fetch, or pull. Right now both labels point at
the same commit, so your copy and GitHub agree.
3. Push from the Second Computer
Switch to the "other computer":
cd ~/my-site-laptop
Add a line to the end of README.md:
Built in Phnom Penh while learning Git.
Commit and push:
git commit -am "Mention where the site was built"
git push
Now GitHub has a commit that ~/my-site has never seen.
4. git fetch: Look Before You Leap
Go back to your main copy:
cd ~/my-site
git status
On branch main
Your branch is up to date with 'origin/main'.
"Up to date" — but that's wrong! It's comparing with its memory of GitHub, and that memory is old. To refresh the memory, fetch:
git fetch
git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
git fetch downloads new commits from GitHub and moves origin/main,
but doesn't touch your files or your main branch. It's always
safe. You can look at what arrived before deciding what to do:
git log --oneline main..origin/main
b81d3f6 (origin/main) Mention where the site was built
(main..origin/main means "commits on origin/main that aren't on
main yet".)
5. git pull: Fetch and Merge
To bring those commits into your branch and your files:
git pull
Updating e2c4a91..b81d3f6
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
git pull is git fetch followed by git merge. It downloads the
new commits, then merges origin/main into your main — exactly like
merging a branch in chapter 6. Here it was a fast-forward, because you
had no new commits of your own.
Open README.md: the new line is there. Both computers now match
GitHub.
6. Editing on GitHub Itself
You can also make small changes straight on the GitHub website, which
is handy for fixing a typo in a README. Open README.md on GitHub,
click the pencil icon (Edit this file), make a change, and click
Commit changes…. GitHub asks for a commit message, just like the
terminal — write a good one and confirm.
That commit exists only on GitHub. Get it locally the usual way:
git pull
7. When Your Push Is Rejected
Now for the situation that happens to everyone: two people commit without pulling first.
In ~/my-site-laptop — which hasn't pulled the website edit from
section 6 yet — change something in about.html, commit, and try to
push:
cd ~/my-site-laptop
git commit -am "Add hobbies to about page"
git push
To https://github.com/dara-sok/my-site.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/dara-sok/my-site.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. ...
hint: ... use 'git pull' before pushing again.
GitHub refused, and that's a good thing. GitHub has a commit you don't have (the website edit). If it accepted your push, that commit would be thrown away. Git never lets a normal push destroy someone else's work.
The fix is what the hint says — pull first, then push:
git pull
Your branch and GitHub's have each moved on, so this pull creates a
merge commit (your editor opens with a message like
Merge branch 'main' of https://github.com/...; save and close). This
is the case pull.rebase false from chapter 2 was set up for: Git
merges, just like you've practised, instead of stopping to ask how to
combine them.
git push
Accepted. If both sides had changed the same lines, git pull would
have stopped with a merge conflict instead — and you already know how
to resolve those from chapter 7. Resolve, git add, git commit, then
git push.
8. Never Force-Push a Shared Branch
Sooner or later you'll find this command online:
git push --force
It tells GitHub "replace your branch with mine, whatever it has". It gets rid of rejected pushes by deleting the commits you didn't have. On a branch other people use, that means deleting their work.
This is the rule from chapter 5 in action: if you --amend or reset
commits that are already on GitHub, your history no longer matches
GitHub's, and your next push is rejected. The answer is not
--force — it's to avoid rewriting pushed commits in the first place,
and to use git revert instead.
(Experienced developers do sometimes force-push their own
feature branch that nobody else uses. That's a later topic. On main
or any shared branch: never.)
9. Everyday Habits
A few habits that keep remotes painless:
- Pull before you start working. Begin each session with
git pull, so you build on the latest version. - Commit small, push often. Every push is also a backup. If your laptop dies, anything pushed is safe.
- Read
git statusafter fetching. "Behind", "ahead", and "diverged" tell you exactly what to do next. - A rejected push is normal. Pull, resolve if needed, push again.
git status says | It means | Do this |
|---|---|---|
| up to date with 'origin/main' | Matches your last look at GitHub | git fetch to be sure |
| ahead of 'origin/main' by 2 commits | You have commits GitHub doesn't | git push |
| behind 'origin/main' by 1 commit | GitHub has commits you don't | git pull |
| have diverged | Both sides have new commits | git pull, then git push |
10. Try It Yourself
- Push from one copy, pull from the other. Commit in
~/my-site-laptop, push, thengit fetchandgit statusin~/my-sitebefore runninggit pull. - Edit on GitHub. Fix something in
README.mdon the website, then pull it into both local copies. - Get rejected on purpose. Commit in both local copies without
pulling, push one, then try to push the other. Fix it with
git pullandgit push. - Make it conflict. Repeat step 3, but change the same line of
the same file in both copies. Resolve the conflict that
git pullreports, then push. - Read the graph. Run
git log --oneline --graph --all -10and find the merge commits that your pulls created.
You can now keep any number of copies in sync. Next, let's use GitHub for what it does best: working with other people.
Buy Me a Coffee
Found this tutorial helpful? Consider buying me a coffee to support more free content!