Git’s remote command is a surprisingly flexible tool that often gets reduced to just git remote add origin <url>, but it’s actually the backbone for how your local repository interacts with any other repository, not just the one you cloned from.

Let’s see it in action. Imagine you’ve cloned a project from GitHub, and you want to contribute back.

# First, check what remotes you have. Usually, 'origin' is already there.
git remote -v

This will likely show:

origin  https://github.com/your-username/project.git (fetch)
origin  https://github.com/your-username/project.git (push)

Now, let’s say you want to push your changes to your own fork of the project, which is at a different URL.

# Add your fork as a new remote, let's call it 'myfork'
git remote add myfork https://github.com/your-username/project-fork.git

# Verify it's added
git remote -v

Output:

origin  https://github.com/original-author/project.git (fetch)
origin  https://github.com/original-author/project.git (push)
myfork  https://github.com/your-username/project-fork.git (fetch)
myfork  https://github.com/your-username/project-fork.git (push)

Now you can push to your fork:

# Push your current branch (e.g., 'main') to your fork
git push myfork main

The mental model here is that remotes are simply named pointers to other Git repositories. When you clone, Git automatically sets up a remote named origin pointing back to the repository you cloned from. You can have as many remotes as you need, and you can name them anything you like.

The fetch and push URLs are crucial. fetch tells Git where to download commits from, and push tells it where to upload commits to. They don’t have to be the same. For example, you might fetch from a public mirror but push to a private server.

A common pattern is to collaborate on a project:

  1. You clone the original project (origin).
  2. You create a fork on GitHub (or another platform).
  3. You add your fork as a remote (myfork).
  4. You make changes locally on a feature branch (feature/new-thing).
  5. You push your branch to your fork: git push myfork feature/new-thing.
  6. You open a pull request from your fork’s branch to the original project’s branch.

This brings us to tracking branches. When you git clone, Git usually sets up your local main (or master) branch to "track" the origin/main branch. This means Git knows which remote branch your local branch corresponds to.

# Check which branch your local 'main' is tracking
git branch -vv

Output might look like:

  feature/new-thing
* main         a1b2c3d [origin/main] Add awesome feature

The [origin/main] part indicates that your local main is tracking the main branch on the origin remote. This enables convenient commands like git pull (which is equivalent to git fetch origin followed by git merge origin/main) and git push (which, when run without arguments on a tracking branch, pushes to its upstream).

To explicitly set up tracking for a branch you pushed manually:

# Assume you just pushed 'feature/new-thing' to 'myfork'
git push -u myfork feature/new-thing

The -u (or --set-upstream) flag tells Git to set up feature/new-thing on your local machine to track myfork/feature/new-thing. From now on, git push and git pull on this branch will default to using myfork and feature/new-thing.

The most surprising thing about tracking branches is how much Git infers from them. When you run git status, if your local branch is ahead of its upstream, it will tell you "Your branch is ahead of 'origin/main' by X commits." This information is solely derived from the upstream tracking configuration. You can even change which branch a local branch tracks after the fact: git branch --set-upstream-to=origin/develop main.

The next concept you’ll want to explore is how Git handles branch renaming across remotes and the implications for pull requests.

Want structured learning?

Take the full Git course →