Skip to main content

What are Remote Repositories?

Remote repositories are versions of your project hosted elsewhere - on the internet, network, or even another directory on your local machine. They enable collaboration by allowing multiple developers to share commits, synchronize work, and maintain a common history. From Git’s documentation:
Manage the set of repositories (“remotes”) whose branches you track.
In Git’s distributed model, every clone is a full repository. “Remote” simply means “not this repository” - it could be on GitHub, your coworker’s laptop, or a server you manage.

Remote Basics

The Origin Remote

When you clone a repository, Git automatically creates a remote called origin:
$ git clone https://github.com/user/repo.git
Cloning into 'repo'...
From the glossary:
The default upstream repository. Most projects have at least one upstream project which they track. By default ‘origin’ is used for that purpose.

Viewing Remotes

# List remotes
$ git remote
origin

# List with URLs
$ git remote -v
origin  https://github.com/user/repo.git (fetch)
origin  https://github.com/user/repo.git (push)
Each remote has two URLs:
  • fetch: Where Git pulls changes from
  • push: Where Git pushes changes to
Fetch and push URLs can differ. For example, you might fetch from a public HTTPS URL but push via SSH.

Managing Remotes

Adding Remotes

From git-remote.adoc:
$ git remote add <name> <url>
Example:
# Add a remote repository
$ git remote add upstream https://github.com/original/repo.git

# Verify
$ git remote -v
origin    https://github.com/you/repo.git (fetch)
origin    https://github.com/you/repo.git (push)
upstream  https://github.com/original/repo.git (fetch)
upstream  https://github.com/original/repo.git (push)
Common naming conventions:
  • origin - Your primary remote (default when cloning)
  • upstream - The original repository you forked from
  • production - Deployment target
  • coworker-name - Collaborator’s repository

Renaming Remotes

$ git remote rename old-name new-name
Example:
$ git remote rename origin backup
$ git remote rename upstream origin
This updates:
  • Remote configuration
  • Remote-tracking branches (refs/remotes/)
  • Branch upstream tracking

Removing Remotes

$ git remote remove <name>
# Or:
$ git remote rm <name>
This removes:
  • The remote configuration
  • All remote-tracking branches
  • Branch tracking settings

Inspecting Remotes

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/user/repo.git
  Push  URL: https://github.com/user/repo.git
  HEAD branch: main
  Remote branches:
    main   tracked
    dev    tracked
  Local branch configured for 'git pull':
    main merges with remote main
  Local ref configured for 'git push':
    main pushes to main (up to date)

Remote-Tracking Branches

From Git’s data model:
A remote-tracking branch refers to a commit ID. It’s how Git stores the last-known state of a branch in a remote repository.
Remote-tracking branches are stored in refs/remotes/<remote>/<branch>:
refs/remotes/origin/main
refs/remotes/origin/feature-x
refs/remotes/upstream/main

Characteristics

1

Read-only

You can’t commit directly to remote-tracking branches. They’re updated only by fetch/pull operations.
2

Automatic updates

git fetch updates remote-tracking branches to match the remote repository.
3

Local mirrors

They provide a local snapshot of the remote repository’s state at the last fetch.

Viewing Remote Branches

# List remote-tracking branches
$ git branch -r
  origin/HEAD -> origin/main
  origin/main
  origin/feature-x
  origin/bugfix-123

# List all branches (local + remote)
$ git branch -a
  main
  feature-x
* dev
  remotes/origin/HEAD -> origin/main
  remotes/origin/main
  remotes/origin/feature-x

Fetching and Pulling

Fetching

git fetch downloads commits, files, and refs from a remote repository:
# Fetch from origin
$ git fetch origin
remote: Counting objects: 10, done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 10 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (10/10), done.
From https://github.com/user/repo
   abc123..def456  main       -> origin/main
 * [new branch]    feature-x  -> origin/feature-x
This updates remote-tracking branches but doesn’t modify your working directory or current branch.

Fetch all remotes

$ git fetch --all

Fetch specific branch

$ git fetch origin feature-x

Fetch and prune deleted branches

$ git fetch --prune
# Or:
$ git fetch -p
Removes remote-tracking branches that no longer exist on the remote.

Fetch tags

$ git fetch --tags

Pulling

git pull = git fetch + git merge:
$ git pull origin main
This:
  1. Fetches changes from origin/main
  2. Merges them into your current branch
1

Pull with automatic merge

$ git pull
Updating abc123..def456
Fast-forward
 README.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
2

Pull with rebase

$ git pull --rebase
Replays your local commits on top of fetched commits instead of merging.
3

Pull specific remote and branch

$ git pull upstream main
git pull modifies your working directory. If you have uncommitted changes, you may need to commit or stash them first.

Pushing

From git-push.adoc, pushing uploads your local commits to a remote repository:
$ git push <remote> <branch>

Basic Push

# Push current branch to origin
$ git push origin main
Counting objects: 5, done.
Writing objects: 100% (5/5), 450 bytes, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/user/repo.git
   abc123..def456  main -> main

Push Variations

Push with upstream tracking

$ git push -u origin feature-x
Sets up tracking so future git push and git pull work without arguments.

