Git & GitHub

Fetching and Pulling

13 min Lesson 14 of 35

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!

ES
Edrees Salih
22 hours ago

We are still cooking the magic in the way!