Remote Repositories — clone, fetch, pull, push
What Is a Remote?
In lesson 1 we established that Git is distributed: every developer has a full copy of the repository. But in practice, teams need a shared rendezvous point — a copy that everyone agrees is authoritative. This shared copy is a remote repository.
A remote is just a Git repository hosted somewhere else — on a server (GitHub, GitLab, Bitbucket, a company's own server) or even another path on your local machine. From your local repository's perspective, a remote is an alias (a name) pointing to a URL.
The convention is to name the primary remote origin. This is just a convention — you could name it anything — but every tutorial, documentation page, and colleague will assume your main remote is called origin. Stick with it.
git remote — Managing Remote Connections
Viewing Remotes
In a freshly cloned repository:
Each remote shows two URLs: one for fetch (downloading) and one for push (uploading). They are usually the same URL, but you can configure them differently.
Adding a Remote
If you initialized a local repo with git init and want to connect it to a remote:
The syntax is: git remote add <name> <url>
Renaming and Removing Remotes
git remote show origin gives you a lot of useful information:
Changing a Remote URL
Useful when you migrate from HTTPS to SSH, or when a repository is renamed or moved:
git clone — Copying an Existing Repository
git clone downloads a complete copy of a repository — all commits, all branches, all history — and sets up the remote for you automatically.
After cloning, Git automatically:
- Creates the remote
originpointing to the URL you cloned from - Checks out the default branch (usually
mainormaster) - Creates remote-tracking branches for all remote branches (
origin/main, etc.)
Remote-Tracking Branches: Understanding origin/main
This is one of the most important concepts in Git collaboration, and also one of the most commonly misunderstood.
When you clone a repository or run git fetch, Git creates remote-tracking branches — local references that represent the state of branches on the remote at the time of the last fetch.
origin/main is NOT your local main. It is a read-only snapshot of what main looked like on origin the last time you fetched. It lives in .git/refs/remotes/origin/main.
You cannot commit directly to origin/main. You commit to your local main, and then push that to the remote.
Think of remote-tracking branches as bookmarks: they record the position of remote branches at last contact. Running git fetch updates these bookmarks to the current state of the remote.
git fetch — Downloading Changes Without Merging
git fetch downloads all new commits, branches, and tags from the remote and updates your remote-tracking branches. It does not modify your working directory or local branches.
After git fetch:
origin/mainis updated to the latest state of the remote'smain- Your local
mainis unchanged - New remote branches appear as
origin/feature-name
To see what changed on the remote since your last fetch:
git pull — Fetch and Merge in One Step
git pull is shorthand for git fetch followed by git merge (or git rebase, depending on configuration).
What git pull does internally:
git pull Strategies
When you run git pull, Git needs to integrate the remote commits with your local commits. There are three strategies:
Merge (default): Creates a merge commit. Preserves the fact that a pull happened. History shows the divergence and reconciliation.
Rebase: Replays your local commits on top of the fetched commits. Results in a linear history. Preferred by many teams for cleaner logs.
Fast-forward only: Fails if a merge commit would be needed. Forces you to explicitly rebase if there is divergence.
Set your preferred default:
The rebase approach is popular in teams that value a clean linear history. The merge approach preserves more historical information about when pulls happened. Both are valid.
The Golden Rule of Pulling
Before starting work each day, pull the latest changes:
And before merging a feature branch:
This ensures you are integrating with the latest state of the base branch.
git push — Uploading Your Commits
git push uploads your local commits to the remote.
Setting the Upstream
The first time you push a new local branch, you need to tell Git where to push it:
After setting the upstream once, subsequent pushes from that branch just need git push.
What Is an Upstream?
A tracking relationship (upstream) connects a local branch to a remote-tracking branch. Once set:
git pushknows where to push without being toldgit pullknows where to pull from without being toldgit statusshows how many commits ahead/behind your local branch is relative to the remote
This shows:
mainis 2 commits ahead oforigin/main(you have 2 local commits not yet pushed)feature/due-datesis up to date with its remote counterpart
Pushing Tags
Tags (covered in lesson 8) are not pushed automatically with git push. You must push them explicitly:
Deleting Remote Branches
When a feature branch has been merged and you want to clean up the remote:
After deleting the remote branch, other developers can clean up their stale remote-tracking branches with:
Force Push — Use With Extreme Caution
Sometimes you need to push commits that conflict with the remote's history (e.g., after a rebase). This requires a force push:
Never force-push to main, master, or any branch shared by your team, unless everyone has been warned and coordinated. Force-pushing rewrites the remote's history and requires everyone else to reset their local branches. Use --force-with-lease instead of --force — it fails if someone else has pushed since your last fetch.
Force pushing is legitimate on your own private feature branches, particularly after rebasing.
Authentication: SSH Keys vs HTTPS
To push to a remote, you need to authenticate. There are two main methods: HTTPS (with a personal access token) and SSH keys.
HTTPS Authentication
GitHub no longer accepts password authentication for HTTPS. You need a personal access token (PAT):
- Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate a new token with
reposcope - Copy the token — you will not see it again
When Git prompts for a password, enter your token instead.
To avoid entering credentials every time:
SSH Key Authentication
SSH is generally more convenient for developers: you set it up once and never type passwords again.
Step 1: Generate an SSH key pair
Accept the default location (~/.ssh/id_ed25519). Set a passphrase when prompted (optional but recommended).
Step 2: Add the public key to GitHub
Go to GitHub → Settings → SSH and GPG keys → New SSH key. Paste the public key.
Step 3: Add the key to your SSH agent
On macOS, add this to ~/.ssh/config to auto-load the key:
Step 4: Test the connection
Step 5: Update your remote URLs to use SSH
The Forking Model — Contributing to Open Source
Many open-source projects on GitHub use a forking workflow. You cannot push directly to someone else's repository, so the process is:
- Fork the repository on GitHub (creates your own copy under your account)
- Clone your fork locally
- Add the original as a remote (convention: call it
upstream) - Create a feature branch, make changes, commit
- Push the branch to your fork
- Open a Pull Request from your fork's branch to the original repo
Practical Exercises
Exercise 1: Push Your taskr Repository to GitHub
Exercise 2: Simulate a Collaborative Workflow
Exercise 3: Practice fetch vs pull
Challenge: Set Up SSH Authentication
If you have been using HTTPS:
- Generate an SSH key pair with ed25519
- Add the public key to GitHub
- Update your remote URL to use SSH
- Verify with
ssh -T git@github.com - Push a commit to confirm SSH auth works
Summary
- A remote is a named reference to a URL of another Git repository. The conventional primary remote name is
origin. git clonecreates a local copy of a repository and automatically sets up theoriginremote and remote-tracking branches.- Remote-tracking branches (like
origin/main) are read-only local bookmarks of the remote's branch state at the time of the last fetch. git fetchdownloads changes from the remote and updates remote-tracking branches without touching your local branches or working directory.git pull=git fetch+git merge(or rebase). Use--rebasefor a cleaner linear history.git pushuploads your local commits to the remote. Use-uon the first push to set the tracking relationship.- Never force-push to shared branches. Use
--force-with-leaseinstead of--forcewhen a force push is genuinely necessary. - SSH key authentication is the most convenient and secure method for daily use with GitHub/GitLab.
The next lesson tackles merge conflicts — what they are, why they happen, how to read the conflict markers, and how to resolve them confidently.