40+ modular Git exercises with automated validation using pytest and git-autograder.
Exercise types:
- Standard exercises (40+ directories): Complete with download.py, verify.py, test_verify.py, README.md, res/
- Hands-on scripts (hands_on/): Single-file demonstrations without validation
Shared utilities (exercise_utils/): git.py, github_cli.py, cli.py, file.py, gitmastery.py, test.py
exercise-development: Creating exercises (standard vs hands-on)
- References: exercise-utils, coding standards
- Use for: implementing download.py, verify.py, test_verify.py, README.md
exercise-utils: Utility modules API reference
- Standalone: git, github_cli, cli, file, gitmastery, test utilities
- Never use raw subprocess calls
./new.sh # Create exercise/hands-on (interactive)
./test.sh <exercise> # Test one exercise
pytest . -s -vv # Test all
ruff format . && ruff check . # Format & lintStyle: 88 char lines, 4 spaces, double quotes, 2 blank lines between functions
Naming:
- Functions/Variables: snake_case
- Constants: UPPER_SNAKE_CASE
- Classes: PascalCase
- Directories: kebab-case
Type hints: Required on all function signatures
Imports: Order: stdlib, third-party, local (blank lines between)
Common mistakes:
- Don't call git directly, use exercise_utils/git.py
- Don't forget create_start_tag() at end of download.py
- Don't hardcode paths, use Path(file).parent
- Don't create tests without test_ prefix
Pre-commit: Run ruff format, ruff check, mypy, and ./test.sh
- Create "exercise discussion" GitHub issue
- Wait for approval
- Use ./new.sh to scaffold
- Implement files
- Test thoroughly
- Submit PR referencing approved issue
Python 3.13+, pytest, git-autograder 6.*, repo-smith, ruff, mypy, Git CLI, GitHub CLI (gh)