Now that your local repository is connected to GitHub, it's time to master the core workflow of collaborative development: pushing your changes to share them and pulling changes to stay updated. In this lesson, you'll learn how git push and git pull work, understand the difference between fetch and pull, handle common synchronization scenarios, and develop the habits that keep you in sync with your team. By the end, you'll be comfortable with the daily rhythm of collaborative Git work.
Understanding Push and Pull
Push and pull are how you synchronize your local repository with GitHub. Think of them as upload and download for code.
git push: Uploads your local commits to GitHub
- Shares your work with others
- Backs up your commits to the cloud
- Makes your changes visible on GitHub
git pull: Downloads commits from GitHub and merges them
- Gets the latest changes from teammates
- Keeps your local repository up-to-date
- Automatically merges remote changes into your branch
The Sync Cycle
Here's the typical workflow:
1. Pull latest changes
↓
2. Work on your code (edit, stage, commit)
↓
3. Pull again (in case anything changed while you worked)
↓
4. Push your changes
↓
5. Repeat!🔄 The Golden Rule
Always pull before you push!
This prevents conflicts and ensures you're working with the latest code. Make this a habit and you'll avoid many common problems.
Git Push: Uploading Your Changes
Basic Push
Once you've made and committed changes locally, push them to GitHub:
# Make sure you're on the right branch
git status
# Push to remote
git pushIf you set up upstream tracking (with git push -u), this simple git push command knows where to push.
First Push (Setting Upstream)
For a new branch's first push:
# First push - set upstream tracking
git push -u origin main
# Or for a feature branch
git push -u origin feature/new-featureAfter the first push with -u, subsequent pushes just need:
git pushExplicit Push
You can also specify exactly where to push:
# Push to specific remote and branch
git push origin main
# Push current branch to remote
git push origin HEADWhat Happens During a Push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 300 bytes | 300 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:username/repo.git
a1b2c3d..f4e5d6c main -> mainThis shows:
- Git packaging your commits
- Compressing data for efficient transfer
- Uploading to GitHub
- The commit range pushed (
a1b2c3d..f4e5d6c)
Success! Your changes are now on GitHub. Visit your repository to see them.
Git Pull: Downloading Changes
Basic Pull
Download and merge the latest changes from GitHub:
# Pull changes from remote
git pullIf upstream is set, this pulls from the tracked remote branch.
Explicit Pull
# Pull from specific remote and branch
git pull origin mainWhat Happens During a Pull
Scenario 1: Fast-Forward (No Local Changes)
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:username/repo
f4e5d6c..c7d8e9f main -> origin/main
Updating f4e5d6c..c7d8e9f
Fast-forward
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)Your local branch fast-forwards to match the remote. Simple and clean!
Scenario 2: Merge (You Have Local Commits)
If you've made commits locally that don't exist on the remote, Git creates a merge commit:
From github.com:username/repo
f4e5d6c..c7d8e9f main -> origin/main
Merge made by the 'recursive' strategy.
styles.css | 5 +++++
1 file changed, 5 insertions(+)Git merges the remote changes with your local changes automatically.
Scenario 3: Conflicts
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.If the same lines were changed both locally and remotely, you'll need to resolve conflicts (we'll cover this in the collaboration section).
Git Fetch vs Git Pull
Understanding the difference between git fetch and git pull is important for having control over your workflow.
Git Fetch
git fetch downloads commits from the remote but doesn't merge them:
git fetch originThis updates your remote-tracking branches (like origin/main) but doesn't touch your working directory or current branch.
Git Pull = Fetch + Merge
# These two are equivalent:
git pull origin main
# Is the same as:
git fetch origin
git merge origin/mainWhen to Use Fetch
Use git fetch when you want to:
- See what changed on the remote without merging
- Review changes before integrating them
- Work on multiple branches and update all remote tracking
Fetch and Review Workflow
# Download latest changes
git fetch origin
# See what's new
git log HEAD..origin/main --oneline
# Review the changes
git diff HEAD origin/main
# Looks good? Merge it
git merge origin/main
# Or if you don't like it, don't merge!🔍 Fetch is Safer for Review
Many developers prefer git fetch because it lets them see what changed before merging. Think of pull as "fetch and auto-merge" vs fetch as "fetch and let me decide."
Comparison Table
Command | Downloads? | Merges? | Use Case
------------|-----------|---------|---------------------------
git fetch | Yes | No | Review before merging
git pull | Yes | Yes | Quick sync when confident
git merge | No | Yes | Merge existing remote dataComplete Push/Pull Workflow
Let's walk through a complete realistic workflow:
Morning: Starting Work
# 1. Pull latest changes
git pull
# 2. Create a feature branch
git switch -c feature/add-search
# 3. Work on your feature
# ... edit files ...
# 4. Stage and commit your changes
git add .
git commit -m "Add search functionality"
# 5. Make more changes
# ... edit more files ...
git commit -am "Improve search performance"Afternoon: Ready to Share
# 1. Switch to main to update it
git switch main
# 2. Pull latest changes (colleagues may have pushed)
git pull
# 3. Switch back to your feature branch
git switch feature/add-search
# 4. Merge main into your branch (get latest changes)
git merge main
# 5. Push your feature branch
git push -u origin feature/add-searchWhy This Workflow?
- Update main first: Ensures you have the latest code
- Merge main into feature: Resolves conflicts in your branch, not main
- Push feature branch: Shares your work without affecting main
Pushing and Tracking Branches
Push a New Branch
# Create and switch to new branch
git switch -c feature/dark-mode
# Make changes and commit
git commit -am "Add dark mode toggle"
# Push and set upstream
git push -u origin feature/dark-modePush All Branches
# Push all local branches to remote
git push --all originBe careful! This pushes ALL branches, including ones you might not be ready to share.
Delete a Remote Branch
# Delete remote branch
git push origin --delete feature/old-feature
# Or shorthand
git push origin :feature/old-featureView Remote Branches
# See all branches (local and remote)
git branch -a
# Output:
# * main
# feature/login
# remotes/origin/HEAD -> origin/main
# remotes/origin/main
# remotes/origin/feature/login
# remotes/origin/feature/dark-modeCommon Push/Pull Scenarios
Scenario 1: Push Rejected - Remote Has Changes
Error:
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'github.com:user/repo.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.Solution: Pull first, then push:
git pull
# Resolve any conflicts if needed
git pushScenario 2: Forgot to Pull Before Committing
# You made commits, but remote has changed
git push
# Error: rejected!
# Pull to merge remote changes
git pull
# This might create a merge commit
# Now push
git pushScenario 3: Want to Avoid Merge Commits
Use rebase instead of merge when pulling:
# Pull with rebase instead of merge
git pull --rebase
# This replays your commits on top of the remote commits
# Results in cleaner, linear historyRebase vs Merge when pulling:
- Merge (default): Creates a merge commit, preserves exact history
- Rebase: Replays your commits on top, creates linear history
Many teams prefer rebase for a cleaner history. You can make it the default:
git config --global pull.rebase trueScenario 4: Check Status Before Pushing
# See what will be pushed
git log origin/main..HEAD --oneline
# See what changed
git diff origin/main..HEAD
# Check branch status
git statusForce Pushing (Use with Caution!)
Sometimes you need to overwrite the remote history:
# Force push (dangerous!)
git push --force
# Safer force push (won't overwrite if someone else pushed)
git push --force-with-leaseWARNING: Force Pushing is Dangerous!
Force pushing rewrites remote history. This causes problems for anyone who has already pulled the old commits.
Only force push when:
- You're working alone on a branch
- You've coordinated with your team
- You're fixing a critical mistake
Never force push to:
- Shared branches like
mainordevelop - Branches others are working on
- Public repositories (unless you have a very good reason)
When You Might Need Force Push
# You amended a commit that was already pushed
git commit --amend -m "Better message"
git push --force-with-lease
# You rebased to clean up history (on your personal branch)
git rebase -i HEAD~3
git push --force-with-leaseBest Practices for Staying Synced
1. Pull Before You Start Working
# Every morning or session
git pull2. Pull Before You Push
# Before pushing
git pull
git push3. Commit Often, Push Regularly
Don't let your local changes pile up. Push frequently:
- Backs up your work
- Shares progress with team
- Makes conflicts smaller and easier to resolve
4. Use Feature Branches
Work on branches, not directly on main:
# Create feature branch
git switch -c feature/my-feature
# Work and commit
git commit -am "Progress on feature"
# Push to remote
git push -u origin feature/my-feature
# Main stays clean!5. Check Status Frequently
# See local status
git status
# See how you compare to remote
git status -sb
# Output shows:
# ## main...origin/main [ahead 2]
# This means you have 2 commits to push6. Communicate with Your Team
If you're going to make big changes:
- Let teammates know
- Work on a separate branch
- Use pull requests for review
Practice Push/Pull Commands
Try these commands to practice synchronization:
Practice Push and Pull
Experiment with synchronization commands
Try these examples:
Troubleshooting Push/Pull Issues
Issue: Diverged Branches
Message: "Your branch and 'origin/main' have diverged"
Meaning: Both local and remote have commits the other doesn't have
Solution:
# Pull to merge
git pull
# Or pull with rebase for cleaner history
git pull --rebase
# Then push
git pushIssue: Pull Creates Unwanted Merge Commits
Problem: Every pull creates a merge commit
Solution: Use rebase when pulling:
# Set as default
git config --global pull.rebase true
# Or use flag each time
git pull --rebaseIssue: Accidentally Pushed to Wrong Branch
Problem: Pushed commits to wrong branch
Solution: Reset and push to correct branch:
# Create branch at current commit
git branch correct-branch
# Reset current branch
git reset --hard origin/wrong-branch
# Switch and push to correct branch
git switch correct-branch
git push -u origin correct-branchCommand Reference
Here's a quick reference of push and pull commands:
# Pushing
git push # Push to tracked remote
git push origin main # Push to specific remote/branch
git push -u origin main # Push and set upstream
git push --all # Push all branches
git push origin --delete branch # Delete remote branch
git push --force-with-lease # Safe force push
# Pulling
git pull # Pull from tracked remote
git pull origin main # Pull from specific remote/branch
git pull --rebase # Pull with rebase instead of merge
# Fetching
git fetch # Fetch from all remotes
git fetch origin # Fetch from specific remote
git fetch --all # Fetch from all remotes
git fetch --prune # Fetch and remove deleted remote branches
# Checking Status
git status # Local status
git status -sb # Branch status with ahead/behind info
git log origin/main..HEAD # Commits to push
git log HEAD..origin/main # Commits to pull
git diff origin/main # Differences with remoteKey Takeaways
git pushuploads your local commits to GitHubgit pulldownloads and merges remote commitsgit fetchdownloads without merging (safer for review)- Always pull before pushing to avoid conflicts
git pull=git fetch+git merge- Use
-uflag on first push to set upstream tracking git pull --rebasecreates cleaner history than merge- Force pushing is dangerous—use
--force-with-leaseif needed - Work on feature branches, keep main stable
- Push regularly to backup work and share progress
What's Next?
Excellent work! You now understand the complete push/pull workflow and can synchronize your local and remote repositories effectively. You're ready for real collaborative development!
In the next lesson, we'll learn about cloning repositories. You'll discover how to download existing projects from GitHub, work with other people's code, contribute to open source, and understand the difference between cloning and forking. This opens up a whole world of collaboration and learning from existing projects!
🎯 Practice Assignment
Before the next lesson, practice the push/pull workflow:
- Make several commits in your local repository
- Practice pulling before pushing
- Try
git fetchfollowed by reviewing changes before merging - Create a feature branch, push it, and delete it remotely
- Experiment with
git pull --rebase - Check your status frequently with
git statusandgit status -sb