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 < nam e > < ur l >
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 < nam e >
# Or:
$ git remote rm < nam e >
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
Read-only
You can’t commit directly to remote-tracking branches. They’re updated only by fetch/pull operations.
Automatic updates
git fetch updates remote-tracking branches to match the remote repository.
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 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.
Pulling
git pull = git fetch + git merge:
This:
Fetches changes from origin/main
Merges them into your current branch
Pull with automatic merge
$ git pull
Updating abc123..def456
Fast-forward
README.md | 5 +++--
1 file changed, 3 insertions ( + ) , 2 deletions ( - )
Pull with rebase
Replays your local commits on top of fetched commits instead of merging.
Pull specific remote and branch
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 < remot e > < branc h >
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 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
Automatic (during checkout)
$ git checkout feature-x
Branch 'feature-x' set up to track remote branch 'feature-x' from 'origin'.
Explicit setup
$ git branch --set-upstream-to=origin/feature-x
# Or shorter:
$ git branch -u origin/feature-x
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 )
$ 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:
Fork the repository
Create your own copy on GitHub.
Clone your fork
$ git clone https://github.com/you/repo.git
$ cd repo
Add upstream remote
$ git remote add upstream https://github.com/original/repo.git
Create feature branch
$ git checkout -b feature-x
Make changes and commit
$ git add .
$ git commit -m "Add feature"
Push to your fork
$ git push origin feature-x
Create pull request
On GitHub, create a pull request from your fork to the upstream repository.
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
Fetch before you work
Stay updated with remote changes before starting new work.
Pull regularly
$ git pull --rebase origin main
Keep your branch up-to-date to avoid large merge conflicts.
Push often
$ git push origin feature-x
Share your work early and often for backup and visibility.
Use descriptive remote names
Good: origin, upstream, production
Bad: remote1, temp, test
Clean up tracking branches
Remove tracking branches for deleted remote branches.
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