Mission: Create a project, make 3 commits, fix the last one.
mkdir test-git && cd test-git && git init
# 3 commits
echo "print('v1')" > app.py && git add . && git commit -m "Version 1"
echo "print('v2')" > app.py && git add . && git commit -m "Version 2"
echo "print('v3 with bug')" > app.py && git add . && git commit -m "Version 3"
# Fix the last commit
echo "print('v3 fixed')" > app.py && git add . && git commit --amend -m "Version 3 - Fixed"Check: git log --oneline → 3 commits, the last one says "Fixed"
Mission: 2 features in parallel, merge cleanly.
# Base
echo "print('main')" > main.py && git add . && git commit -m "Main app"
# Feature 1
git checkout -b feature-login
echo "print('login')" > login.py && git add . && git commit -m "Add login"
# Feature 2
git checkout main && git checkout -b feature-api
echo "print('api')" > api.py && git add . && git commit -m "Add API"
# Merge everything into main
git checkout main
git merge feature-login
git merge feature-api
# Clean up
git branch -d feature-login feature-apiCheck: git log --graph --oneline → see the merges
Mission: Same scenario, 2 different strategies.
mkdir test-merge && cd test-merge && git init
echo "print('base')" > app.py && git add . && git commit -m "Base"
# Feature branch
git checkout -b feature
echo "print('feature')" > feature.py && git add . && git commit -m "Add feature"
# Main moves forward
git checkout main
echo "print('base v2')" > app.py && git add . && git commit -m "Update base"
# Merge
git merge feature
git log --graph --oneline # See the history with mergemkdir test-rebase && cd test-rebase && git init
echo "print('base')" > app.py && git add . && git commit -m "Base"
git checkout -b feature
echo "print('feature')" > feature.py && git add . && git commit -m "Add feature"
git checkout main
echo "print('base v2')" > app.py && git add . && git commit -m "Update base"
# Rebase
git checkout feature && git rebase main
git checkout main && git merge feature
git log --oneline # Linear historyQuestion: What difference do you see in git log?
Mission: Juggle several tasks.
mkdir test-stash && cd test-stash && git init
echo "print('v1')" > app.py && git add . && git commit -m "Version 1"
# You start coding
echo "print('work in progress')" >> app.py
# EMERGENCY! You have to switch
git stash # Save
git checkout -b hotfix
echo "print('URGENT FIX')" > fix.py && git add . && git commit -m "Critical fix"
# Cherry-pick the fix onto main
git checkout main
git cherry-pick <hash-du-fix>
# Go back to your work
git stash pop
echo "print('feature complete')" >> app.py && git add . && git commit -m "Feature done"Challenge: Is the urgent fix in main AND in hotfix?
Mission: Simulate an emergency with reset.
mkdir test-urgence && cd test-urgence && git init
# Several commits
echo "print('v1')" > app.py && git add . && git commit -m "Version 1"
echo "print('v2')" > app.py && git add . && git commit -m "Version 2"
echo "print('v3')" > app.py && git add . && git commit -m "Version 3"
echo "print('v4 BROKEN')" > app.py && git add . && git commit -m "Version 4 - Bug!"
# Oh no! v4 breaks everything in production
git log --oneline # Note the v3 hash
# Solution 1: Hard reset (destructive)
git reset --hard <hash-v3> # Back to v3, v4 disappears
git log --oneline # Only 3 commits left
# Solution 2: Revert (safe)
# Put v4 back first
git reset --hard <hash-v4> # Go back to v4
git revert HEAD # Create a commit that undoes v4
git log --oneline # 5 commits: v1,v2,v3,v4,revert-v4Lesson: Revert = safe for production, Reset = OK for local
Can you do all of this in 15 minutes?
If yes → you master Git!