Remote Repositories

Difficulty: Beginner

Question

Explain the difference between git fetch and git pull. How do remote tracking branches work?

Answer

git fetch downloads new data from the remote repository but does NOT integrate it into your working files. It updates your remote tracking branches (like origin/main) so you can see what others have done without changing your local branch.

git pull is essentially git fetch + git merge. It fetches from the remote and immediately merges the changes into your current branch. Some teams prefer git pull --rebase which does fetch + rebase instead of fetch + merge, creating a cleaner linear history.

Remote tracking branches (like origin/main) are local references to the state of branches on the remote. They are updated when you fetch or pull. Your local branches can be set to track a remote branch, which lets git push and git pull know where to send and receive changes.

The key insight: always fetch first to see what is happening on the remote before deciding how to integrate changes. Blindly pulling can lead to unexpected merge conflicts.

Code examples

Remote Management

# Add a remote
git remote add origin https://github.com/user/repo.git

# List remotes
git remote -v
# origin  https://github.com/user/repo.git (fetch)
# origin  https://github.com/user/repo.git (push)

# Add a second remote (e.g., upstream for forks)
git remote add upstream https://github.com/original/repo.git

# Rename a remote
git remote rename origin github

# Change remote URL (e.g., HTTPS to SSH)
git remote set-url origin git@github.com:user/repo.git

# Remove a remote
git remote remove upstream

# Show detailed info about a remote
git remote show origin
# Fetch URL: ...
# Push  URL: ...
# HEAD branch: main
# Remote branches:
#   main    tracked
#   develop tracked
# Local branches configured for 'git pull':
#   main    merges with remote main
#   develop merges with remote develop

Most repos have one remote (origin). Forks typically add an upstream remote to sync with the original repository.

Fetch vs Pull

# Fetch: download changes, don't merge
git fetch origin
# Updates origin/main, origin/develop, etc.
# Your local branches are UNCHANGED

# See what changed on remote
git log main..origin/main --oneline
# Shows commits on origin/main that you don't have

# Now decide: merge or rebase
git merge origin/main
# OR
git rebase origin/main

# Pull: fetch + merge in one step
git pull origin main
# Equivalent to:
#   git fetch origin
#   git merge origin/main

# Pull with rebase (cleaner history)
git pull --rebase origin main
# Equivalent to:
#   git fetch origin
#   git rebase origin/main

# Set pull to rebase by default
git config --global pull.rebase true

# Fetch all remotes
git fetch --all

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

Prefer git fetch + inspect + merge/rebase over blind git pull. Use --prune to clean up remote tracking branches that no longer exist on the server.

Push and Upstream Tracking

# Push and set upstream tracking
git push -u origin feature/auth
# -u sets origin/feature/auth as the tracking branch
# After this, just 'git push' works

# Push to a different remote branch name
git push origin local-branch:remote-branch

# Force push (CAREFUL - rewrites remote history)
git push --force-with-lease origin feature/auth
# --force-with-lease is safer than --force
# It fails if someone else pushed since your last fetch

# Delete a remote branch
git push origin --delete feature/old-branch

# Push all branches
git push --all origin

# Push tags
git push origin v1.0.0
git push --tags  # push all tags

# See tracking relationships
git branch -vv
# * main       a1b2c3d [origin/main] feat: add auth
#   feature    e4f5g6h [origin/feature] wip: login
#   local-only i7j8k9l no tracking branch

Always use --force-with-lease instead of --force. It prevents overwriting others' work. git push -u sets up tracking so future push/pull commands know the default remote.

Key points

Concepts covered

git remote, git push, git pull, git fetch, Upstream Tracking