Remotes

Work with a copy of the repository on a server without ever being surprised by it.

11of 16
≈ 13Min read
5Parts

A remote is just another repository

GitHub is not part of git. A remote is a named URL pointing at another copy of the same repository, and push and fetch copy objects between them. Everything you have learned so far works with no network at all.

naming one
git remote add origin https://github.com/you/doors.git
git remote -v
git remote rename origin upstream
git remote remove origin
"origin" is only a convention

It is the default name git clone gives the place you cloned from. A fork usually has two: origin (yours) and upstream (the original).

Three kinds of branch

origin/main is not the server. It is a note your repository keeps, updated only when you talk to the server. That single fact explains every "but I pulled ten minutes ago" conversation.

NameIsMoves when
mainyour local branchyou commit
origin/mainyour record of where their main wasyou fetch or push
their mainthe branch on the serveranyone pushes

fetch, then merge — which is what pull is

fetch can never break anything: it only adds objects and moves the remote-tracking refs. When you are unsure what is happening on a branch, fetch first and look.

the safe one, and the convenient one
git fetch origin            # download commits, move origin/*. Your work is untouched.
git log --oneline --all     # look at what arrived
git merge origin/main       # now bring it into your branch

git pull                    # = fetch + merge, in one step
git pull --rebase           # = fetch + rebase

push, and the rejection everybody meets

Git refuses because pushing would drop their commits. The fix is never --force: fetch, integrate their work (merge or rebase), then push again. --force on a shared branch deletes someone else's work from the server.

somebody pushed while you were working
$ git push origin main
! [rejected]        main -> main (fetch first)
hint: Updates were rejected because the remote contains work that you do not have locally.
If you must force, use --force-with-lease

It refuses when the remote has moved since your last fetch — so it overwrites only the history you actually looked at. Plain --force overwrites whatever is there.

Tracking, and the first push of a branch

The "ahead by 2, behind by 1" line in git status is computed against the tracking branch — which is, again, only as fresh as your last fetch.

-u links the two names, once
git push -u origin feature     # push, and remember that feature ↔ origin/feature
git push                       # from then on, this is enough
git status                     # "Your branch is ahead of 'origin/main' by 2 commits"

git branch -vv                 # what each branch tracks
git fetch -p                   # -p prunes remote branches that were deleted

Practice