Hands-on Lab TP4 — GitHub & Remote Repositories
Hands-on Lab 60 min Module 03
Objectives
By the end of this lab, you will have:
- Created and pushed a repository to GitHub
- Mastered push/pull/fetch commands
- Forked a public repository
- Synchronized with an upstream repository
- Opened a Pull Request to an open-source project
Part 1: Push Your Project to GitHub
mkdir git-tp4-github
cd git-tp4-github
git init
echo "__pycache__/" > .gitignore
echo "*.pyc" >> .gitignore
Create calculator.py:
"""Simple calculator module."""
def add(a, b):
"""Add two numbers."""
return a + b
def subtract(a, b):
"""Subtract b from a."""
return a - b
def multiply(a, b):
"""Multiply two numbers."""
return a * b
def divide(a, b):
"""Divide a by b."""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
Create README.md:
# Python Calculator
A simple calculator module with basic arithmetic operations.
## Features
- Addition
- Subtraction
- Multiplication
- Division (with zero division protection)
## Usage
```python
from calculator import add, multiply
result = add(3, 4) # → 7
```bash
git add .
git commit -m "feat: initial calculator with basic operations"
Create test_calculator.py:
"""Tests for calculator module."""
from calculator import add, subtract, multiply, divide
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
def test_subtract():
assert subtract(10, 3) == 7
def test_multiply():
assert multiply(4, 5) == 20
def test_divide():
assert divide(10, 2) == 5.0
try:
divide(1, 0)
assert False, "Should have raised ValueError"
except ValueError:
pass
print("All tests passed!")
git add test_calculator.py
git commit -m "test: add unit tests for calculator module"
Push to GitHub
gh repo create git-tp4-github --public --description "TP4 - GitHub & Remotes"
git push -u origin main
gh repo view --web
Part 2: Simulate a Remote Team
In this part, we simulate a colleague pushing work to the same repository.
cd ..
git clone git@github.com:YOUR_USERNAME/git-tp4-github.git git-tp4-colleague
cd git-tp4-colleague
Add these functions to the end of calculator.py in the colleague's clone:
def power(base, exponent):
"""Calculate base raised to the power of exponent."""
return base ** exponent
def square_root(n):
"""Calculate the square root of n."""
if n < 0:
raise ValueError("Cannot take square root of negative number")
return n ** 0.5
git add calculator.py
git commit -m "feat: add power and square_root functions"
git push
# Back to your main folder
cd ../git-tp4-github
# Simulate your own local work
echo "# Advanced Calculator" >> README.md
git add README.md
git commit -m "docs: update README title"
# Try to push — it will fail!
git push
# Error: rejected — remote contains work you don't have locally
# Solution: fetch then rebase
git fetch origin
git log --oneline main..origin/main # See what's new
git rebase origin/main # Integrate their changes
git push # Now succeeds!
Part 3: Fork a Public Project
gh repo fork octocat/Spoon-Knife --clone
cd Spoon-Knife
# View remotes
git remote -v
# origin git@github.com:YOUR_USERNAME/Spoon-Knife.git
# upstream git@github.com:octocat/Spoon-Knife.git
Create a branch and add a contribution:
git switch -c docs/add-french-translation
Create LISEZ-MOI.md with this content:
# Spoon-Knife
Ce dépôt est un exemple de fork GitHub.
## Instructions
1. Forkez ce dépôt
2. Clonez votre fork
3. Faites vos modifications
4. Créez une Pull Request
## À propos
Ce projet est utilisé par GitHub pour démontrer le workflow Fork & Pull Request.
git add LISEZ-MOI.md
git commit -m "docs: add French README (LISEZ-MOI.md)"
git push -u origin docs/add-french-translation
gh pr create \
--repo octocat/Spoon-Knife \
--title "docs: add French README translation" \
--body "Adding a French version of the README for French-speaking contributors."
Part 4: Synchronize with Upstream
git fetch upstream
git log --oneline HEAD..upstream/main
git switch main
git merge upstream/main
git push origin main
Part 5: Manage Remote Branches
cd ../git-tp4-github
git branch -a
git switch -c feature/advanced-math
Add this function to the end of calculator.py:
def factorial(n):
"""Calculate n factorial."""
if n < 0:
raise ValueError("Factorial not defined for negative numbers")
if n == 0:
return 1
return n * factorial(n - 1)
git add calculator.py
git commit -m "feat: add factorial function"
git push -u origin feature/advanced-math
git branch -a
# Delete the remote branch
git push origin --delete feature/advanced-math
# Delete the local branch
git branch -d feature/advanced-math
git remote prune origin
git fetch --prune
Validation Checklist
-
git-tp4-githubrepository is visible on GitHub with all commits -
git pushwithout arguments works (tracking configured) -
git fetch+git rebasesuccessfully integrated team changes - Fork created with
upstreamremote configured - Contribution sent to forked repository as a PR
- Sync with upstream via
git fetch upstream+git merge - Remote branch created, then deleted
Common Errors and Solutions
Error: "rejected - non-fast-forward"
# Problem: Remote has commits you don't have
# Solution: Fetch and rebase (or merge) before pushing
git fetch origin
git rebase origin/main
git push
Error: "Permission denied (publickey)"
# Problem: SSH key not configured or not added to GitHub
ssh -T git@github.com # Test the connection
ssh-add ~/.ssh/id_ed25519 # Add key to agent
# If key not in GitHub:
cat ~/.ssh/id_ed25519.pub
# Add to: https://github.com/settings/keys
Accidental push of sensitive files
# Remove from tracking
git rm --cached .env
echo ".env" >> .gitignore
git add .gitignore
git commit -m "fix: remove .env from tracking"
git push
# Warning: The file is still in Git history!
# Rotate all exposed credentials immediately.
Summary
You've mastered:
- Pushing projects to GitHub and managing remotes
- Collaborating with push/fetch/rebase workflow
- Contributing to open-source via fork workflow
- Synchronizing a fork with the upstream project
- Managing remote branches
Ready for Module 04 — Collaboration & Pull Requests!