Git Remote
Connect a local repository to a remote, update remote-tracking branches, and push without guessing which branch moves.
A remote names another repository
A remote is Git configuration: a short name plus a location. The conventional name origin is not a special cloud, not GitHub, and not “the real repository.” It is the default name git clone assigns to the repository you cloned from. You can add more remotes, rename them, or point origin at a folder on disk.
Git vs GitHub already separated the engine from the host. This lesson is the engine’s exchange layer. A later GitHub Repository lesson will create a hosted empty repo; this lesson teaches the commands that talk to whatever location you configured.
Your clone
Working tree, index, commits, and branch names such as main. Commits you make here stay here until you push.
Another repository
A path or URL Git can reach. After fetch, your clone stores a picture of that repository as refs like origin/main.
Inspect and add origin
git remote -v
git remote add origin /tmp/sovrancode-origin.git
git remote -v
git remote show origingit remote -v prints fetch and push URLs. git remote show origin reports which remote branches exist, which local branches track them, and whether your information is stale until Git contacts the remote. If you cloned, origin is usually already present; git remote add origin is for a repository you created with git init.
Test what you learned
Type the command that adds a remote named origin pointing at /tmp/sovrancode-origin.git.
Remote-tracking branches are local refs
origin/main is not “main on GitHub.” It is a ref in your repository, updated when you fetch, that remembers where main was on the remote named origin at fetch time. Your local main is a separate pointer. They can name the same commit or diverge.
git branch -vv
git rev-parse main origin/main
git log --oneline --decorate --graph --all
git status -sbgit branch -vv shows upstream, if any: main [origin/main] means later git push and git pull have a default destination. Until upstream is set, Git will refuse to guess. That refusal is useful. Name the remote and the branch until tracking exists.
Remote-tracking names are still Git refs, in the same graph you studied in Git Branch. They are not a second database and not a GitHub feature.
Fetch updates pictures of the remote
git status
git fetch origin
git log --oneline --decorate --graph --all
git branch -vvgit fetch origin downloads missing objects and updates remote-tracking branches. It does not merge, rebase, or change files in the working tree. After fetch you can read git log main..origin/main and decide whether to integrate.
git fetch --prune origin also deletes stale remote-tracking branches when the remote no longer has them. Fetching is the safe default when you want information without changing the branch you are on.
Test what you learned
Type the command that downloads objects from origin without merging them into your current branch.
Pull fetches, then integrates
# Inspect first, then integrate a named remote-tracking branch
git fetch origin
git log --oneline --decorate --graph --all
git merge origin/main
# Equivalent default pull when upstream is already set
git pull origin mainDefault git pull is fetch plus merge into the current branch. Some people configure pull to rebase instead. Either way, pull changes local history and possibly the working tree. When the incoming commits are unfamiliar, fetch first, look at the graph, then merge or rebase on purpose.
git pull origin main names the remote and the remote branch. After upstream exists, git pull can omit those arguments. Do not treat pull as “refresh GitHub.” It integrates Git history from a remote into the branch you currently have checked out.
Push sends a named branch
git status
git log --oneline --decorate -n 3
git push -u origin main
git branch -vv
git ls-remote origingit push -u origin main updates main on origin and records that local main tracks origin/main. git ls-remote origin lists refs the remote currently advertises, which is useful when your local remote-tracking picture might be stale.
Be explicit until tracking exists. git push origin HEAD pushes the current branch under its current name. Guessing “Git will know” is how people update the wrong branch. Push talks to a Git remote. Authentication failures belong to transport; they are not a broken commit graph. The next lesson covers HTTPS and SSH.
Test what you learned
Type the command that pushes local main to origin and sets upstream tracking.
Handle a rejected non-fast-forward
If the remote branch has commits you do not have, Git rejects a plain push. That protection is correct. Fetch, inspect git log --oneline --decorate --graph --all, then integrate origin/main into your local branch with merge or rebase, and push the result.
git fetch origin
git log --oneline --decorate --graph --all
git merge origin/main
git push origin mainPractice with two clones, not GitHub yet
You can learn remotes without an account. A bare repository is a Git database without a working tree—the usual shape of a shared remote. Two ordinary clones talk to it the way two laptops talk to a host.
# Shared remote as a bare Git repository (no GitHub account required)
git init --bare /tmp/sovrancode-origin.git
git clone /tmp/sovrancode-origin.git /tmp/sovrancode-laptop
git clone /tmp/sovrancode-origin.git /tmp/sovrancode-teammateThe first clone that has commits runs git push -u origin main. The second clone runs git fetch origin and sees origin/main move. That is the whole model. GitHub, when you add it later, is one possible location behind the same names.
- 01Create a bare origin
Initialize a disposable bare repository. It has no files to edit; it only stores Git objects and refs.
- 02Clone twice
Treat one clone as your laptop and one as a teammate. Each has its own working tree and its own
origin. - 03Push from the first clone
Commit a README, then
git push -u origin main. Confirm withgit ls-remote origin. - 04Fetch from the second clone
Do not pull yet. Fetch, read the graph, then merge
origin/mainwhen you intend to integrate.
Guided practice: exchange one commit
- 01Build the three directories
Bare origin, laptop clone, teammate clone. Print
git remote -vin both clones. - 02Record and push
On the laptop, create
README.md, commit, andgit push -u origin main. - 03Fetch without merging
On the teammate clone, run
git fetch origin. Confirm the working tree is unchanged andorigin/mainmoved. - 04Integrate on purpose
Merge or pull only after you can explain the incoming commit. Then add a second file from the teammate and push.
- 05Prove both copies
Fetch on the laptop.
git rev-parse mainandgit rev-parse origin/mainshould match after you integrate.
Independent lab: two clones stay honest
- Create a disposable bare remote and two clones. Do not use a GitHub account for this lab.
- From clone A, commit a file and run
git push -u origin main. Recordgit ls-remote origin. - From clone B, run
git fetch originbefore changing any files. Show thatorigin/mainmoved and the working tree did not. - Integrate on clone B, add a second commit, and push. Fetch on clone A and integrate until both
mainpointers match. - On clone A, commit without fetching, then attempt
git push origin mainafter clone B has already pushed. Read the rejection, fetch, integrate, and push without force.
Common remote mistakes
Calling origin “GitHub”
origin is a remote name. The URL might later be GitHub, GitLab, or a folder.
Treating fetch as pull
Fetch updates remote-tracking refs. Pull also integrates into the current branch.
Pushing without naming the branch
Until upstream exists, Git should not guess. Use git push -u origin main.
Force-pushing a rejected update
A non-fast-forward usually means you are missing remote commits. Fetch first.
Lesson review
You can add a remote, fetch a picture of it, push a named branch, and integrate incoming history without confusing GitHub for Git. Authentication and creating a hosted repository come next.
- I can inspect remotes with
git remote -vandgit remote show origin. - I can explain
mainversusorigin/mainand update the latter withgit fetch origin. - I can
git push -u origin mainand verify withgit ls-remote originandgit branch -vv. - I treat a rejected push as missing remote history, not as a reason to force-push.