Push all branches

$ git push --all origin

Push tags

$ git push --tags

Force push (use with extreme caution)

$ git push --force origin main
Force pushing rewrites history on the remote. This can cause problems for collaborators who have already pulled the old commits.

Safer force push

$ git push --force-with-lease origin main
Only pushes if the remote hasn’t changed since your last fetch.

Delete remote branch

$ git push origin --delete feature-x
# Or:
$ git push origin :feature-x

Branch Tracking

From branch.h, local branches can be configured to track remote branches:
/**
 * Configure local branch "local" as downstream to branch "remote"
 * from remote "origin". Used by git branch --set-upstream.
 */
int install_branch_config(int flag, const char *local, 
                         const char *origin, const char *remote);

Setting Up Tracking

1

Automatic (during checkout)

$ git checkout feature-x
Branch 'feature-x' set up to track remote branch 'feature-x' from 'origin'.
2

Explicit setup

$ git branch --set-upstream-to=origin/feature-x
# Or shorter:
$ git branch -u origin/feature-x
3

During push

$ git push -u origin feature-x

Benefits of Tracking

When a branch tracks a remote branch:
  • git status shows ahead/behind information
  • git pull knows where to pull from
  • git push knows where to push to
$ git status
On branch feature-x
Your branch is ahead of 'origin/feature-x' by 2 commits.
  (use "git push" to publish your local commits)

Viewing Tracking Information

$ git branch -vv
  main      abc123 [origin/main] Latest commit message
* feature-x def456 [origin/feature-x: ahead 2] Add feature
  bugfix    789abc Fix critical bug

Collaboration Workflows

Fork and Pull Request

Common on GitHub/GitLab:
1

Fork the repository

Create your own copy on GitHub.
2

Clone your fork

$ git clone https://github.com/you/repo.git
$ cd repo
3

Add upstream remote

$ git remote add upstream https://github.com/original/repo.git
4

Create feature branch

$ git checkout -b feature-x
5

Make changes and commit

$ git add .
$ git commit -m "Add feature"
6

Push to your fork

$ git push origin feature-x
7

Create pull request

On GitHub, create a pull request from your fork to the upstream repository.
8

Keep your fork updated

$ git fetch upstream
$ git checkout main
$ git merge upstream/main
$ git push origin main

Centralized Workflow

Team shares a single remote repository:
# Update your local copy
$ git pull origin main

# Make changes
$ git checkout -b feature-x
# ... work ...
$ git commit -m "Add feature"

# Push to shared repository
$ git push origin feature-x

# Team member reviews and merges

Remote Configuration

Remotes are stored in .git/config:
[remote "origin"]
    url = https://github.com/user/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*

[remote "upstream"]
    url = https://github.com/original/repo.git
    fetch = +refs/heads/*:refs/remotes/upstream/*

[branch "main"]
    remote = origin
    merge = refs/heads/main

Refspecs

The fetch line is a refspec defining how refs map:
+refs/heads/*:refs/remotes/origin/*
Breakdown:
  • + - Force update (even if not fast-forward)
  • refs/heads/* - All branches on remote
  • : - Maps to
  • refs/remotes/origin/* - Local remote-tracking branches

Remote Protocols

Git supports multiple protocols:

HTTPS

https://github.com/user/repo.git
Pros: Works everywhere, through firewalls Cons: Requires authentication for every push (unless cached)

SSH

git@github.com:user/repo.git
Pros: Secure, no password prompts (with SSH keys) Cons: Requires SSH setup

Git Protocol

git://github.com/user/repo.git
Pros: Fast Cons: No authentication, read-only for public repositories

Local Path

/path/to/repo.git
# Or:
file:///path/to/repo.git
Pros: Simple for local/network drives Cons: No built-in authentication or access control

Best Practices

1

Fetch before you work

$ git fetch origin
Stay updated with remote changes before starting new work.
2

Pull regularly

$ git pull --rebase origin main
Keep your branch up-to-date to avoid large merge conflicts.
3

Push often

$ git push origin feature-x
Share your work early and often for backup and visibility.
4

Use descriptive remote names

Good: origin, upstream, production Bad: remote1, temp, test
5

Clean up tracking branches

$ git fetch --prune
Remove tracking branches for deleted remote branches.
6

Avoid force pushing to shared branches

Never force push to main or other shared branches unless absolutely necessary and coordinated with your team.

Troubleshooting

Remote Rejected Push

$ git push origin main
To https://github.com/user/repo.git
 ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs
Solution: Pull first, then push:
$ git pull --rebase origin main
$ git push origin main

Diverged Branches

$ git status
Your branch and 'origin/main' have diverged,
and have 2 and 3 different commits each, respectively.
Solution: Merge or rebase:
# Option 1: Merge
$ git pull origin main

# Option 2: Rebase
$ git pull --rebase origin main

Authentication Issues

remote: Invalid username or password.
fatal: Authentication failed
Solution: Check credentials, use SSH keys, or configure credential helper:
$ git config --global credential.helper cache

Further Reading

  • git help remote - Managing remotes
  • git help fetch - Fetching changes
  • git help pull - Fetching and merging
  • git help push - Uploading changes