Skip to main content

Remotes, Push, Pull & Fetch

Quick Summary

A remote is a bookmark to a copy of your repository hosted elsewhere (usually GitHub). Push uploads your commits. Pull downloads and integrates remote commits. Fetch downloads without integrating. These commands are how you collaborate and keep repositories synchronized.


Understanding Remotes

flowchart LR
L["Local Repository<br/>(your machine)"]
R["Remote: origin<br/>(GitHub)"]
L -->|git push| R
R -->|git fetch| L
R -->|"git pull<br/>fetch + merge"| L

Adding and Managing Remotes

# View existing remotes
git remote -v

# Add a remote
git remote add origin git@github.com:donnyaw/my-project.git

# Add a second remote (e.g., upstream fork)
git remote add upstream git@github.com:original-author/project.git

# Rename a remote
git remote rename origin github

# Remove a remote
git remote remove upstream

# Change a remote's URL
git remote set-url origin git@github.com:donnyaw/new-project.git

Expected output:

$ git remote -v
origin git@github.com:donnyaw/my-project.git (fetch)
origin git@github.com:donnyaw/my-project.git (push)
upstream git@github.com:original/project.git (fetch)
upstream git@github.com:original/project.git (push)

git push — Upload Commits

# Push current branch to origin
git push

# Push specific branch
git push origin main

# Push and set upstream tracking (-u, first time only)
git push -u origin main

# Push all branches
git push --all origin

# Push tags
git push --tags

# Force push (dangerous — overwrites remote)
git push --force

# Safe force push (won't overwrite others' work)
git push --force-with-lease

First Push for a New Branch

# Create branch, make changes, push for the first time
git switch -c feature/api
# ... make changes and commit ...
git push -u origin feature/api

The -u flag sets up tracking so future git push and git pull know which remote branch to target.

Force push

git push --force overwrites the remote history. Only use it on branches where you're the sole contributor. Prefer --force-with-lease which checks that no one else has pushed since your last fetch.


git fetch — Download Without Merging

Downloads new commits, branches, and tags from the remote — but doesn't modify your working files.

# Fetch from origin
git fetch origin

# Fetch from all remotes
git fetch --all

# Fetch and prune deleted remote branches
git fetch --prune

Why Fetch?

sequenceDiagram
participant L as Local
participant R as Remote (origin)

R->>L: git fetch (downloads new commits)
Note over L: origin/main updated<br/>Your main unchanged
L->>L: git log origin/main (inspect)
L->>L: git merge origin/main (integrate when ready)

Fetch is safe — it never modifies your working directory or current branch. It only updates your remote-tracking branches (origin/main, origin/feature/x).


git pull — Fetch + Merge

# Pull (fetch + merge in one step)
git pull origin main

# Pull with rebase (cleaner history)
git pull --rebase origin main

# Pull current tracking branch
git pull

Pull = Fetch + Merge

# These are equivalent:
git pull origin main

# Same as:
git fetch origin
git merge origin/main

Pull with Rebase

# These are equivalent:
git pull --rebase origin main

# Same as:
git fetch origin
git rebase origin/main
Set rebase as default pull strategy
git config --global pull.rebase true

This avoids unnecessary merge commits when pulling.


Remote-Tracking Branches

When you fetch, Git creates remote-tracking branches like origin/main:

# List all remote-tracking branches
git branch -r

# See how your branch compares to remote
git log main..origin/main # Commits on remote not in local
git log origin/main..main # Commits in local not on remote
$ git branch -r
origin/HEAD -> origin/main
origin/main
origin/feature/auth
origin/fix/login-bug

Common Workflows

Solo Developer

# Daily workflow
git add .
git commit -m "feat: add new feature"
git push

Team Collaboration

# Start of day: get latest changes
git pull --rebase origin main

# Work on feature
git switch -c feature/dashboard
# ... make changes ...
git commit -m "feat: add dashboard layout"

# Before merging: update with latest main
git fetch origin
git rebase origin/main

# Push feature branch
git push -u origin feature/dashboard

# Create pull request on GitHub...

Contributing to Open Source (Fork Workflow)

# 1. Fork on GitHub, then clone your fork
git clone git@github.com:donnyaw/project.git
cd project

# 2. Add original repo as upstream
git remote add upstream git@github.com:original/project.git

# 3. Keep your fork updated
git fetch upstream
git rebase upstream/main

# 4. Push your changes to your fork
git push origin main

Decision Guide

What You WantCommand
See remote URLsgit remote -v
Upload commits to GitHubgit push
Download remote changesgit fetch
Download and integrategit pull
Push new branch first timegit push -u origin <branch>
Clean up stale remote branchesgit fetch --prune
Check ahead/behind statusgit status (with tracking set)

Troubleshooting

ProblemCauseFix
rejected (non-fast-forward)Remote has commits you don't havegit pull --rebase then git push
Permission denied (publickey)SSH key not configuredSee SSH Setup
remote origin already existsRan git remote add twiceUse git remote set-url origin <url>
no tracking informationBranch doesn't track a remotegit push -u origin <branch>
fatal: refusing to merge unrelated historiesRepos have different originsgit pull --allow-unrelated-histories

Best Practices

  • Always pull before push — reduces conflicts and rejected pushes
  • Use --rebase for pull — avoids unnecessary merge commits
  • Set up tracking with -u on first push — enables simple git push/git pull
  • Fetch regularly — stay aware of remote changes without modifying your work
  • Prune stale branchesgit fetch --prune keeps your branch list clean

What's Next

  1. Repository Creation — Create repos on GitHub via web and API
  2. Forking & Pull Requests — Contribute to other projects