Files
git-workshop/01_essentials/09-multiplayer/FACILITATOR-SETUP.md
2026-01-07 23:46:32 +01:00

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:

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

  1. Go to Gitea admin panel
  2. Create users one by one
  3. Set initial passwords (students can change later)
  4. Provide credentials to students

Option B: Self-registration (if you trust your network)

  1. Enable self-registration in Gitea settings
  2. Provide registration URL to students
  3. They create their own accounts
  4. 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 repo scope
  • Students use token as password when pushing/pulling

Step 2: Create the Repository

Create the shared repository: great-print-project

Via Gitea web UI:

  1. Log in as admin or organization account
  2. Click "+" → "New Repository"
  3. Name: great-print-project
  4. Owner: multiplayer (organization) or your admin account
  5. Visibility: Private (only visible to students you add)
  6. Initialize: Check "Initialize this repository with selected files"
  7. README: Yes
  8. License: None
  9. .gitignore: Python
  10. 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:

  1. Go to repository → Settings → Collaborators
  2. Add each student account
  3. 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:

  1. Repository → Settings → Branches
  2. Add protection rule for main branch
  3. 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.md in 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:

  1. Branches created: Repository → Branches

    • Should see pair-1-bcd, pair-2-efg, etc.
  2. Commits: Repository → Commits

    • Each pair should have multiple commits
  3. 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:

  1. First 2-3 PRs: You review and merge (demonstrate good practices)
  2. Remaining PRs: Students review each other, you approve
  3. 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.py together to test

Problem: "We both committed to main!"

  • Have them create proper feature branch
  • Use git cherry-pick to 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)

For Students


Questions or Issues?

This guide should cover most scenarios. If you encounter issues not listed here:

  1. Check Gitea logs: docker logs gitea-container-name
  2. Test with minimal setup (single test student)
  3. Consult Gitea documentation
  4. Reach out to workshop repository maintainers

Good luck with your workshop! The multiplayer module is where Git skills really come alive.