Working with Remotes

Table of Contents

  1. Three Copies of One Project
  2. origin/main: Your Last Look at GitHub
  3. Push from the Second Computer
  4. git fetch: Look Before You Leap
  5. git pull: Fetch and Merge
  6. Editing on GitHub Itself
  7. When Your Push Is Rejected
  8. Never Force-Push a Shared Branch
  9. Everyday Habits
  10. 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 status after 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 saysIt meansDo this
up to date with 'origin/main'Matches your last look at GitHubgit fetch to be sure
ahead of 'origin/main' by 2 commitsYou have commits GitHub doesn'tgit push
behind 'origin/main' by 1 commitGitHub has commits you don'tgit pull
have divergedBoth sides have new commitsgit pull, then git push

10. Try It Yourself

  1. Push from one copy, pull from the other. Commit in ~/my-site-laptop, push, then git fetch and git status in ~/my-site before running git pull.
  2. Edit on GitHub. Fix something in README.md on the website, then pull it into both local copies.
  3. Get rejected on purpose. Commit in both local copies without pulling, push one, then try to push the other. Fix it with git pull and git push.
  4. Make it conflict. Repeat step 3, but change the same line of the same file in both copies. Resolve the conflict that git pull reports, then push.
  5. Read the graph. Run git log --oneline --graph --all -10 and 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!