What Is a Git Remote?
A remote is simply a named URL pointing to another copy of the repository. That copy might be on GitHub, GitLab, Bitbucket, a company server, or even another folder on your own machine.
Git stores remotes as name-URL pairs in .git/config:
# Inside .git/config
[remote "origin"]
url = https://github.com/username/my-repo.git
fetch = +refs/heads/*:refs/remotes/origin/*
[remote "upstream"]
url = https://github.com/original-author/my-repo.git
fetch = +refs/heads/*:refs/remotes/upstream/*
Remotes let you push (upload) your commits to the remote, and fetch/pull (download) commits others have pushed. The remote repo doesn't need to be online for you to work locally — Git only contacts it when you explicitly push, fetch, or pull.
What Is "origin"?
origin is just a conventional name — nothing more. When you run git clone <url>, Git automatically creates a remote called origin pointing to the URL you cloned from. You could rename it to anything, but origin is the universal convention that every tool and tutorial expects.
# git clone automatically creates the "origin" remote
git clone https://github.com/username/my-repo.git
cd my-repo
git remote -v
# origin https://github.com/username/my-repo.git (fetch)
# origin https://github.com/username/my-repo.git (push)
When you fork a repo and clone your fork, "origin" refers to YOUR fork (because that's what you cloned). The original repository you forked from is conventionally named "upstream". This two-remote setup is standard for open-source contribution workflows.
Adding Remotes
If you initialised a repo with git init (rather than cloning), there's no remote yet. You add one manually:
# Add the primary remote (your repo on GitHub)
git remote add origin https://github.com/username/my-repo.git
# Add upstream (the original repo you forked from)
git remote add upstream https://github.com/original-author/my-repo.git
# Verify remotes were added
git remote -v
# origin https://github.com/username/my-repo.git (fetch)
# origin https://github.com/username/my-repo.git (push)
# upstream https://github.com/original-author/my-repo.git (fetch)
# upstream https://github.com/original-author/my-repo.git (push)
Listing Remotes
# List remote names only
git remote
# origin
# upstream
# List remotes with their URLs (fetch and push URLs)
git remote -v
# origin git@github.com:username/my-repo.git (fetch)
# origin git@github.com:username/my-repo.git (push)
# upstream git@github.com:original/my-repo.git (fetch)
# upstream git@github.com:original/my-repo.git (push)
# Detailed info about a specific remote
git remote show origin
# * remote origin
# Fetch URL: git@github.com:username/my-repo.git
# Push URL: git@github.com:username/my-repo.git
# HEAD branch: main
# Remote branches:
# main tracked
# feature/login tracked
# Local branch configured for 'git pull':
# main merges with remote main
Renaming and Removing Remotes
# Rename a remote
git remote rename origin backup
git remote rename backup origin # rename back
# Remove a remote (just removes the local reference — doesn't delete anything on GitHub)
git remote remove upstream
# Change a remote's URL (e.g., switching from HTTPS to SSH)
git remote set-url origin git@github.com:username/my-repo.git
Tracking Branches
When you fetch from a remote, Git creates remote-tracking branches — local read-only copies that record what each remote branch looked like the last time you fetched. They're named <remote>/<branch>: for example, origin/main or origin/feature/login.
# After git fetch, list all branches including remote-tracking
git branch -a
# * main
# remotes/origin/main
# remotes/origin/feature/login
# See how far ahead/behind your local branch is from the remote
git status
# On branch main
# Your branch is behind 'origin/main' by 2 commits, and can be fast-forwarded.
# Compare local main to origin/main
git log main..origin/main --oneline
# Shows commits on origin/main that you don't have locally
origin/main only updates when you explicitly run git fetch or git pull. If a teammate pushed new commits to GitHub 5 minutes ago, your local origin/main doesn't know about them until you fetch. This is intentional — Git never contacts the network without your permission.
| Remote name | Convention | Set by |
|---|---|---|
origin |
Your primary remote (the repo you cloned or your fork) | Auto-set by git clone |
upstream |
The original repo you forked from | Added manually: git remote add upstream <url> |
📋 Summary
- A remote is a named URL pointing to another copy of the repository — stored in
.git/config. originis the conventional name for the default remote, automatically set bygit clone.upstreamis the convention for the original repo when you've forked.git remote -v— list all remotes with URLs.git remote add <name> <url>— add a new remote.git remote renameandgit remote remove— manage existing remotes.- Tracking branches (e.g.,
origin/main) are local snapshots of the remote branch's state at last fetch.
FAQ
Yes — and it's common. The typical open-source setup has two: origin (your fork) and upstream (the original repo). Some teams push to multiple hosting services simultaneously (GitHub + an internal GitLab server). Each remote is independent — you can fetch from upstream and push to origin without any conflict.
A remote branch is a branch that lives on the remote server (e.g., main on GitHub). A remote-tracking branch is a local reference (e.g., origin/main) that mirrors what that remote branch looked like the last time you fetched. You can't commit directly to a remote-tracking branch — it's read-only and only updated by fetch/pull operations.
No. git remote remove only removes the local reference (the name-URL entry in .git/config). The remote repository on GitHub is completely unaffected. You can re-add the remote at any time with git remote add. To actually delete a GitHub repository, you'd do that through the GitHub web interface.
Git allows different URLs for fetch and push on the same remote — a rarely-used but valid configuration. For example, you might fetch over HTTPS (no credentials needed for public repos) but push over SSH. In most cases they're the same URL, so Git shows both to make the configuration transparent. You can set them separately with git remote set-url --push origin <url>.