Pushing and Pulling
Pushing and pulling are how you synchronize changes between your local repository and remote repositories.
Git Push
Pushing uploads your local commits to a remote repository.
Basic Push
git push origin main
This pushes your local main branch to the origin remote.
Push Current Branch
git push
If your branch is tracking a remote branch, this pushes to it.
Push with Upstream
git push -u origin feature
# or
git push --set-upstream origin feature
The -u flag:
- Pushes the branch
- Sets up tracking (so future
git pushandgit pulljust work)
Push All Branches
git push --all origin
Push Tags
# Push specific tag
git push origin v1.0.0
# Push all tags
git push origin --tags
What Happens When You Push
Before push:
Local: A ← B ← C ← D ← E (main)
↑
origin/main
Remote: A ← B ← C ← D (main)
After push:
Local: A ← B ← C ← D ← E (main)
↑
origin/main
Remote: A ← B ← C ← D ← E (main)
Push Rejections
If the remote has commits you don't have:
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes before pushing again.
Solutions:
# Option 1: Pull first (recommended)
git pull origin main
git push origin main
# Option 2: Force push (DANGEROUS - rewrites history)
git push --force origin main
Never force push to shared branches unless you know what you're doing!
Git Pull
Pulling downloads and integrates remote changes.
Basic Pull
git pull origin main
This is equivalent to:
git fetch origin main
git merge origin/main
Pull Current Branch
git pull
If tracking is set up, pulls from the tracked remote branch.
Pull with Rebase
git pull --rebase origin main
Instead of merging, this rebases your changes on top of the remote changes. Creates a cleaner history.
What Happens When You Pull
Before pull:
Local: A ← B ← C ← D (main)
↑
origin/main
Remote: A ← B ← C ← E ← F (main)
After pull (with merge):
Local: A ← B ← C ← D ← ← ← M (main)
\ /
E ← F
↑
origin/main
After pull --rebase:
Local: A ← B ← C ← E ← F ← D' (main)
↑
origin/main
The Push/Pull Workflow
Typical daily workflow:
# Start of day: Get latest changes
git pull origin main
# Make your changes
# ... edit files ...
# Commit your work
git add .
git commit -m "Add feature"
# Before pushing, get any new changes
git pull origin main
# Push your changes
git push origin main
Exercise: Push and Pull
Practice the push/pull workflow:
Handling Push Conflicts
When you can't push because the remote has diverged:
Merge Approach (Default)
git pull origin main # Fetch + Merge
# Resolve any conflicts
git push origin main
Rebase Approach (Cleaner History)
git pull --rebase origin main
# Resolve any conflicts
git rebase --continue # If conflicts occurred
git push origin main
Force Push (Use Carefully!)
git push --force origin main
# or safer:
git push --force-with-lease origin main
--force-with-lease only force pushes if no one else has pushed since you last fetched.
Push Options
# Push and set upstream
git push -u origin feature
# Delete remote branch
git push origin --delete feature
# Push all branches
git push --all
# Push tags
git push --tags
# Force push (dangerous!)
git push --force
git push -f
# Safer force push
git push --force-with-lease
# Dry run (show what would happen)
git push --dry-run
Pull Options
# Pull with rebase
git pull --rebase
# Pull and autostash local changes
git pull --autostash
# Pull from specific remote/branch
git pull origin feature
# Pull all remotes
git pull --all
Configuring Default Behavior
Set Push Default
# Push current branch to matching remote branch
git config --global push.default current
# Only push if upstream is set
git config --global push.default simple # (default)
Set Pull Default
# Always rebase on pull
git config --global pull.rebase true
# Always merge on pull (default)
git config --global pull.rebase false
Summary
- Push uploads your commits to a remote
- Pull downloads and integrates remote commits
- Use
-uto set up tracking when pushing new branches - Pull before push to avoid rejections
- Use
--rebasefor cleaner history - Never force push to shared branches
- Use
--force-with-leaseif you must force push
In the next lesson, we'll explore the difference between fetch and pull.

