Fetching and Pulling
Fetching and pulling are essential operations for keeping your local repository synchronized with remote repositories. In this lesson, we'll explore the differences between fetch and pull, and learn when to use each command.
Understanding Fetch vs Pull
The key difference between fetch and pull:
git fetch:
- Downloads commits, files, and refs from remote
- Updates remote tracking branches (origin/main)
- Does NOT modify your working directory
- Does NOT merge changes into your current branch
- Safe to run anytime
git pull:
- Performs git fetch
- Immediately merges changes into current branch
- Updates both remote tracking branches and working directory
- Equivalent to: git fetch + git merge
- Can cause merge conflicts
Key Concept: Fetch is like checking your mail - you see what's new but don't open it. Pull is like checking your mail and immediately reading everything.
Basic Fetch Command
The basic syntax for fetching:
# Fetch from default remote (origin)
git fetch
# Fetch from specific remote
git fetch origin
# Fetch from all remotes
git fetch --all
# Fetch specific branch
git fetch origin main
What Happens During Fetch
When you fetch, Git:
1. Connects to the remote repository
2. Downloads new commits and files
3. Updates remote tracking branches (origin/main, origin/develop)
4. Shows what was fetched
5. Does NOT modify your working files
6. Does NOT modify your local branches
# Example output:
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From https://github.com/user/repo
abc1234..def5678 main -> origin/main
Viewing Fetched Changes
After fetching, you can inspect the changes before merging:
# Fetch changes
git fetch origin
# View commits that were fetched
git log HEAD..origin/main --oneline
# See detailed changes
git diff HEAD..origin/main
# View all remote branches
git branch -r
# Check status
git status
# Output: Your branch is behind 'origin/main' by 3 commits
Tip: Fetch first, review changes, then decide whether to merge or rebase. This gives you control over when and how to integrate changes.
Basic Pull Command
The basic syntax for pulling:
# Pull from default remote and branch
git pull
# Pull from specific remote and branch
git pull origin main
# Pull from upstream
git pull upstream main
# Example workflow:
git checkout main
git pull origin main
Pull with Rebase
Instead of merging, you can rebase when pulling:
# Pull and rebase instead of merge
git pull --rebase origin main
# Set rebase as default for pull
git config --global pull.rebase true
# Pull with rebase for current branch only
git config branch.main.rebase true
# Verify configuration
git config --get pull.rebase
Difference:
- git pull - Creates a merge commit
- git pull --rebase - Replays your commits on top of fetched commits (cleaner history)
Fetch and Prune
Remove references to remote branches that no longer exist:
# Fetch and remove stale remote tracking branches
git fetch --prune origin
# OR
git fetch -p origin
# Set prune as default
git config --global fetch.prune true
# Prune without fetching
git remote prune origin
# See what would be pruned
git remote prune origin --dry-run
Tip: Use --prune regularly to keep your remote tracking branches clean. Deleted remote branches won't automatically disappear from your local tracking branches without pruning.
Fast-Forward Only Pulls
Ensure pull only succeeds if it can fast-forward:
# Only pull if fast-forward is possible
git pull --ff-only origin main
# Set fast-forward only as default
git config --global pull.ff only
# If fast-forward isn't possible, pull will fail:
fatal: Not possible to fast-forward, aborting.
# Then you can decide to merge or rebase manually
git merge origin/main
# OR
git rebase origin/main
Handling Pull Conflicts
When pull causes conflicts, here's how to handle them:
# Attempt to pull
git pull origin main
# If conflicts occur:
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
# 1. Check which files have conflicts
git status
# 2. Open conflicted files and resolve
# Look for conflict markers:
<<<<<<< HEAD
Your changes
=======
Remote changes
>>>>>>> origin/main
# 3. After resolving, stage the files
git add file.txt
# 4. Complete the merge
git commit -m "Merge branch 'main' of origin/main"
# Or if using pull --rebase:
git add file.txt
git rebase --continue
Important: If pull creates conflicts and you want to abort, use:
- For merge: git merge --abort
- For rebase: git rebase --abort
Fetching Specific Branches
You can fetch specific branches or references:
# Fetch specific branch
git fetch origin feature-branch
# Fetch multiple branches
git fetch origin main develop
# Fetch all branches from remote
git fetch origin 'refs/heads/*:refs/remotes/origin/*'
# Fetch tags only
git fetch --tags origin
# Fetch without tags
git fetch --no-tags origin
Syncing Forked Repositories
A common workflow for keeping forks up to date:
# 1. Add upstream remote (original repository)
git remote add upstream https://github.com/original/repo.git
# 2. Fetch from upstream
git fetch upstream
# 3. Checkout your main branch
git checkout main
# 4. Merge upstream changes
git merge upstream/main
# 5. Push to your fork
git push origin main
# Alternative: Rebase instead of merge
git rebase upstream/main
git push --force-with-lease origin main
Fork Workflow: Regular syncing keeps your fork up to date with the original repository, making it easier to contribute and avoiding large conflicts.
Fetch Depth and Shallow Clones
Control how much history to fetch:
# Fetch only recent commits (shallow fetch)
git fetch --depth=1 origin main
# Fetch more history in shallow clone
git fetch --deepen=50
# Convert shallow clone to full clone
git fetch --unshallow
# Check if repository is shallow
git rev-parse --is-shallow-repository
Pull Strategies
Different strategies for pulling changes:
Strategy 1: Default Merge
git pull origin main
# Creates merge commit if needed
Strategy 2: Rebase
git pull --rebase origin main
# Replays your commits on top
Strategy 3: Fast-Forward Only
git pull --ff-only origin main
# Fails if merge commit would be needed
Strategy 4: Fetch + Manual Merge
git fetch origin
git log HEAD..origin/main # Review changes
git merge origin/main # Merge when ready
Automatic Pull on Checkout
Configure branches to automatically pull on checkout:
# Set up branch to track remote
git branch --set-upstream-to=origin/main main
# Configure automatic pull (use with caution)
git config branch.main.mergeoptions "--ff-only"
# View tracking configuration
git branch -vv
Caution: Automatic pulls can cause unexpected changes. It's generally better to explicitly fetch and pull when needed.
Fetch vs Pull: When to Use Each
Use FETCH when:
✓ You want to see what changed on remote
✓ You're in the middle of work and want to check updates
✓ You want to review changes before integrating
✓ You're working on experimental code
✓ You want to compare branches
Use PULL when:
✓ You're ready to integrate remote changes immediately
✓ You're starting new work and want latest code
✓ You trust the remote branch completely
✓ You're on a stable branch like main
✓ You want to quickly sync with remote
Fetch Multiple Remotes
Working with multiple remote repositories:
# Fetch from all remotes
git fetch --all
# Fetch from specific remotes
git fetch origin
git fetch upstream
# Compare branches from different remotes
git diff origin/main..upstream/main
# Merge from upstream
git merge upstream/main
Practice Exercise:
Fetch, Review, and Pull Workflow:
# 1. Check current status
git status
git branch -vv
# 2. Fetch from remote
git fetch origin
# 3. See what was fetched
git log HEAD..origin/main --oneline
git log --graph --all --oneline
# 4. Review changes in detail
git diff HEAD..origin/main
# 5. Check for conflicts before pulling
git merge-base HEAD origin/main
# 6. Pull with rebase
git pull --rebase origin main
# 7. Verify everything is up to date
git status
# 8. Practice with upstream (if you have it)
git fetch upstream
git log HEAD..upstream/main --oneline
git merge upstream/main
# 9. Practice pruning
git fetch --prune origin
git branch -r # See remaining remote branches
Troubleshooting Fetch and Pull Issues
Issue: "Your branch is behind by N commits"
Solution:
git pull origin main
Issue: "divergent branches"
Solution:
git fetch origin
git rebase origin/main
# OR
git merge origin/main
Issue: "refusing to merge unrelated histories"
Solution:
git pull origin main --allow-unrelated-histories
Issue: Stale remote tracking branches
Solution:
git fetch --prune origin
git remote prune origin
Issue: Pull conflicts
Solution:
# Resolve conflicts, then:
git add .
git commit
# Or abort:
git merge --abort
Best Practices
✓ Fetch regularly to stay aware of remote changes
✓ Use fetch before pull to review changes
✓ Prune regularly to clean up stale branches
✓ Configure pull.rebase for cleaner history
✓ Use --ff-only on important branches for safety
✓ Commit or stash local changes before pulling
✓ Communicate with team before force pushing after rebase
✗ Don't pull into a dirty working directory
✗ Don't use pull if you have uncommitted important changes
✗ Avoid pulling without reviewing changes first
Fetch and Pull Configuration
# Set default remote for fetch/pull
git config branch.main.remote origin
# Set default merge branch
git config branch.main.merge refs/heads/main
# Always prune when fetching
git config --global fetch.prune true
# Use rebase when pulling
git config --global pull.rebase true
# Show all fetch/pull related configs
git config --get-regexp "branch|fetch|pull"
Summary
In this lesson, you learned:
- git fetch downloads changes without modifying your working directory
- git pull fetches and immediately merges changes
- Fetch is safer - review changes before integrating
- Use --rebase option for cleaner commit history
- Use --prune to clean up deleted remote branches
- --ff-only prevents accidental merge commits
- Handle conflicts by resolving and committing or aborting
- Regularly sync forks with upstream repositories
Next Up: In the next lesson, we'll learn about cloning repositories and different cloning options!