20 KiB
Facilitator Setup Guide - The Great Print Project
This guide helps workshop facilitators set up the cloud-based multiplayer Git module.
Overview
The Great Print Project is a collaborative Git exercise where pairs of students work together on a shared repository hosted on your Gitea server at https://git.frod.dk/multiplayer.
What participants will do:
- Clone a real repository from your server
- Collaborate with partners on shared branches
- Deliberately create and resolve merge conflicts
- Create pull requests and review code
- Experience the full collaborative Git workflow
Prerequisites
Gitea Server Setup
You should have:
- Gitea running at https://git.frod.dk/multiplayer
- Admin access to create repositories and users
- HTTPS or SSH access enabled for Git operations
Need to set up Gitea? See the main workshop's GITEA-SETUP.md for Docker + Cloudflare Tunnel instructions.
Workshop Materials
Participants need:
- Access to the module README in
01_essentials/09-multiplayer/README.md - Git installed (version 2.23+)
- Python 3.6+ (to run the print project)
- Text editor
Pre-Workshop Setup
Step 1: Create User Accounts
Create individual Gitea accounts for each participant.
Recommended naming:
student01,student02,student03, etc.- Or use their real names/emails if preferred
Two approaches:
Option A: Manual account creation
- Go to Gitea admin panel
- Create users one by one
- Set initial passwords (students can change later)
- Provide credentials to students
Option B: Self-registration (if you trust your network)
- Enable self-registration in Gitea settings
- Provide registration URL to students
- They create their own accounts
- You verify and approve accounts
Access tokens (recommended for HTTPS):
- Have students create personal access tokens after logging in
- Settings → Applications → Generate New Token
- Token needs
reposcope - Students use token as password when pushing/pulling
Step 2: Create the Repository
Create the shared repository: great-print-project
Via Gitea web UI:
- Log in as admin or organization account
- Click "+" → "New Repository"
- Name:
great-print-project - Owner:
multiplayer(organization) or your admin account - Visibility: Private (only visible to students you add)
- Initialize: Check "Initialize this repository with selected files"
- README: Yes
- License: None
- .gitignore: Python
- Click "Create Repository"
Via command line (alternative):
# Create local directory
mkdir great-print-project
cd great-print-project
# Initialize git
git init
# Add files (see Step 3)
git add .
git commit -m "Initial commit: The Great Print Project"
# Create bare repo on server
ssh user@git.frod.dk
cd /path/to/gitea/repositories/multiplayer
git init --bare great-print-project.git
exit
# Push to server
git remote add origin git@git.frod.dk:multiplayer/great-print-project.git
git push -u origin main
Step 3: Add Starter Code to Repository
Commit these four files to the repository:
File 1: main.py
#!/usr/bin/env python3
"""
The Great Print Project
A collaborative Git exercise
When everyone completes their assigned functions,
this program will print the complete alphabet and numbers!
"""
from letters import print_letters
from numbers import print_numbers
def main():
print("=" * 50)
print(" THE GREAT PRINT PROJECT")
print("=" * 50)
print("\nLetters:")
print_letters()
print() # New line after letters
print("\nNumbers:")
print_numbers()
print() # New line after numbers
print("\n" + "=" * 50)
print(" PROJECT COMPLETE!")
print("=" * 50)
if __name__ == "__main__":
main()
File 2: letters.py
"""
Letter Printing Functions
Each pair completes their assigned functions.
Expected output: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
"""
def print_a():
"""Print letter A - EXAMPLE (already completed)"""
print("A", end=" ")
def print_b():
# TODO: Pair 1 - implement this function
pass
def print_c():
# TODO: Pair 1 - implement this function
pass
def print_d():
# TODO: Pair 1 - implement this function
pass
def print_e():
# TODO: Pair 2 - implement this function
pass
def print_f():
# TODO: Pair 2 - implement this function
pass
def print_g():
# TODO: Pair 2 - implement this function
pass
def print_h():
# TODO: Pair 3 - implement this function
pass
def print_i():
# TODO: Pair 3 - implement this function
pass
def print_j():
# TODO: Pair 3 - implement this function
pass
def print_k():
# TODO: Pair 4 - implement this function
pass
def print_l():
# TODO: Pair 4 - implement this function
pass
def print_m():
# TODO: Pair 4 - implement this function
pass
def print_n():
# TODO: Pair 5 - implement this function
pass
def print_o():
# TODO: Pair 5 - implement this function
pass
def print_p():
# TODO: Pair 5 - implement this function
pass
def print_q():
# TODO: Pair 6 - implement this function
pass
def print_r():
# TODO: Pair 6 - implement this function
pass
def print_s():
# TODO: Pair 6 - implement this function
pass
def print_t():
# TODO: Pair 7 - implement this function
pass
def print_u():
# TODO: Pair 7 - implement this function
pass
def print_v():
# TODO: Pair 7 - implement this function
pass
def print_w():
# TODO: Pair 8 - implement this function
pass
def print_x():
# TODO: Pair 8 - implement this function
pass
def print_y():
# TODO: Pair 8 - implement this function
pass
def print_z():
# TODO: Pair 9 - implement this function
pass
def print_letters():
"""Print all letters A-Z"""
print_a()
print_b()
print_c()
print_d()
print_e()
print_f()
print_g()
print_h()
print_i()
print_j()
print_k()
print_l()
print_m()
print_n()
print_o()
print_p()
print_q()
print_r()
print_s()
print_t()
print_u()
print_v()
print_w()
print_x()
print_y()
print_z()
File 3: numbers.py
"""
Number Printing Functions
Each pair completes their assigned functions.
Expected output: 0 1 2 3 4 5 6 7 8 9
"""
def print_0():
# TODO: Pair 9 - implement this function
pass
def print_1():
# TODO: Pair 10 - implement this function
pass
def print_2():
# TODO: Pair 10 - implement this function
pass
def print_3():
# TODO: Pair 10 - implement this function
pass
def print_4():
# TODO: Pair 11 - implement this function
pass
def print_5():
# TODO: Pair 11 - implement this function
pass
def print_6():
# TODO: Pair 11 - implement this function
pass
def print_7():
# TODO: Pair 12 - implement this function
pass
def print_8():
# TODO: Pair 12 - implement this function
pass
def print_9():
# TODO: Pair 12 - implement this function
pass
def print_numbers():
"""Print all numbers 0-9"""
print_0()
print_1()
print_2()
print_3()
print_4()
print_5()
print_6()
print_7()
print_8()
print_9()
File 4: assignments.md
# Pair Assignments
## How This Works
Each pair is assigned 3 functions to implement. You'll work together on a shared branch.
**Important:** Check with your facilitator for your pair number and assignment!
---
## Assignments
### Pair 1
- **Functions:** `print_b()`, `print_c()`, `print_d()`
- **File:** `letters.py`
- **Branch:** `pair-1-bcd`
### Pair 2
- **Functions:** `print_e()`, `print_f()`, `print_g()`
- **File:** `letters.py`
- **Branch:** `pair-2-efg`
### Pair 3
- **Functions:** `print_h()`, `print_i()`, `print_j()`
- **File:** `letters.py`
- **Branch:** `pair-3-hij`
### Pair 4
- **Functions:** `print_k()`, `print_l()`, `print_m()`
- **File:** `letters.py`
- **Branch:** `pair-4-klm`
### Pair 5
- **Functions:** `print_n()`, `print_o()`, `print_p()`
- **File:** `letters.py`
- **Branch:** `pair-5-nop`
### Pair 6
- **Functions:** `print_q()`, `print_r()`, `print_s()`
- **File:** `letters.py`
- **Branch:** `pair-6-qrs`
### Pair 7
- **Functions:** `print_t()`, `print_u()`, `print_v()`
- **File:** `letters.py`
- **Branch:** `pair-7-tuv`
### Pair 8
- **Functions:** `print_w()`, `print_x()`, `print_y()`
- **File:** `letters.py`
- **Branch:** `pair-8-wxy`
### Pair 9
- **Functions:** `print_z()`, `print_0()`, `print_1()`
- **Files:** `letters.py`, `numbers.py`
- **Branch:** `pair-9-z01`
### Pair 10
- **Functions:** `print_2()`, `print_3()`, `print_4()`
- **File:** `numbers.py`
- **Branch:** `pair-10-234`
### Pair 11
- **Functions:** `print_5()`, `print_6()`, `print_7()`
- **File:** `numbers.py`
- **Branch:** `pair-11-567`
### Pair 12
- **Functions:** `print_8()`, `print_9()`
- **File:** `numbers.py`
- **Branch:** `pair-12-89`
---
## Example Implementation
```python
def print_a():
"""Print letter A - EXAMPLE (already completed)"""
print("A", end=" ")
Your functions should follow the same pattern:
def print_x():
"""Print letter/number X"""
print("X", end=" ")
Testing
After implementing your functions, test with:
python main.py
You should see your letters/numbers in the output!
Questions?
Ask your facilitator for:
- Your pair number
- Your Gitea credentials
- Help with authentication setup
- Any Git or Python issues
#### File 5: README.md (in repository)
```markdown
# The Great Print Project 🎯
A collaborative Git exercise for learning teamwork with version control!
## Goal
When everyone completes their assigned functions, running `python main.py` will print:
================================================== THE GREAT PRINT PROJECT
Letters: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Numbers: 0 1 2 3 4 5 6 7 8 9
================================================== PROJECT COMPLETE!
## Your Mission
1. Find your pair assignment in `assignments.md`
2. Clone this repository
3. Create your feature branch
4. Implement your assigned functions
5. Practice collaboration: push, pull, resolve conflicts
6. Create a pull request
7. Celebrate when your code is merged!
## Quick Start
```bash
# Clone the repository
git clone https://git.frod.dk/multiplayer/great-print-project.git
cd great-print-project
# Check your assignment
cat assignments.md
# Create your branch (replace X with your pair number)
git switch -c pair-X-feature
# Edit your file (letters.py or numbers.py)
# Implement your functions
# Test it
python main.py
# Commit and push
git add .
git commit -m "Implement print_x() functions"
git push -u origin pair-X-feature
Files
- main.py - Orchestrator (runs the whole program)
- letters.py - Functions for printing A-Z
- numbers.py - Functions for printing 0-9
- assignments.md - See which functions your pair should implement
Need Help?
See the module README in the workshop repository for detailed step-by-step instructions!
Happy Collaborating! 🚀
**Commit these files:**
```bash
git add main.py letters.py numbers.py assignments.md README.md
git commit -m "Add Great Print Project starter code"
git push origin main
Step 4: Grant Student Access
Add students as collaborators with write access:
Via Gitea web UI:
- Go to repository → Settings → Collaborators
- Add each student account
- Set permission level: Write (allows push, pull, branch creation)
Important: Students need Write access to:
- Create branches
- Push commits
- Create pull requests
Step 5: Configure Branch Protection (Optional)
To prevent accidental pushes to main:
- Repository → Settings → Branches
- Add protection rule for
mainbranch - Settings:
- Block direct pushes: Yes (requires pull requests)
- Require PR reviews: Optional (you can review PRs yourself)
- Auto-merge: Disabled (you merge manually or students do)
This ensures students:
- MUST use feature branches
- MUST create pull requests
- Can't accidentally break main
For beginners: Consider allowing students to merge their own PRs after approval to complete the full workflow.
Step 6: Test the Setup
Before the workshop, test as a student would:
# Clone as a test student
git clone https://git.frod.dk/multiplayer/great-print-project.git
cd great-print-project
# Run the program
python main.py
# Should show only "A" with missing letters/numbers
# Create test branch
git switch -c test-branch
# Edit letters.py, add print_b()
def print_b():
print("B", end=" ")
# Commit and push
git add letters.py
git commit -m "Test commit"
git push -u origin test-branch
# Create test pull request
# (Do this via web UI)
# Clean up test branch after
git push origin --delete test-branch
During the Workshop
Pairing Students
Strategies for assigning pairs:
Option 1: Random pairing
- Use a random number generator
- Pair students as they arrive
Option 2: Skill-based pairing
- Mix experienced and beginner students
- Balance pair capabilities
Option 3: Let them choose
- Students pick their own partners
- Good for building team dynamics
Announce pairs clearly:
- Write on board/screen: "Pair 1: Alice & Bob"
- Provide printed assignment sheet
- Update
assignments.mdin repo if needed
Timeline
Suggested schedule for 2-hour session:
- 0:00-0:10 (10 min): Introduction, distribute credentials
- 0:10-0:20 (10 min): Students clone repo, verify access
- 0:20-0:35 (15 min): Part 1 - Getting Started
- 0:35-0:55 (20 min): Part 2 - First Contribution
- 0:55-1:25 (30 min): Part 3 - Conflict Exercise (key learning!)
- 1:25-1:45 (20 min): Part 4 - Pull Requests
- 1:45-2:00 (15 min): Part 5 - Syncing, Q&A, wrap-up
Monitoring Progress
Use Gitea to track:
-
Branches created: Repository → Branches
- Should see
pair-1-bcd,pair-2-efg, etc.
- Should see
-
Commits: Repository → Commits
- Each pair should have multiple commits
-
Pull requests: Repository → Pull Requests
- Should see one PR per pair
Walk around the room:
- Check screens for conflict markers
- Ask pairs how they're resolving conflicts
- Ensure both partners are engaged
Common issues to watch for:
- Partners not using the same branch name
- Forgetting to pull before pushing
- Not removing conflict markers completely
- Committing to main instead of feature branch
Managing Pull Requests
Your role:
Option A: Review and merge yourself
- Teaches students what good reviews look like
- Ensures quality before merging
- More facilitator work
Option B: Students merge their own
- More autonomous learning
- Students experience complete workflow
- Risk of messy main branch
Recommended approach:
- First 2-3 PRs: You review and merge (demonstrate good practices)
- Remaining PRs: Students review each other, you approve
- Students can merge after approval
What to check in PR reviews:
- Functions implemented correctly
- No conflict markers in code
- Code follows pattern (e.g.,
print("X", end=" ")) - Meaningful commit messages
Handling Problems
Common issues and solutions:
Problem: "I can't push!"
- Check they're authenticated (token or SSH key)
- Check they pulled latest changes first
- Check branch name matches their partner's
Problem: "Merge conflict won't resolve!"
- Walk through Part 3 step-by-step with them
- Show them the conflict markers
- Verify they removed ALL markers
- Run
python main.pytogether to test
Problem: "We both committed to main!"
- Have them create proper feature branch
- Use
git cherry-pickto move commits - Reset main to origin/main
Problem: "GitHub Desktop / GUI tool shows something different"
- Recommend command line for this exercise
- GUIs can hide important details during conflicts
Celebrating Success
When all pairs have merged:
git pull origin main
python main.py
Everyone should see:
==================================================
THE GREAT PRINT PROJECT
==================================================
Letters:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Numbers:
0 1 2 3 4 5 6 7 8 9
==================================================
PROJECT COMPLETE!
==================================================
Take a screenshot! Share it with the class. This is a genuine collaborative achievement.
Post-Workshop
Cleanup (Optional)
Keep the repository for future workshops:
- Delete all feature branches:
git push origin --delete pair-1-bcd(etc.) - Reset main to initial state
- Reuse for next cohort
Archive the session:
- Export final repository state
- Take screenshots of successful PRs
- Save for portfolio/examples
Student Takeaways
Provide students:
- Link to repository (they can clone for reference)
- Completion certificate (if applicable)
- Next steps: contributing to open source, Git resources
Troubleshooting
Gitea Server Issues
Problem: Server unreachable
- Check Cloudflare Tunnel is running:
cloudflared tunnel info - Verify Gitea container is up:
docker ps - Check firewall rules
Problem: SSH not working
- Verify SSH port is exposed in docker-compose.yml
- Check Cloudflare Tunnel config includes SSH
- Test:
ssh -T git@git.frod.dk
Problem: HTTPS clone fails
- Check certificate validity
- Try
GIT_SSL_NO_VERIFY=true git clone ...(temporary workaround) - Configure Gitea to use proper HTTPS certificates
Authentication Issues
Problem: Students can't log in
- Verify accounts created and active
- Reset passwords if needed
- Check email verification isn't blocking (disable for workshop)
Problem: Push fails with authentication error
- HTTPS: Ensure students use access token, not password
- SSH: Verify keys added to Gitea account
- Check repo permissions (must be Write, not Read)
Git Workflow Issues
Problem: Students create PR but can't merge
- Check branch protection rules
- Verify they have Write access
- Ensure PR doesn't have conflicts
Problem: Main branch gets messy
- Reset to last good commit:
git reset --hard <commit> - Force push:
git push --force origin main(CAREFUL!) - Or start fresh: delete repo, recreate with starter code
Tips for Success
Before Workshop
- Test the entire flow yourself as a student
- Prepare credential sheets for each student
- Have backup plan if server goes down (local git exercise)
- Prepare slides explaining merge conflicts visually
During Workshop
- Start on time - respect everyone's schedule
- Pair programming - ensure both partners engage
- Encourage talking - best conflicts are resolved by discussion
- Celebrate small wins - first push, first conflict resolution
- Walk the room - see screens, answer questions live
After Workshop
- Gather feedback - what worked, what didn't
- Note timing - were parts too rushed or too slow?
- Archive successful PRs as examples
- Plan improvements for next session
Scaling Considerations
Small Groups (4-8 students, 2-4 pairs)
- More hands-on facilitator time
- Can review all PRs in detail
- Easier to monitor progress
Medium Groups (10-20 students, 5-10 pairs)
- Recommended size
- Good mix of collaboration and individual attention
- Helps if you have a teaching assistant
Large Groups (20+ students, 10+ pairs)
- Consider multiple repositories (split into groups of 12 pairs max)
- Recruit teaching assistants to help monitor
- Use breakout rooms (if online)
- Automate more (less PR review, more self-merging)
Additional Resources
For You (Facilitator)
- Gitea documentation: https://docs.gitea.io/
- Pro Git book (free): https://git-scm.com/book/en/v2
- Teaching Git: https://git-scm.com/doc
For Students
- Git cheatsheet (included in workshop repo)
- Interactive Git tutorial: https://learngitbranching.js.org/
- Oh Shit Git: https://ohshitgit.com/ (recovering from mistakes)
Questions or Issues?
This guide should cover most scenarios. If you encounter issues not listed here:
- Check Gitea logs:
docker logs gitea-container-name - Test with minimal setup (single test student)
- Consult Gitea documentation
- Reach out to workshop repository maintainers
Good luck with your workshop! The multiplayer module is where Git skills really come alive.