From e68b6f445a325327813b50cc098868c231f725a8 Mon Sep 17 00:00:00 2001 From: ced4568 Date: Wed, 26 Aug 2026 17:08:00 -0500 Subject: [PATCH] feat(root03): author Git & Collaborative Development MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds all 6 ROOT 03 modules (why version control exists, the Git mental model, everyday Git, branching & merging, remote repositories, engineering Git workflow) — 31 activities. Uses only real LOCAL Git repositories throughout — no Gitea account, no network access, and no RootNode-canonical-repo credential is ever needed or exposed in a student Lab (docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md §4). Modules 1, 2, and 6 are conceptual bookends with no lab, matching the flexible readiness standard already used in ROOT 01/02. Adds 3 new hands-on Git scenarios plus 2 MCQs: git-everyday-basics (init/add/commit, validated by inspecting real `git log`/`git show` state, not just command output strings — Step 6's explicit requirement), git-branching-and-merge (a REAL merge conflict caused on purpose by two branches editing the same line, resolved by the student, validated by confirming the conflict markers are gone and a real two-parent merge commit exists), and git-remote-clone-push (a real local bare repository standing in for a remote — clone/commit/push validated by inspecting the REMOTE side directly, not just the student's own clone). All tested end-to-end via the real scenario-validation API, including negative tests. Wires rootnode-git-fundamentals-assessment (2 required + 3 random-draw scenarios) using the existing Phase 3B assessment engine. Co-Authored-By: Claude Sonnet 5 --- .../01-lesson-why-version-control-exists.md | 40 ++++++ .../02-knowledge-check.md | 31 +++++ .../03-reflection.md | 25 ++++ .../01-lesson-git-mental-model.md | 59 +++++++++ ...tion-watching-a-file-move-between-areas.md | 55 ++++++++ .../03-knowledge-check.md | 36 +++++ ...4-guided-exercise-predicting-git-status.md | 31 +++++ .../m02-git-mental-model/05-reflection.md | 25 ++++ .../01-lesson-everyday-git.md | 70 ++++++++++ ...2-demonstration-the-full-everyday-cycle.md | 56 ++++++++ .../m03-everyday-git/03-knowledge-check.md | 39 ++++++ ...04-guided-exercise-planning-your-commit.md | 32 +++++ .../m03-everyday-git/05-reflection.md | 24 ++++ .../01-lesson-branching-and-merging.md | 62 +++++++++ ...demonstration-a-conflict-happening-live.md | 61 +++++++++ .../03-knowledge-check.md | 36 +++++ ...4-guided-exercise-choosing-a-resolution.md | 36 +++++ .../05-reflection.md | 26 ++++ .../01-lesson-remote-repositories.md | 56 ++++++++ .../02-demonstration-clone-commit-push.md | 56 ++++++++ .../03-knowledge-check.md | 40 ++++++ .../04-guided-exercise-fetch-vs-pull.md | 30 +++++ .../m05-remote-repositories/05-reflection.md | 24 ++++ .../01-lesson-engineering-git-workflow.md | 54 ++++++++ ...emonstration-a-bad-commit-vs-a-good-one.md | 47 +++++++ .../03-knowledge-check.md | 32 +++++ .../04-reflection.md | 30 +++++ ...e_root03_git_collaborative_development.sql | 123 ++++++++++++++++++ scenarios/data/git-branching-and-merge.json | 44 +++++++ scenarios/data/git-diverged-branches-mcq.json | 22 ++++ scenarios/data/git-everyday-basics.json | 34 +++++ scenarios/data/git-remote-clone-push.json | 35 +++++ scenarios/data/git-staging-area-mcq.json | 22 ++++ 33 files changed, 1393 insertions(+) create mode 100644 content/root/root-03-git-collaborative-development/m01-why-version-control-exists/01-lesson-why-version-control-exists.md create mode 100644 content/root/root-03-git-collaborative-development/m01-why-version-control-exists/02-knowledge-check.md create mode 100644 content/root/root-03-git-collaborative-development/m01-why-version-control-exists/03-reflection.md create mode 100644 content/root/root-03-git-collaborative-development/m02-git-mental-model/01-lesson-git-mental-model.md create mode 100644 content/root/root-03-git-collaborative-development/m02-git-mental-model/02-demonstration-watching-a-file-move-between-areas.md create mode 100644 content/root/root-03-git-collaborative-development/m02-git-mental-model/03-knowledge-check.md create mode 100644 content/root/root-03-git-collaborative-development/m02-git-mental-model/04-guided-exercise-predicting-git-status.md create mode 100644 content/root/root-03-git-collaborative-development/m02-git-mental-model/05-reflection.md create mode 100644 content/root/root-03-git-collaborative-development/m03-everyday-git/01-lesson-everyday-git.md create mode 100644 content/root/root-03-git-collaborative-development/m03-everyday-git/02-demonstration-the-full-everyday-cycle.md create mode 100644 content/root/root-03-git-collaborative-development/m03-everyday-git/03-knowledge-check.md create mode 100644 content/root/root-03-git-collaborative-development/m03-everyday-git/04-guided-exercise-planning-your-commit.md create mode 100644 content/root/root-03-git-collaborative-development/m03-everyday-git/05-reflection.md create mode 100644 content/root/root-03-git-collaborative-development/m04-branching-and-merging/01-lesson-branching-and-merging.md create mode 100644 content/root/root-03-git-collaborative-development/m04-branching-and-merging/02-demonstration-a-conflict-happening-live.md create mode 100644 content/root/root-03-git-collaborative-development/m04-branching-and-merging/03-knowledge-check.md create mode 100644 content/root/root-03-git-collaborative-development/m04-branching-and-merging/04-guided-exercise-choosing-a-resolution.md create mode 100644 content/root/root-03-git-collaborative-development/m04-branching-and-merging/05-reflection.md create mode 100644 content/root/root-03-git-collaborative-development/m05-remote-repositories/01-lesson-remote-repositories.md create mode 100644 content/root/root-03-git-collaborative-development/m05-remote-repositories/02-demonstration-clone-commit-push.md create mode 100644 content/root/root-03-git-collaborative-development/m05-remote-repositories/03-knowledge-check.md create mode 100644 content/root/root-03-git-collaborative-development/m05-remote-repositories/04-guided-exercise-fetch-vs-pull.md create mode 100644 content/root/root-03-git-collaborative-development/m05-remote-repositories/05-reflection.md create mode 100644 content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/01-lesson-engineering-git-workflow.md create mode 100644 content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/02-demonstration-a-bad-commit-vs-a-good-one.md create mode 100644 content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/03-knowledge-check.md create mode 100644 content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/04-reflection.md create mode 100644 platform/api/migrations/027_phase6e_root03_git_collaborative_development.sql create mode 100644 scenarios/data/git-branching-and-merge.json create mode 100644 scenarios/data/git-diverged-branches-mcq.json create mode 100644 scenarios/data/git-everyday-basics.json create mode 100644 scenarios/data/git-remote-clone-push.json create mode 100644 scenarios/data/git-staging-area-mcq.json diff --git a/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/01-lesson-why-version-control-exists.md b/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/01-lesson-why-version-control-exists.md new file mode 100644 index 0000000..4ce240e --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/01-lesson-why-version-control-exists.md @@ -0,0 +1,40 @@ +# Why Version Control Exists + +## The problem: `final.txt`, `final_v2.txt`, `final_v2_ACTUALLY_FINAL.txt` + +Before version control, "keeping history" usually meant copying a file with a new name every +time something changed. This fails fast: you lose track of WHAT changed between versions, WHO +changed it, and WHY — and it gets completely unworkable the moment more than one person touches +the same project. + +## What version control actually gives you + +- **History** — every change, in order, permanently. You can see exactly what a file looked + like at any point in the past. +- **Reproducibility** — you can recreate the EXACT state of an entire project at any past + moment, not just one file. +- **Collaboration** — multiple people can work on the same project without emailing files back + and forth or overwriting each other's work. +- **A source of truth** — one authoritative history everyone agrees is correct, instead of + "whoever has the newest-looking filename." +- **Rollback** — if a change turns out to be wrong, you can return to a known-good prior state + with confidence, not by hoping you kept a backup copy somewhere. + +## Why copying files isn't version control + +Copying `app.py` to `app_backup.py` before making a risky change LOOKS like version control, but +it has none of version control's real properties: no record of WHY the change was made, no way +to see incremental history, no way to combine two people's simultaneous edits, and no +scalability past a handful of files. Git (and version control generally) tracks CHANGES over +time as a structured history, not disconnected snapshots you have to manually manage. + +## Instructor Notes + +**Lesson goal:** Motivate Git before teaching a single command — students should feel the real +problem (the `final_v2_ACTUALLY_FINAL.txt` pattern) before the solution makes sense. + +**Approximate timing:** 10 minutes read; 8 minutes live. + +**Discussion question:** "Has anyone ever lost work, or overwritten someone else's work, because +of exactly this kind of file-copying problem?" (Real personal stories land this lesson far +better than abstract description.) diff --git a/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/02-knowledge-check.md b/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/02-knowledge-check.md new file mode 100644 index 0000000..8930b15 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/02-knowledge-check.md @@ -0,0 +1,31 @@ +# Knowledge Check: Why Version Control Exists + +--- + +**1. Name three real properties version control gives you that copying files as backups +doesn't.** + +*Answer:* Any three of: structured history of every change, reproducibility of exact past +states, real collaboration between multiple people, a single agreed-upon source of truth, +confident rollback to a known-good state. + +--- + +**2. Why does `final_v2_ACTUALLY_FINAL.txt` fail as a version-control strategy?** + +*Answer:* It has no record of what changed or why between versions, doesn't scale past a +handful of files, and provides no way to merge two people's simultaneous changes. + +--- + +**3. What does "source of truth" mean in the context of version control?** + +*Answer:* One authoritative, agreed-upon history of a project that everyone treats as +correct — as opposed to ambiguity over which copy or filename is the "real" current version. + +## Instructor Notes + +**Facilitation:** Keep this brief — it's checking motivation/vocabulary before the hands-on +modules begin, not testing depth yet. + +**Approximate timing:** 4 minutes. diff --git a/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/03-reflection.md b/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/03-reflection.md new file mode 100644 index 0000000..3d537b5 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m01-why-version-control-exists/03-reflection.md @@ -0,0 +1,25 @@ +# Reflection: Naming the Problem You're About to Solve + +## Reflection questions + +1. Have you personally ever lost work, or been confused about which file version was current, + in a way version control would have prevented? +2. What do you expect to feel DIFFERENT about how you work once you have real history and + rollback available? + +## Real Ops takeaway + +**Every engineering practice this program builds toward — code review, CI/CD, GitOps, +infrastructure as code — assumes version control as its foundation.** You cannot meaningfully +automate deployment, review changes before they ship, or declare infrastructure as code without +first having a reliable, structured history of what changed and when. This module named the +problem; the rest of ROOT 03 gives you the tool. + +This module is complete. Continue to the next module. + +## Instructor Notes + +**Discussion questions for a live classroom:** question 1 tends to produce genuine, motivating +stories — let students share before moving to Module 2's mental model. + +**Approximate timing:** 5 minutes live discussion; 3 minutes self-paced writing. diff --git a/content/root/root-03-git-collaborative-development/m02-git-mental-model/01-lesson-git-mental-model.md b/content/root/root-03-git-collaborative-development/m02-git-mental-model/01-lesson-git-mental-model.md new file mode 100644 index 0000000..1f39174 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m02-git-mental-model/01-lesson-git-mental-model.md @@ -0,0 +1,59 @@ +# Git Mental Model + +## Three places your files can be + +Git tracks your project through three distinct areas, and understanding this model is what +makes every Git command make sense — memorizing commands without it just produces confusion the +first time something doesn't behave as expected. + +``` +Working Tree → Staging Area → Repository (commit history) +(your actual (what you've (permanent, + files, as you marked ready recorded + edit them) to commit) snapshots) +``` + +- **Working tree** — the actual files on disk, exactly as you're editing them right now. +- **Staging area** (also called "the index") — a holding area for changes you've deliberately + marked as ready to be committed. This is Git's most distinctive design choice: you don't + commit "everything that changed," you commit "exactly what you staged." +- **Repository** — the permanent, recorded history of every commit ever made — this is what + `git log` shows you. + +## Why `git add` exists at all + +A change starts in your working tree. `git add ` moves it (conceptually — the mechanics +are more subtle, but this framing is enough for now) into the staging area. `git commit` takes +EVERYTHING currently staged and permanently records it as a new snapshot in the repository's +history. This two-step process (stage, then commit) exists so you can build up a commit +DELIBERATELY — staging exactly the related changes that belong together, even if your working +tree currently has other, unrelated changes you're not ready to commit yet. + +## Core vocabulary + +- **Commit** — one permanently recorded snapshot, with a message describing what changed and + why, and a unique identifier (a hash). +- **Branch** — a movable pointer to a specific commit, letting you develop something (a + "feature branch") without affecting the main line of history until you're ready to combine it + back in (Module 4). +- **HEAD** — Git's pointer to "which commit you're currently looking at" — almost always the + tip of whichever branch you have checked out. +- **Remote** — a reference to another copy of the same repository, usually hosted somewhere else + (Module 5). + +## Instructor Notes + +**Lesson goal:** Establish the three-area model BEFORE any commands — same "model before syntax" +pedagogy as ROOT 01's process model and ROOT 05's Kubernetes mental model. Every subsequent Git +command should be explainable in terms of moving something between these three areas. + +**Approximate timing:** 15 minutes read; 10 minutes live, ideally with a literal diagram drawn +live (whiteboard or shared screen) showing files moving between the three areas. + +**Common misconception to watch for:** assuming `git commit` commits every changed file +automatically — this is the single most common Git surprise for beginners, and it's exactly +what Module 3's Lab will make concrete. + +**Discussion question:** "Why would you ever WANT to stage only some of your changes, not all +of them?" (Answer: to build one commit about ONE logical change, even if your working tree +currently has several unrelated edits in progress.) diff --git a/content/root/root-03-git-collaborative-development/m02-git-mental-model/02-demonstration-watching-a-file-move-between-areas.md b/content/root/root-03-git-collaborative-development/m02-git-mental-model/02-demonstration-watching-a-file-move-between-areas.md new file mode 100644 index 0000000..dadf06d --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m02-git-mental-model/02-demonstration-watching-a-file-move-between-areas.md @@ -0,0 +1,55 @@ +# Demonstration: Watching a File Move Between the Three Areas + +## OBSERVE + +``` +$ echo "draft" > report.txt +$ git status --short +?? report.txt +``` + +`??` means: Git sees this file, but it's in neither the staging area nor the repository yet — +purely in the working tree. + +## HYPOTHESIS + +Predict what `git status` will show after `git add report.txt`. + +## INSPECT + +``` +$ git add report.txt +$ git status --short +A report.txt +``` + +`A` (in the LEFT column, which represents the staging area) means: staged, ready to commit. + +## CHANGE + +``` +$ git commit -m "Add report draft" +$ git status --short +(nothing — clean) +``` + +## VERIFY + +``` +$ git log --oneline -1 +a1b2c3d Add report draft +``` + +The file traveled through all three areas exactly as the model predicts: working tree (`??`) → +staging area (`A`) → repository (a permanent commit in `git log`). + +## Instructor Notes + +**Demo goal:** Make `git status`'s output legible by directly connecting its symbols (`??`, `A`, +clean) to the three-area model just taught, rather than treating them as arbitrary codes to +memorize. + +**Approximate timing:** 8 minutes live. + +**Common mistake to watch for:** students reading `git status` output without connecting it +back to WHICH of the three areas each symbol refers to — reinforce the mapping explicitly. diff --git a/content/root/root-03-git-collaborative-development/m02-git-mental-model/03-knowledge-check.md b/content/root/root-03-git-collaborative-development/m02-git-mental-model/03-knowledge-check.md new file mode 100644 index 0000000..fd6eb84 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m02-git-mental-model/03-knowledge-check.md @@ -0,0 +1,36 @@ +# Knowledge Check: Git Mental Model + +--- + +**1. Name the three areas a file passes through, in order.** + +*Answer:* Working tree → staging area → repository (commit history). + +--- + +**2. What does `git add` actually do, in terms of this model?** + +*Answer:* Moves a change from the working tree into the staging area — marking it as ready to +be included in the next commit. + +--- + +**3. If you edit three files but only `git add` one of them, what happens when you `git +commit`?** + +*Answer:* Only the staged file is included in the new commit — the other two edited-but-unstaged +files remain as uncommitted changes in the working tree. + +--- + +**4. What is HEAD?** + +*Answer:* Git's pointer to the commit you're currently looking at — almost always the tip of +whichever branch you have checked out. + +## Instructor Notes + +**Facilitation:** Question 3 is the single most important check in this module — if students +get this wrong, revisit the diagram before continuing to Module 3. + +**Approximate timing:** 5 minutes. diff --git a/content/root/root-03-git-collaborative-development/m02-git-mental-model/04-guided-exercise-predicting-git-status.md b/content/root/root-03-git-collaborative-development/m02-git-mental-model/04-guided-exercise-predicting-git-status.md new file mode 100644 index 0000000..48fb717 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m02-git-mental-model/04-guided-exercise-predicting-git-status.md @@ -0,0 +1,31 @@ +# Guided Exercise: Predict `git status` Before You See It + +This is a paper exercise — commit to a prediction before checking it in the Lab. + +## Your task + +Starting from a clean repository (nothing staged, nothing modified), predict what `git status +--short` would show after EACH of these actions, in sequence: + +1. `echo "v1" > file.txt` (a brand new file) +2. `git add file.txt` +3. `echo "v2" >> file.txt` (modifying the ALREADY-STAGED file further) +4. `git commit -m "Add file"` + +## A worked shape to check yourself against + +1. `?? file.txt` — untracked, in the working tree only. +2. `A file.txt` — staged (left column). +3. `AM file.txt` — this is the surprising one: staged (`A`, left column) AND modified again + since staging (`M`, right column) — the staging area has a SNAPSHOT from step 2, and your + further edit in step 3 hasn't been staged yet. +4. Clean (nothing) — but only the STAGED version (from step 2, without the step-3 edit) actually + got committed; the step-3 edit remains as an uncommitted modification afterward. + +## Instructor Notes + +**Facilitation:** Item 3 is deliberately the hardest — it's the exact scenario that surprises +real beginners ("I thought I already staged this file, why does it show changes again?"). Worth +slowing down on. + +**Approximate timing:** 10-12 minutes live discussion; 8 minutes self-paced. diff --git a/content/root/root-03-git-collaborative-development/m02-git-mental-model/05-reflection.md b/content/root/root-03-git-collaborative-development/m02-git-mental-model/05-reflection.md new file mode 100644 index 0000000..cdf06a0 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m02-git-mental-model/05-reflection.md @@ -0,0 +1,25 @@ +# Reflection: The Model Explains the Commands, Not the Other Way Around + +## Reflection questions + +1. Before this module, would `git add` before `git commit` have seemed like an unnecessary + extra step? Why does it actually matter now? +2. Which of the three areas (working tree, staging, repository) do you feel least confident + distinguishing? What would help solidify it? + +## Real Ops takeaway + +**Every Git confusion you'll ever hit traces back to one of these three areas.** "Why isn't my +change in the commit," "why does `git status` show something weird," "why did my commit include +something I didn't mean to" — all of them are answerable by asking "which of the three areas is +this change actually in right now?" You now have that question available; Module 3 makes it +muscle memory. + +This module is complete. Continue to the next module. + +## Instructor Notes + +**Discussion questions for a live classroom:** question 2 is worth a quick poll — knowing where +the class is least confident tells you where to slow down in Module 3's hands-on Lab. + +**Approximate timing:** 5-8 minutes live discussion; 5 minutes self-paced writing. diff --git a/content/root/root-03-git-collaborative-development/m03-everyday-git/01-lesson-everyday-git.md b/content/root/root-03-git-collaborative-development/m03-everyday-git/01-lesson-everyday-git.md new file mode 100644 index 0000000..05bc2f5 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m03-everyday-git/01-lesson-everyday-git.md @@ -0,0 +1,70 @@ +# Everyday Git + +## The commands you'll actually use constantly + +Module 2 gave you the model. This module gives you the six commands that make up the vast +majority of real, everyday Git usage. + +## `git init` — start tracking a project + +``` +$ git init +``` + +Creates a new, empty repository in the current directory (a hidden `.git` folder holds +everything). You only run this ONCE per project, at the very beginning. + +## `git status` — where do things stand right now? + +Shows what's staged, what's modified-but-unstaged, and what's untracked — the single most +useful command for orienting yourself, and one you'll run constantly, almost reflexively, +before and after almost every other Git command. + +## `git add` — stage a change + +``` +$ git add file.txt # stage one specific file +$ git add . # stage everything currently changed +``` + +## `git commit` — permanently record what's staged + +``` +$ git commit -m "Add configuration loader" +``` + +A good commit message describes WHAT changed and, ideally, WHY — future-you (or a teammate) +reading `git log` months later should understand the change without re-reading the entire diff. + +## `git log` — see the history + +``` +$ git log --oneline +a1b2c3d Add configuration loader +9f8e7d6 Initial commit +``` + +## `git diff` — see exactly what changed, before you commit it + +``` +$ git diff # unstaged changes vs. the last commit +$ git diff --staged # staged changes vs. the last commit +``` + +Reading your own diff before committing is one of the highest-value habits in this entire +course — catching an accidental leftover debug line, or a change you didn't mean to include, +BEFORE it becomes a permanent part of history. + +## Instructor Notes + +**Lesson goal:** Convert Module 2's model into the six commands used in nearly every real Git +session — this is the fluency floor for everything that follows in ROOT 03. + +**Approximate timing:** 15 minutes read; 10 minutes live. + +**Common misconception to watch for:** treating `git add .` as always safe — it stages +EVERYTHING changed, including files you might not have intended to include; `git status` before +`git add .` is the habit that prevents this. + +**Demo idea:** run the full init→status→add→commit→log→diff sequence live, narrating `git +status`'s changing output at each step. diff --git a/content/root/root-03-git-collaborative-development/m03-everyday-git/02-demonstration-the-full-everyday-cycle.md b/content/root/root-03-git-collaborative-development/m03-everyday-git/02-demonstration-the-full-everyday-cycle.md new file mode 100644 index 0000000..742f7a4 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m03-everyday-git/02-demonstration-the-full-everyday-cycle.md @@ -0,0 +1,56 @@ +# Demonstration: The Full Cycle, End to End + +## OBSERVE + +``` +$ git init +$ git status --short +(nothing — empty repository) +``` + +## HYPOTHESIS + +Predict what happens to `git status` after creating a new file. + +## INSPECT + +``` +$ echo "v1" > app.py +$ git status --short +?? app.py +``` + +## CHANGE + +``` +$ git add app.py +$ git diff --staged ++v1 +$ git commit -m "Add initial app.py" +``` + +`git diff --staged` shows exactly what's ABOUT to be committed — a real, final check before it +becomes permanent. + +## VERIFY + +``` +$ git log --oneline +3f9a1c2 Add initial app.py +$ git status --short +(clean) +``` + +The complete cycle, verified with real evidence at each step — not "I think I committed it," +but confirmed via `git log`. + +## Instructor Notes + +**Demo goal:** Show `git diff --staged` as the final safety check before a commit becomes +permanent — a habit worth building explicitly, not just mentioning in passing. + +**Approximate timing:** 8 minutes live. + +**Common mistake to watch for:** skipping `git diff`/`git diff --staged` entirely and committing +on faith — a good moment to ask "how would you know if you accidentally staged the wrong +thing?" diff --git a/content/root/root-03-git-collaborative-development/m03-everyday-git/03-knowledge-check.md b/content/root/root-03-git-collaborative-development/m03-everyday-git/03-knowledge-check.md new file mode 100644 index 0000000..7ec1245 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m03-everyday-git/03-knowledge-check.md @@ -0,0 +1,39 @@ +# Knowledge Check: Everyday Git + +--- + +**1. What's the difference between `git diff` and `git diff --staged`?** + +*Answer:* `git diff` shows unstaged changes (working tree vs. last commit); `git diff --staged` +shows what's currently staged and about to be committed (staging area vs. last commit). + +--- + +**2. Why is `git add .` potentially risky compared to `git add `?** + +*Answer:* It stages EVERYTHING currently changed in the directory, which can accidentally +include files you didn't mean to commit — checking `git status` first (or using targeted `git +add`) avoids this. + +--- + +**3. What makes a commit message actually useful months later?** + +*Answer:* Describing WHAT changed and ideally WHY, clearly enough that someone (including +future-you) reading `git log` understands the change without re-reading the full diff. + +--- + +**4. You run `git init` in a directory that already has an existing Git repository. What +happens?** + +*Answer:* `git init` only needs to run once per project — running it again in an already- +initialized repository is harmless (it won't destroy existing history) but is never actually +necessary. + +## Instructor Notes + +**Facilitation:** Question 2 is a good moment to establish "check status before staging broadly" +as a house habit for the rest of the course. + +**Approximate timing:** 5 minutes. diff --git a/content/root/root-03-git-collaborative-development/m03-everyday-git/04-guided-exercise-planning-your-commit.md b/content/root/root-03-git-collaborative-development/m03-everyday-git/04-guided-exercise-planning-your-commit.md new file mode 100644 index 0000000..4f8fd0b --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m03-everyday-git/04-guided-exercise-planning-your-commit.md @@ -0,0 +1,32 @@ +# Guided Exercise: Plan a Real Commit Before You Make It + +This is a paper exercise — commit to a plan before working in the Lab. + +## Your task + +You've made three unrelated changes to your working tree: fixed a typo in `README.md`, added a +new function to `utils.py`, and started (but not finished) an unrelated experiment in +`scratch.py` you're not ready to commit. Write out the exact sequence of commands you'd use to +end up with exactly ONE clean commit containing the README typo fix, leaving the other two files +alone. + +## A worked shape to check yourself against + +``` +git status +git add README.md +git diff --staged +git commit -m "Fix typo in README" +git status +``` + +The key insight: `git add` lets you choose EXACTLY what goes into the next commit, regardless of +what else is sitting, unstaged, in your working tree — `utils.py` and `scratch.py` remain +untouched and uncommitted. + +## Instructor Notes + +**Facilitation:** This exercise directly tests whether Module 2's staging-area model actually +stuck — if students reach for `git add .`, that's a sign to revisit the model before the Lab. + +**Approximate timing:** 8-10 minutes live discussion; 5 minutes self-paced. diff --git a/content/root/root-03-git-collaborative-development/m03-everyday-git/05-reflection.md b/content/root/root-03-git-collaborative-development/m03-everyday-git/05-reflection.md new file mode 100644 index 0000000..6dbbfcb --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m03-everyday-git/05-reflection.md @@ -0,0 +1,24 @@ +# Reflection: You Have Real, Permanent History Now + +## Reflection questions + +1. Look at your own `git log` from this module's Lab. Is your commit message something a + stranger (or future-you) could understand without more context? +2. Which of the six commands from this module do you expect to type the most, going forward? + +## Real Ops takeaway + +**A real, permanent, inspectable history of your work now exists — this is the actual thing +Module 1 named as missing from copy-a-file-as-backup.** Every commit you make from here on is +recoverable, comparable, and explainable. Module 4 builds on this by letting multiple lines of +work (branches) develop independently before combining — impossible without the reliable +history you just built the habit of creating. + +This module is complete. Continue to the next module. + +## Instructor Notes + +**Discussion questions for a live classroom:** question 1 works well as a peer-review pass — +have students read a neighbor's commit message and guess what it changed, then compare. + +**Approximate timing:** 5-8 minutes live discussion; 5 minutes self-paced writing. diff --git a/content/root/root-03-git-collaborative-development/m04-branching-and-merging/01-lesson-branching-and-merging.md b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/01-lesson-branching-and-merging.md new file mode 100644 index 0000000..8e197b2 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/01-lesson-branching-and-merging.md @@ -0,0 +1,62 @@ +# Branching and Merging + +## Why branches exist + +Without branches, every commit happens on the same single line of history — risky work and +finished work are indistinguishable, and two people can't develop different things +simultaneously without directly interfering with each other. A **branch** is a movable pointer +to a commit, letting you develop something in isolation and only combine it back into the main +line when it's actually ready. + +## Creating and switching branches + +``` +$ git branch feature-login # create a new branch (doesn't switch to it) +$ git checkout feature-login # switch to it +$ git switch feature-login # the newer, clearer equivalent of checkout for this purpose +$ git checkout -b feature-login # create AND switch in one step +``` + +Commits made while on `feature-login` only affect that branch — `main` is completely unaffected +until you deliberately combine them. + +## Merging: combining two branches' history + +``` +$ git checkout main +$ git merge feature-login +``` + +Git attempts to combine the two branches' history automatically. When the two branches changed +DIFFERENT parts of a project, this usually succeeds with no fuss. + +## Divergence and conflicts + +When both branches changed the SAME lines of the SAME file differently, Git can't automatically +decide which version is correct — this is a **merge conflict**. Git marks the conflicting +section directly in the file: + +``` +<<<<<<< HEAD +your current branch's version +======= +the incoming branch's version +>>>>>>> feature-login +``` + +A conflict is not an error you did something wrong — it's Git correctly refusing to silently +guess which change you actually want. You resolve it by editing the file to the content you +actually want (removing the markers), then staging and committing to complete the merge. + +## Instructor Notes + +**Lesson goal:** Frame merge conflicts as an EXPECTED, normal part of collaborative work — not +a sign of failure — before students hit their first real one in this module's Lab. + +**Approximate timing:** 15 minutes read; 10 minutes live. + +**Common misconception to watch for:** panicking at the sight of conflict markers — reinforce +explicitly that this is Git behaving correctly, not breaking. + +**Demo idea:** deliberately narrate a conflict as "Git is asking YOU to make a decision it +can't make safely on its own" rather than "something went wrong." diff --git a/content/root/root-03-git-collaborative-development/m04-branching-and-merging/02-demonstration-a-conflict-happening-live.md b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/02-demonstration-a-conflict-happening-live.md new file mode 100644 index 0000000..c518b2d --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/02-demonstration-a-conflict-happening-live.md @@ -0,0 +1,61 @@ +# Demonstration: A Conflict, Caused and Resolved on Purpose + +## OBSERVE + +Two branches both changed line 1 of `config.txt` — `main` to `"env=production"`, `feature` to +`"env=staging"`. + +## HYPOTHESIS + +Predict what `git merge feature` will do. + +## INSPECT + +``` +$ git merge feature +Auto-merging config.txt +CONFLICT (content): Merge conflict in config.txt +Automatic merge failed; fix conflicts and then commit the result. +``` + +Exactly as predicted — Git refuses to guess. + +## CHANGE + +``` +$ cat config.txt +<<<<<<< HEAD +env=production +======= +env=staging +>>>>>>> feature +``` + +Decide the real answer — here, say `env=production` is correct — and edit the file to exactly +that, deleting all three marker lines. + +## VERIFY + +``` +$ git add config.txt +$ git commit -m "Merge feature, keep production config" +$ git log --oneline --graph +* a1b2c3d Merge feature, keep production config +|\ +| * 9f8e7d6 Update from feature +* | 3d2c1b0 Update from main +|/ +* 0a1b2c3 Initial commit +``` + +The graph shows exactly what happened: two lines of history, deliberately combined. + +## Instructor Notes + +**Demo goal:** Walk a real conflict from cause to resolution without skipping any step, +reinforcing that resolution means making an explicit CHOICE, not applying a trick. + +**Approximate timing:** 10 minutes live. + +**Common mistake to watch for:** leaving conflict markers accidentally in the "resolved" file +(easy to miss one) — `grep '<<<<<<<' file` before committing catches this reliably. diff --git a/content/root/root-03-git-collaborative-development/m04-branching-and-merging/03-knowledge-check.md b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/03-knowledge-check.md new file mode 100644 index 0000000..14e5fda --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/03-knowledge-check.md @@ -0,0 +1,36 @@ +# Knowledge Check: Branching and Merging + +--- + +**1. What is a branch, really?** + +*Answer:* A movable pointer to a specific commit — not a copy of the whole project, just a +reference letting you develop independently from other branches. + +--- + +**2. Why does a merge conflict happen?** + +*Answer:* Both branches changed the SAME lines of the SAME file differently, and Git can't +safely guess which version you actually want — so it stops and asks you to decide. + +--- + +**3. Is a merge conflict a sign something went wrong?** + +*Answer:* No — it's Git correctly refusing to silently guess at a decision only a human should +make. It's a normal, expected part of collaborative work. + +--- + +**4. After resolving a conflict by editing the file, what two steps complete the merge?** + +*Answer:* Stage the resolved file (`git add`) and commit (`git commit`) — exactly like +completing any other commit, once the conflict markers are gone. + +## Instructor Notes + +**Facilitation:** Question 3 is worth stating explicitly and repeating — reframing conflicts +as normal, not scary, meaningfully changes how confidently students approach this module's Lab. + +**Approximate timing:** 5 minutes. diff --git a/content/root/root-03-git-collaborative-development/m04-branching-and-merging/04-guided-exercise-choosing-a-resolution.md b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/04-guided-exercise-choosing-a-resolution.md new file mode 100644 index 0000000..4b98525 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/04-guided-exercise-choosing-a-resolution.md @@ -0,0 +1,36 @@ +# Guided Exercise: Decide the Resolution Before You Touch the File + +This is a paper exercise — commit to a decision before resolving anything in the Lab. + +## Your task + +A merge conflict shows: + +``` +<<<<<<< HEAD +timeout_seconds = 30 +======= +timeout_seconds = 120 +>>>>>>> feature +``` + +You know `main`'s value (30) was set deliberately for production safety, but `feature`'s value +(120) was added while debugging a slow endpoint that genuinely needs more time. Write out: what +final content would you put in the file, and why is that the RIGHT resolution (not just "pick +one side")? + +## A worked shape to check yourself against + +A well-reasoned resolution here is neither side alone: something like keeping `30` as the +DEFAULT but adding a comment or a separate, more specific setting for the slow endpoint +specifically — the point is that conflict resolution sometimes means genuinely combining intent +from both sides, not mechanically picking `HEAD` or the incoming branch. There's no single +"correct" file content — the value is in justifying whichever choice you make with real +reasoning, not defaulting to whichever side happens to be `HEAD`. + +## Instructor Notes + +**Facilitation:** The point of this exercise is resisting "just pick a side" as a reflex — +some conflicts genuinely require combining or renegotiating intent, not mechanical selection. + +**Approximate timing:** 8-10 minutes live discussion; 5 minutes self-paced. diff --git a/content/root/root-03-git-collaborative-development/m04-branching-and-merging/05-reflection.md b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/05-reflection.md new file mode 100644 index 0000000..f784051 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m04-branching-and-merging/05-reflection.md @@ -0,0 +1,26 @@ +# Reflection: Your First Conflict Wasn't a Disaster + +## Reflection questions + +1. Before this module, how would you have reacted to seeing conflict markers in a real file + for the first time? +2. What made resolving the conflict in this module's Lab feel manageable (or not)? What would + make a REAL conflict, in a large unfamiliar file, harder? + +## Real Ops takeaway + +**Merge conflicts are one of the most feared parts of Git for beginners, and one of the most +routine parts of Git for experienced engineers — the difference is just repetition.** You've now +caused one on purpose, resolved it deliberately, and verified the result — exactly the +experience that turns "conflicts are scary" into "conflicts are Tuesday." Module 5 adds a real +remote to this same workflow; conflicts show up there too, and you're now prepared for them. + +This module is complete. Continue to the next module. + +## Instructor Notes + +**Discussion questions for a live classroom:** question 2 is worth extending into "what would +make a conflict on a 500-line file, with someone else's unfamiliar code, actually hard" — a good +honest preview of real collaborative work. + +**Approximate timing:** 5-8 minutes live discussion; 5 minutes self-paced writing. diff --git a/content/root/root-03-git-collaborative-development/m05-remote-repositories/01-lesson-remote-repositories.md b/content/root/root-03-git-collaborative-development/m05-remote-repositories/01-lesson-remote-repositories.md new file mode 100644 index 0000000..995da13 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m05-remote-repositories/01-lesson-remote-repositories.md @@ -0,0 +1,56 @@ +# Remote Repositories + +## What a remote actually is + +Every repository you've worked with so far has been entirely LOCAL — on this one machine. A +**remote** is a reference to another copy of the same repository, typically hosted somewhere +else (a server, or in this Lab, a second local repository playing that role). Remotes are what +make real collaboration possible: multiple people, multiple machines, all synchronizing through +one shared history. + +## `origin`: a name, not a special concept + +By convention, the remote you cloned FROM is named `origin` — but this is just a label Git +assigns automatically, not a technical requirement. You could name a remote anything; `origin` +is simply the default everyone recognizes. + +## The four remote operations + +- **`git clone `** — copy an ENTIRE remote repository (full history included) to a new + local directory, automatically configuring it as `origin`. +- **`git fetch`** — download the remote's latest commits WITHOUT changing your own working + files or branches — a safe way to see what's new before deciding what to do about it. +- **`git pull`** — fetch AND immediately merge the remote's changes into your current branch — + effectively `fetch` + `merge` in one step (which is exactly why a `pull` can produce a merge + conflict, the same as Module 4's local merges). +- **`git push`** — upload your local commits to the remote, making them visible to everyone else + using that remote. + +## Upstream: your branch's remote counterpart + +A local branch can be configured to TRACK a specific remote branch (its "upstream") — once set, +plain `git pull`/`git push` (no extra arguments) know exactly which remote branch to sync +against, rather than requiring you to specify it every time. + +## RootNode uses Gitea (this course does not) + +RootNode's own engineering team uses Gitea (a self-hosted Git service) for its real work — the +CONCEPTS in this lesson (origin, clone, fetch, pull, push) are identical regardless of which +service hosts a remote (Gitea, GitHub, GitLab, or a private server). This course teaches those +concepts using a disposable LOCAL repository standing in for a remote — no account, no network +access, and no RootNode credentials are ever needed or exposed in this Lab. + +## Instructor Notes + +**Lesson goal:** Teach remotes as a genuine, transferable concept — students should be able to +work with ANY real Git hosting service afterward, not just this Lab's local simulation. + +**Approximate timing:** 15 minutes read; 10 minutes live. + +**Common misconception to watch for:** treating `git pull` as a "safe, no-side-effects" command +— it's a merge, and merges can conflict, exactly like Module 4 taught. + +**Discussion question:** "Why might a team prefer `git fetch` followed by manually reviewing +changes, over always running `git pull` directly?" (Answer: fetch lets you see what changed +before it touches your own working files/branch — useful caution before merging in unfamiliar +changes.) diff --git a/content/root/root-03-git-collaborative-development/m05-remote-repositories/02-demonstration-clone-commit-push.md b/content/root/root-03-git-collaborative-development/m05-remote-repositories/02-demonstration-clone-commit-push.md new file mode 100644 index 0000000..9e3fdbc --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m05-remote-repositories/02-demonstration-clone-commit-push.md @@ -0,0 +1,56 @@ +# Demonstration: A Complete Clone-to-Push Round Trip + +## OBSERVE + +A bare (remote-style) repository already exists, currently empty. + +``` +$ git clone /srv/demo-remote.git /srv/demo-clone +warning: You appear to have cloned an empty repository. +``` + +Cloning an empty remote is completely normal — it just means no commits exist there yet. + +## HYPOTHESIS + +Predict what `git remote -v` will show inside the new clone. + +## INSPECT + +``` +$ cd /srv/demo-clone && git remote -v +origin /srv/demo-remote.git (fetch) +origin /srv/demo-remote.git (push) +``` + +Automatically configured as `origin` — exactly as the lesson described, with no extra setup. + +## CHANGE + +``` +$ echo "# Demo Project" > README.md +$ git add README.md +$ git commit -m "Add README" +$ git push origin main +``` + +## VERIFY + +``` +$ git --git-dir=/srv/demo-remote.git log --oneline +3f9a1c2 Add README +``` + +Checking the REMOTE directly (not the clone) proves the push actually reached it — the commit +now exists in two places, in sync. + +## Instructor Notes + +**Demo goal:** Prove the push actually worked by inspecting the REMOTE side independently, +not just trusting the clone's own `git log`. + +**Approximate timing:** 8 minutes live. + +**Common mistake to watch for:** assuming a successful `git push` with no error message means +success without ever double-checking — worth reinforcing the "verify independently" habit from +earlier ROOT_ modules. diff --git a/content/root/root-03-git-collaborative-development/m05-remote-repositories/03-knowledge-check.md b/content/root/root-03-git-collaborative-development/m05-remote-repositories/03-knowledge-check.md new file mode 100644 index 0000000..c151107 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m05-remote-repositories/03-knowledge-check.md @@ -0,0 +1,40 @@ +# Knowledge Check: Remote Repositories + +--- + +**1. What's the difference between `git fetch` and `git pull`?** + +*Answer:* `git fetch` downloads the remote's new commits without touching your working files or +branches. `git pull` does that AND immediately merges them into your current branch — it's +fetch + merge combined. + +--- + +**2. Why can `git pull` produce a merge conflict?** + +*Answer:* Because it performs a real merge under the hood — if your local branch and the +remote's branch both changed the same lines differently, the same conflict situation from +Module 4 can occur. + +--- + +**3. Is `origin` a required, special name Git enforces?** + +*Answer:* No — it's just the conventional default name Git assigns to the remote you cloned +from. You could name a remote something else; `origin` is a widely recognized convention, not a +technical requirement. + +--- + +**4. Does this course require a GitHub or Gitea account to learn remotes?** + +*Answer:* No — this course uses a disposable local bare repository to safely simulate a real +remote, teaching the same concepts (clone/fetch/pull/push/origin) without any account or network +access. + +## Instructor Notes + +**Facilitation:** Question 2 is worth emphasizing — many students assume `pull` is risk-free +until they hit their first real pull-conflict. + +**Approximate timing:** 5 minutes. diff --git a/content/root/root-03-git-collaborative-development/m05-remote-repositories/04-guided-exercise-fetch-vs-pull.md b/content/root/root-03-git-collaborative-development/m05-remote-repositories/04-guided-exercise-fetch-vs-pull.md new file mode 100644 index 0000000..227145c --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m05-remote-repositories/04-guided-exercise-fetch-vs-pull.md @@ -0,0 +1,30 @@ +# Guided Exercise: Fetch First, Decide Second + +This is a paper exercise — commit to a plan before working in the Lab. + +## Your task + +You're about to sync with a shared remote that a teammate has been actively pushing to all day. +You're not sure what they changed. Write out the SAFER sequence of commands (as opposed to +running `git pull` immediately), and explain what each step lets you verify before your own +working files are touched. + +## A worked shape to check yourself against + +``` +git fetch origin +git log HEAD..origin/main --oneline +``` + +`git fetch` downloads the new commits without touching your branch. The `log` command then +shows you exactly what commits exist on the remote that you don't have locally yet — letting you +review WHAT changed before deciding to merge it in with a subsequent `git merge origin/main` (or +`git pull`, now that you already know roughly what to expect). + +## Instructor Notes + +**Facilitation:** This exercise directly builds the "fetch first, review, then merge" habit +real teams use on shared branches — worth connecting explicitly to why blind `git pull` on a +busy shared branch is a common source of surprise conflicts. + +**Approximate timing:** 8-10 minutes live discussion; 5 minutes self-paced. diff --git a/content/root/root-03-git-collaborative-development/m05-remote-repositories/05-reflection.md b/content/root/root-03-git-collaborative-development/m05-remote-repositories/05-reflection.md new file mode 100644 index 0000000..0f5b5ba --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m05-remote-repositories/05-reflection.md @@ -0,0 +1,24 @@ +# Reflection: You Just Practiced Real Collaboration, Safely + +## Reflection questions + +1. What would have felt different about this module's Lab if the remote were a real hosted + service (Gitea/GitHub) instead of a local simulation? What would have felt the same? +2. Where do you expect `push` to matter most in real engineering work you'll do later? + +## Real Ops takeaway + +**Everything you just practiced — clone, commit, push, verified independently on the remote +side — is the exact mechanism behind CI/CD and GitOps, which ROOT 11 covers later.** A CI +pipeline triggers because someone pushed; a GitOps deployment happens because a change was +pushed to a Git repository treated as the source of truth. You haven't just learned Git commands +— you've practiced the literal trigger mechanism modern deployment automation is built around. + +This module is complete. Continue to the final module of this course. + +## Instructor Notes + +**Discussion questions for a live classroom:** question 2 previews ROOT 11's GitOps content +directly — worth naming that connection explicitly, even without teaching GitOps itself yet. + +**Approximate timing:** 5-8 minutes live discussion; 5 minutes self-paced writing. diff --git a/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/01-lesson-engineering-git-workflow.md b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/01-lesson-engineering-git-workflow.md new file mode 100644 index 0000000..67b98a7 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/01-lesson-engineering-git-workflow.md @@ -0,0 +1,54 @@ +# Engineering Git Workflow + +## Small commits, meaningful messages + +A commit containing "fixed stuff" and 40 unrelated file changes is nearly useless to anyone +reading history later — including future-you. A commit that does ONE logical thing, with a +message describing what and why, is what actually makes `git log` a useful tool rather than +noise. This isn't pedantry — it's what makes rollback (below) and code review actually +practical. + +## `main` as a protected source of truth + +Real engineering teams treat their main branch as the one everyone trusts to be in a working +state at all times — direct, unreviewed pushes to `main` are typically restricted specifically +BECAUSE it's the shared source of truth every deployment and every other branch is built from. +Feature branches (Module 4) exist precisely so risky, in-progress work never threatens that +trust. + +## Review: another set of eyes before history is permanent + +Before a change reaches `main`, most real teams have someone else look at it first (a "pull +request" or "merge request," depending on the platform). This isn't about distrust — it's a +second perspective catching mistakes, and a natural point to discuss WHY a change is being made, +not just what it does. + +## History and rollback as safety nets + +Because every commit is permanent and inspectable, a bad change can be identified precisely (via +`git log`) and reverted deliberately — confident recovery, not panic, when something goes wrong. +This is Module 1's original promise, now fully realized: reproducibility and rollback aren't +theoretical, they're what your daily small-commit discipline actually buys you. + +## Why this matters to DevOps, GitOps, and Infrastructure as Code + +Everything in this lesson — small deliberate changes, a trusted source of truth, review before +merge, reliable history — is EXACTLY what CI/CD pipelines automate, what GitOps treats a Git +repository as authoritative for, and what Infrastructure as Code relies on to safely manage real +infrastructure through the same discipline you just practiced on plain text files. ROOT 11 +builds directly on this course's habits, not a new set of ideas. + +## Instructor Notes + +**Lesson goal:** Close ROOT 03 by explicitly naming the professional discipline (not just Git +commands) this course was building, and its direct connection to DevOps/GitOps/IaC. + +**Approximate timing:** 15 minutes read; 10 minutes live. + +**Common misconception to watch for:** treating "review" and "protecting main" as bureaucratic +overhead rather than genuine risk management — connect it back to the real cost of a bad change +reaching a shared source of truth unreviewed. + +**Discussion question:** "Why might a team enforce small commits and review even when working +alone on a personal project?" (Good answers: future-you benefits from the same clarity; building +the habit now pays off the moment you DO work with others.) diff --git a/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/02-demonstration-a-bad-commit-vs-a-good-one.md b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/02-demonstration-a-bad-commit-vs-a-good-one.md new file mode 100644 index 0000000..60a3691 --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/02-demonstration-a-bad-commit-vs-a-good-one.md @@ -0,0 +1,47 @@ +# Demonstration: The Same Change, Told Two Ways + +## OBSERVE + +``` +$ git log --oneline +a1b2c3d fixed stuff +``` + +One commit, an unhelpful message, and (imagine) 15 unrelated files changed together: a bug fix, +a typo correction, and an unrelated half-finished experiment. + +## HYPOTHESIS + +Predict: six months from now, could you (or a teammate) confidently `git revert` just the bug +fix from this commit, leaving the other 14 files untouched? + +## INSPECT + +No — reverting this ONE commit reverts everything in it together, including the unrelated +typo fix and experiment, whether you want that or not. + +## CHANGE + +The same work, done as three separate, well-described commits instead: + +``` +$ git log --oneline +3f9a1c2 Fix null-pointer crash in payment retry logic +9d8e7f6 Fix typo in onboarding email template +1a2b3c4 WIP: experiment with new caching strategy (not ready) +``` + +## VERIFY + +Now `git revert 3f9a1c2` cleanly undoes JUST the payment bug fix, with zero effect on the other +two — because each commit is one logical, independently-reversible unit of work. + +## Instructor Notes + +**Demo goal:** Make the practical cost of "fixed stuff" commits concrete — not a style +preference, a genuine loss of capability (precise revert, clear history, easier review). + +**Approximate timing:** 8 minutes live. + +**Common mistake to watch for:** treating this as a purely aesthetic preference rather than a +practical one — reinforce the concrete "can you revert just the bug fix" test. diff --git a/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/03-knowledge-check.md b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/03-knowledge-check.md new file mode 100644 index 0000000..e998dad --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/03-knowledge-check.md @@ -0,0 +1,32 @@ +# Knowledge Check: Engineering Git Workflow + +--- + +**1. Why does bundling unrelated changes into one commit cost you something real, not just +style points?** + +*Answer:* It makes precise operations like `git revert` impossible to apply to just ONE logical +change — reverting the commit reverts everything in it together, whether you want that or not. + +--- + +**2. Why do teams typically restrict direct, unreviewed pushes to `main`?** + +*Answer:* `main` is the shared source of truth everything else (deployments, other branches) is +built from — protecting it reduces the chance an unreviewed mistake reaches something everyone +else depends on being trustworthy. + +--- + +**3. Name one concrete way this course's Git discipline connects to GitOps or CI/CD.** + +*Answer:* Any reasonable answer connecting small deliberate changes / a trusted source of truth +/ review-before-merge / reliable history to how CI/CD pipelines trigger on pushes or how GitOps +treats a Git repository as the authoritative record of desired infrastructure state. + +## Instructor Notes + +**Facilitation:** Question 3 is open-ended by design — the goal is students making the +connection in their own words, not reciting a fixed answer. + +**Approximate timing:** 5 minutes. diff --git a/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/04-reflection.md b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/04-reflection.md new file mode 100644 index 0000000..0baf07f --- /dev/null +++ b/content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/04-reflection.md @@ -0,0 +1,30 @@ +# Reflection: You've Practiced Real Engineering Discipline, Not Just Syntax + +## Reflection questions + +1. Look back across all six modules of ROOT 03. Which single habit (small commits, checking + `git status` before staging, fetch-before-pull, resolving conflicts deliberately) do you + think will matter most in real work? +2. This course started with "copying files as backup isn't version control." Can you now + explain, in one sentence, what Git actually gives you that copying never could? + +## Real Ops takeaway + +**Version control discipline is not a Git-specific skill — it's an engineering discipline that +happens to be exercised through Git.** Small deliberate changes, a trusted shared source of +truth, review before permanent history, and confident rollback are the same principles behind +CI/CD, GitOps, and Infrastructure as Code, all covered later in ROOT 11. You are not starting +that content from zero — you already practiced its foundation here. + +This module — and ROOT 03 — is complete. Continue to ROOT 04: Containers & Docker. + +## Instructor Notes + +**Discussion questions for a live classroom:** question 2 is a good closing check — a clear, +confident answer here is real evidence the course's central premise landed. + +**Approximate timing:** 8-10 minutes live discussion; 5 minutes self-paced writing. + +**Milestone note:** this is the last module of ROOT 03 — consider a brief recap connecting all +six modules (why version control → the three-area model → everyday commands → branching/ +conflicts → remotes → professional workflow) before moving to ROOT 04. diff --git a/platform/api/migrations/027_phase6e_root03_git_collaborative_development.sql b/platform/api/migrations/027_phase6e_root03_git_collaborative_development.sql new file mode 100644 index 0000000..09632c3 --- /dev/null +++ b/platform/api/migrations/027_phase6e_root03_git_collaborative_development.sql @@ -0,0 +1,123 @@ +-- Phase 6E — ROOT 03: Git & Collaborative Development. Adds 6 modules/activities under the +-- existing (PLANNED, zero-content) root-03-git-collaborative-development course row. Every lab +-- activity uses real LOCAL git repositories (including a local bare repo standing in for a +-- remote) — no Gitea account, no network access, no RootNode-canonical-repo credential ever +-- reaches a student Lab (docs/ROOT_FOUNDATIONS_LAB_STRATEGY.md §4). Modules 1 and 6 are +-- conceptual bookends with no lab, matching the flexible readiness standard. + +UPDATE courses SET + status = 'ready', + objectives = '{"Explain what version control gives you that copying files never could","Explain the working-tree/staging-area/repository model before memorizing commands","Use init/status/add/commit/log/diff fluently on a real repository","Create a branch, cause a real merge conflict, and resolve it deliberately","Clone, commit, and push to a real remote","Apply small-commit, reviewed, source-of-truth discipline"}', + updated_at = now() +WHERE course_id = 'root-03-git-collaborative-development'; + +INSERT INTO course_modules (module_id, course_id, title, description, sequence, objectives, prerequisites, estimated_duration_minutes, status) VALUES +('root-03-m01-why-version-control-exists', 'root-03-git-collaborative-development', 'Why Version Control Exists', + 'History, reproducibility, collaboration, and rollback — the real problem Git solves, before any command. Target learner: has completed ROOT 02.', + 1, '{"Explain what version control gives you that copying files does not","Explain why copying files as backup fails as a strategy"}', '{}', 20, 'ready'), +('root-03-m02-git-mental-model', 'root-03-git-collaborative-development', 'Git Mental Model', + 'Working tree, staging area, repository — the model that makes every later command make sense. No lab — conceptual mastery via demonstrated reasoning.', + 2, '{"Explain the working-tree/staging-area/repository model","Predict git status output from the model, not memorization"}', '{root-03-m01-why-version-control-exists}', 35, 'ready'), +('root-03-m03-everyday-git', 'root-03-git-collaborative-development', 'Everyday Git', + 'init/status/add/commit/log/diff, against a real local repository.', + 3, '{"Initialize and work in a real Git repository","Stage exactly the changes intended, verify with diff","Write a commit message that explains what and why"}', '{root-03-m02-git-mental-model}', 40, 'ready'), +('root-03-m04-branching-and-merging', 'root-03-git-collaborative-development', 'Branching & Merging', + 'Real branches, a real merge conflict caused on purpose, and deliberate resolution.', + 4, '{"Create and switch between branches","Explain why a merge conflict happens and that it is normal","Resolve a real merge conflict and complete the merge"}', '{root-03-m03-everyday-git}', 45, 'ready'), +('root-03-m05-remote-repositories', 'root-03-git-collaborative-development', 'Remote Repositories', + 'Clone, fetch, pull, push against a real local-bare remote — no account or network required.', + 5, '{"Clone a repository and explain origin","Distinguish fetch from pull and explain why pull can conflict","Push a real commit and verify it independently on the remote"}', '{root-03-m04-branching-and-merging}', 40, 'ready'), +('root-03-m06-engineering-git-workflow', 'root-03-git-collaborative-development', 'Engineering Git Workflow', + 'Small commits, review, protecting main, and the direct bridge to CI/CD/GitOps/IaC. No lab — conceptual closer.', + 6, '{"Explain why small, well-described commits matter beyond style","Explain why teams protect main and require review","Connect this course''s discipline to CI/CD and GitOps"}', '{root-03-m05-remote-repositories}', 30, 'ready') +ON CONFLICT (module_id) DO NOTHING; + +INSERT INTO module_activities (activity_id, module_id, sequence, activity_type, title, content_path, scenario_id, assessment_definition_id, completion_behavior, estimated_duration_minutes, status) VALUES +-- M01 (no lab) +('root-03-m01-a01-lesson', 'root-03-m01-why-version-control-exists', 1, 'lesson', 'Why Version Control Exists', + 'content/root/root-03-git-collaborative-development/m01-why-version-control-exists/01-lesson-why-version-control-exists.md', NULL, NULL, 'manual_marker', 10, 'ready'), +('root-03-m01-a02-knowledge-check', 'root-03-m01-why-version-control-exists', 2, 'knowledge_check', 'Knowledge Check: Why Version Control Exists', + 'content/root/root-03-git-collaborative-development/m01-why-version-control-exists/02-knowledge-check.md', NULL, NULL, 'manual_marker', 4, 'ready'), +('root-03-m01-a03-reflection', 'root-03-m01-why-version-control-exists', 3, 'reflection', 'Reflection: Naming the Problem You''re About to Solve', + 'content/root/root-03-git-collaborative-development/m01-why-version-control-exists/03-reflection.md', NULL, NULL, 'manual_marker', 6, 'ready'), +-- M02 (no lab) +('root-03-m02-a01-lesson', 'root-03-m02-git-mental-model', 1, 'lesson', 'Git Mental Model', + 'content/root/root-03-git-collaborative-development/m02-git-mental-model/01-lesson-git-mental-model.md', NULL, NULL, 'manual_marker', 15, 'ready'), +('root-03-m02-a02-demonstration', 'root-03-m02-git-mental-model', 2, 'demonstration', 'Demonstration: Watching a File Move Between the Three Areas', + 'content/root/root-03-git-collaborative-development/m02-git-mental-model/02-demonstration-watching-a-file-move-between-areas.md', NULL, NULL, 'manual_marker', 8, 'ready'), +('root-03-m02-a03-knowledge-check', 'root-03-m02-git-mental-model', 3, 'knowledge_check', 'Knowledge Check: Git Mental Model', + 'content/root/root-03-git-collaborative-development/m02-git-mental-model/03-knowledge-check.md', NULL, NULL, 'manual_marker', 5, 'ready'), +('root-03-m02-a04-guided-exercise', 'root-03-m02-git-mental-model', 4, 'guided_exercise', 'Guided Exercise: Predict git status Before You See It', + 'content/root/root-03-git-collaborative-development/m02-git-mental-model/04-guided-exercise-predicting-git-status.md', NULL, NULL, 'manual_marker', 10, 'ready'), +('root-03-m02-a05-reflection', 'root-03-m02-git-mental-model', 5, 'reflection', 'Reflection: The Model Explains the Commands, Not the Other Way Around', + 'content/root/root-03-git-collaborative-development/m02-git-mental-model/05-reflection.md', NULL, NULL, 'manual_marker', 8, 'ready'), +-- M03 +('root-03-m03-a01-lesson', 'root-03-m03-everyday-git', 1, 'lesson', 'Everyday Git', + 'content/root/root-03-git-collaborative-development/m03-everyday-git/01-lesson-everyday-git.md', NULL, NULL, 'manual_marker', 15, 'ready'), +('root-03-m03-a02-demonstration', 'root-03-m03-everyday-git', 2, 'demonstration', 'Demonstration: The Full Cycle, End to End', + 'content/root/root-03-git-collaborative-development/m03-everyday-git/02-demonstration-the-full-everyday-cycle.md', NULL, NULL, 'manual_marker', 8, 'ready'), +('root-03-m03-a03-knowledge-check', 'root-03-m03-everyday-git', 3, 'knowledge_check', 'Knowledge Check: Everyday Git', + 'content/root/root-03-git-collaborative-development/m03-everyday-git/03-knowledge-check.md', NULL, NULL, 'manual_marker', 5, 'ready'), +('root-03-m03-a04-guided-exercise', 'root-03-m03-everyday-git', 4, 'guided_exercise', 'Guided Exercise: Plan a Real Commit Before You Make It', + 'content/root/root-03-git-collaborative-development/m03-everyday-git/04-guided-exercise-planning-your-commit.md', NULL, NULL, 'manual_marker', 8, 'ready'), +('root-03-m03-a05-lab-everyday-basics', 'root-03-m03-everyday-git', 5, 'lab', 'Lab: Init, Track, Commit — Your First Real Repository', + NULL, 'git-everyday-basics', NULL, 'auto_scenario', 12, 'ready'), +('root-03-m03-a06-reflection', 'root-03-m03-everyday-git', 6, 'reflection', 'Reflection: You Have Real, Permanent History Now', + 'content/root/root-03-git-collaborative-development/m03-everyday-git/05-reflection.md', NULL, NULL, 'manual_marker', 8, 'ready'), +-- M04 +('root-03-m04-a01-lesson', 'root-03-m04-branching-and-merging', 1, 'lesson', 'Branching and Merging', + 'content/root/root-03-git-collaborative-development/m04-branching-and-merging/01-lesson-branching-and-merging.md', NULL, NULL, 'manual_marker', 15, 'ready'), +('root-03-m04-a02-demonstration', 'root-03-m04-branching-and-merging', 2, 'demonstration', 'Demonstration: A Conflict, Caused and Resolved on Purpose', + 'content/root/root-03-git-collaborative-development/m04-branching-and-merging/02-demonstration-a-conflict-happening-live.md', NULL, NULL, 'manual_marker', 10, 'ready'), +('root-03-m04-a03-knowledge-check', 'root-03-m04-branching-and-merging', 3, 'knowledge_check', 'Knowledge Check: Branching and Merging', + 'content/root/root-03-git-collaborative-development/m04-branching-and-merging/03-knowledge-check.md', NULL, NULL, 'manual_marker', 5, 'ready'), +('root-03-m04-a04-guided-exercise', 'root-03-m04-branching-and-merging', 4, 'guided_exercise', 'Guided Exercise: Decide the Resolution Before You Touch the File', + 'content/root/root-03-git-collaborative-development/m04-branching-and-merging/04-guided-exercise-choosing-a-resolution.md', NULL, NULL, 'manual_marker', 10, 'ready'), +('root-03-m04-a05-lab-branching-and-merge', 'root-03-m04-branching-and-merging', 5, 'lab', 'Lab: Resolve a Real Merge Conflict', + NULL, 'git-branching-and-merge', NULL, 'auto_scenario', 15, 'ready'), +('root-03-m04-a06-reflection', 'root-03-m04-branching-and-merging', 6, 'reflection', 'Reflection: Your First Conflict Wasn''t a Disaster', + 'content/root/root-03-git-collaborative-development/m04-branching-and-merging/05-reflection.md', NULL, NULL, 'manual_marker', 8, 'ready'), +-- M05 +('root-03-m05-a01-lesson', 'root-03-m05-remote-repositories', 1, 'lesson', 'Remote Repositories', + 'content/root/root-03-git-collaborative-development/m05-remote-repositories/01-lesson-remote-repositories.md', NULL, NULL, 'manual_marker', 15, 'ready'), +('root-03-m05-a02-demonstration', 'root-03-m05-remote-repositories', 2, 'demonstration', 'Demonstration: A Complete Clone-to-Push Round Trip', + 'content/root/root-03-git-collaborative-development/m05-remote-repositories/02-demonstration-clone-commit-push.md', NULL, NULL, 'manual_marker', 8, 'ready'), +('root-03-m05-a03-knowledge-check', 'root-03-m05-remote-repositories', 3, 'knowledge_check', 'Knowledge Check: Remote Repositories', + 'content/root/root-03-git-collaborative-development/m05-remote-repositories/03-knowledge-check.md', NULL, NULL, 'manual_marker', 5, 'ready'), +('root-03-m05-a04-guided-exercise', 'root-03-m05-remote-repositories', 4, 'guided_exercise', 'Guided Exercise: Fetch First, Decide Second', + 'content/root/root-03-git-collaborative-development/m05-remote-repositories/04-guided-exercise-fetch-vs-pull.md', NULL, NULL, 'manual_marker', 8, 'ready'), +('root-03-m05-a05-lab-remote-clone-push', 'root-03-m05-remote-repositories', 5, 'lab', 'Lab: Clone, Commit, and Push to a Real Remote', + NULL, 'git-remote-clone-push', NULL, 'auto_scenario', 12, 'ready'), +('root-03-m05-a06-reflection', 'root-03-m05-remote-repositories', 6, 'reflection', 'Reflection: You Just Practiced Real Collaboration, Safely', + 'content/root/root-03-git-collaborative-development/m05-remote-repositories/05-reflection.md', NULL, NULL, 'manual_marker', 8, 'ready'), +-- M06 (no lab) +('root-03-m06-a01-lesson', 'root-03-m06-engineering-git-workflow', 1, 'lesson', 'Engineering Git Workflow', + 'content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/01-lesson-engineering-git-workflow.md', NULL, NULL, 'manual_marker', 15, 'ready'), +('root-03-m06-a02-demonstration', 'root-03-m06-engineering-git-workflow', 2, 'demonstration', 'Demonstration: The Same Change, Told Two Ways', + 'content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/02-demonstration-a-bad-commit-vs-a-good-one.md', NULL, NULL, 'manual_marker', 8, 'ready'), +('root-03-m06-a03-knowledge-check', 'root-03-m06-engineering-git-workflow', 3, 'knowledge_check', 'Knowledge Check: Engineering Git Workflow', + 'content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/03-knowledge-check.md', NULL, NULL, 'manual_marker', 5, 'ready'), +('root-03-m06-a04-reflection', 'root-03-m06-engineering-git-workflow', 4, 'reflection', 'Reflection: You''ve Practiced Real Engineering Discipline, Not Just Syntax', + 'content/root/root-03-git-collaborative-development/m06-engineering-git-workflow/04-reflection.md', NULL, NULL, 'manual_marker', 8, 'ready') +ON CONFLICT (activity_id) DO NOTHING; + +-- ═══════════════════════════════════════════════════════════════════════════════════════════ +-- ROOT 03 course assessment — mixes real Git-state-validation tasks with knowledge-recall MCQs +-- reasoning about the staging area and diverged branches, via the existing Phase 3B engine. +-- ═══════════════════════════════════════════════════════════════════════════════════════════ +INSERT INTO assessment_definitions (assessment_definition_id, type, title, description, duration_minutes, hint_policy, pool_spec, completion_rule) +VALUES ( + 'rootnode-git-fundamentals-assessment', 'exam', 'ROOT 03 Git & Collaborative Development Assessment', + 'A timed check across everyday Git usage, branching/merge-conflict resolution, and remote workflows — combining real repository-state-validation tasks with conceptual reasoning questions.', + 35, 'disabled', + '{"required": ["git-everyday-basics", "git-branching-and-merge"], + "random": [ + {"count":1,"from":["git-remote-clone-push"]}, + {"count":2,"from":["git-staging-area-mcq","git-diverged-branches-mcq"]} + ]}', + '{"type":"all_scenarios_passed"}' +) ON CONFLICT (assessment_definition_id) DO NOTHING; + +INSERT INTO module_activities (activity_id, module_id, sequence, activity_type, title, content_path, scenario_id, assessment_definition_id, completion_behavior, estimated_duration_minutes, status) VALUES +('root-03-m06-a05-assessment', 'root-03-m06-engineering-git-workflow', 5, 'assessment', 'ROOT 03 Git & Collaborative Development Assessment', NULL, NULL, 'rootnode-git-fundamentals-assessment', 'auto_assessment', 35, 'ready') +ON CONFLICT (activity_id) DO NOTHING; diff --git a/scenarios/data/git-branching-and-merge.json b/scenarios/data/git-branching-and-merge.json new file mode 100644 index 0000000..8c6b104 --- /dev/null +++ b/scenarios/data/git-branching-and-merge.json @@ -0,0 +1,44 @@ +{ + "id": "git-branching-and-merge", + "title": "Resolve a Real Merge Conflict", + "category": "Git", + "isolation_type": "shared_namespace", + "difficulty": "Medium", + "type": "task", + "weight": 6, + "description": "## Resolve a Real Merge Conflict\n\nA repository at `/srv/git-lab-branch/` already has two branches (`main` and `feature`) that both changed the SAME line of `shared.txt` differently — merging them WILL conflict.\n\n**Your task:**\n\n1. Make sure you're on the `main` branch\n2. Merge `feature` into it: `git merge feature`\n3. Git will report a conflict — open `shared.txt` and you'll see conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`)\n4. Edit the file to remove the markers and decide on final content (either version, both, or something new — your choice)\n5. Stage the resolved file and commit to complete the merge", + "hints": [ + { + "title": "What the conflict markers mean", + "body": "Everything between `<<<<<<< HEAD` and `=======` is YOUR current branch's version; everything between `=======` and `>>>>>>> feature` is the incoming branch's version. Delete all three marker lines and keep whichever content (or combination) you actually want.", + "command": "cat /srv/git-lab-branch/shared.txt" + }, + { + "title": "Completing the merge", + "body": "Once the file no longer has conflict markers, staging and committing tells Git the conflict is resolved.", + "command": "cd /srv/git-lab-branch\ngit add shared.txt\ngit commit -m 'Merge feature, resolve conflict'" + } + ], + "setup_commands": [ + { "command": "git config --global init.defaultBranch main" }, + { "command": "git config --global user.email student@rootnode.local" }, + { "command": "git config --global user.name 'RootNode Student'" }, + { "command": "rm -rf /srv/git-lab-branch && mkdir -p /srv/git-lab-branch" }, + { "command": "cd /srv/git-lab-branch && git init -q && echo 'original line' > shared.txt && git add shared.txt && git commit -q -m 'Initial commit'" }, + { "command": "cd /srv/git-lab-branch && git branch feature && git checkout -q feature && echo 'feature version' > shared.txt && git commit -qam 'Update from feature branch'" }, + { "command": "cd /srv/git-lab-branch && git checkout -q main && echo 'main version' > shared.txt && git commit -qam 'Update from main branch'" }, + { "command": "cd /srv/git-lab-branch && git merge feature 2>/dev/null; true" } + ], + "validation": { + "commands": [ + { "description": "the feature branch still exists", "command": "git -C /srv/git-lab-branch branch --list feature | tr -d ' *'", "expected_output": "feature", "match": "exact" }, + { "description": "a real merge commit (two parents) exists", "command": "git -C /srv/git-lab-branch log --merges --oneline 2>/dev/null | wc -l | tr -d ' '", "expected_output": "^[1-9][0-9]*$", "match": "regex" }, + { "description": "the conflict markers were actually removed", "command": "grep -c '<<<<<<<' /srv/git-lab-branch/shared.txt", "expected_output": "0", "match": "exact" }, + { "description": "the working tree is clean (nothing left uncommitted)", "command": "git -C /srv/git-lab-branch status --short | wc -l | tr -d ' '", "expected_output": "0", "match": "exact" } + ] + }, + "default_namespace": "default", + "teardown_commands": [ + { "command": "rm -rf /srv/git-lab-branch" } + ] +} diff --git a/scenarios/data/git-diverged-branches-mcq.json b/scenarios/data/git-diverged-branches-mcq.json new file mode 100644 index 0000000..92fd9c9 --- /dev/null +++ b/scenarios/data/git-diverged-branches-mcq.json @@ -0,0 +1,22 @@ +{ + "id": "git-diverged-branches-mcq", + "title": "Your Branch and the Remote Have Diverged", + "category": "Git", + "isolation_type": "shared_namespace", + "difficulty": "Medium", + "type": "mcq", + "weight": 4, + "description": "## Your Branch and the Remote Have Diverged\n\n`git status` reports \"Your branch and 'origin/main' have diverged, and have 2 and 3 different commits each, respectively.\" What should you understand BEFORE blindly running `git pull`?", + "options": [ + { "id": "a", "text": "Nothing — git pull always resolves this automatically and safely with no side effects" }, + { "id": "b", "text": "That a pull here will attempt to merge (or rebase, depending on config) the remote's 3 commits with your own 2 local commits, which can itself produce a conflict you'll need to resolve — the same way two diverged branches did in this course's merge exercise" }, + { "id": "c", "text": "That you must delete your local commits first" }, + { "id": "d", "text": "That the remote repository is corrupted" } + ], + "correct_option": "b", + "explanation": "\"Diverged\" means both sides have commits the other doesn't have — a plain `git pull` is really fetch-then-merge (or rebase), and merging two sets of independent commits can conflict exactly like the local branch-merge exercise did, just with a remote branch instead of a local one. Understanding this before pulling means you won't be surprised by a conflict, and you definitely don't need to delete anything or assume corruption.", + "hints": [], + "setup_commands": [], + "default_namespace": "default", + "teardown_commands": [] +} diff --git a/scenarios/data/git-everyday-basics.json b/scenarios/data/git-everyday-basics.json new file mode 100644 index 0000000..7cf3790 --- /dev/null +++ b/scenarios/data/git-everyday-basics.json @@ -0,0 +1,34 @@ +{ + "id": "git-everyday-basics", + "title": "Init, Track, Commit — Your First Real Repository", + "category": "Git", + "isolation_type": "shared_namespace", + "difficulty": "Easy", + "type": "task", + "weight": 4, + "description": "## Init, Track, Commit — Your First Real Repository\n\n**Your task**, inside `/srv/git-lab-everyday/`:\n\n1. Initialize a new Git repository\n2. Create a file named `notes.txt` containing any text you like\n3. Stage and commit it, with a commit message that includes the word `notes`\n4. Confirm your work with `git log` and `git status`", + "hints": [ + { + "title": "The full sequence", + "body": "`git init` creates the repository. `git add` stages a file (moves it from working tree to staging area). `git commit` records the staged snapshot permanently.", + "command": "cd /srv/git-lab-everyday\ngit init\necho 'my first notes' > notes.txt\ngit add notes.txt\ngit commit -m 'Add notes file'" + } + ], + "setup_commands": [ + { "command": "mkdir -p /srv/git-lab-everyday" }, + { "command": "git config --global user.email student@rootnode.local" }, + { "command": "git config --global user.name 'RootNode Student'" } + ], + "validation": { + "commands": [ + { "description": "a real Git repository was initialized", "command": "git -C /srv/git-lab-everyday rev-parse --is-inside-work-tree 2>/dev/null", "expected_output": "true", "match": "exact" }, + { "description": "at least one commit exists", "command": "git -C /srv/git-lab-everyday log --oneline 2>/dev/null | wc -l | tr -d ' '", "expected_output": "^[1-9][0-9]*$", "match": "regex" }, + { "description": "notes.txt is tracked in the latest commit", "command": "git -C /srv/git-lab-everyday show --name-only --format= HEAD 2>/dev/null", "expected_output": "notes.txt", "match": "exact" }, + { "description": "the commit message mentions notes", "command": "git -C /srv/git-lab-everyday log -1 --pretty=%s 2>/dev/null", "expected_output": "notes", "match": "contains" } + ] + }, + "default_namespace": "default", + "teardown_commands": [ + { "command": "rm -rf /srv/git-lab-everyday" } + ] +} diff --git a/scenarios/data/git-remote-clone-push.json b/scenarios/data/git-remote-clone-push.json new file mode 100644 index 0000000..494e106 --- /dev/null +++ b/scenarios/data/git-remote-clone-push.json @@ -0,0 +1,35 @@ +{ + "id": "git-remote-clone-push", + "title": "Clone, Commit, and Push to a Real Remote", + "category": "Git", + "isolation_type": "shared_namespace", + "difficulty": "Medium", + "type": "task", + "weight": 5, + "description": "## Clone, Commit, and Push to a Real Remote\n\nA bare Git repository already exists at `/srv/git-lab-remote.git` — this plays the role of a real remote (like Gitea or GitHub) without needing any account or network access. It is currently empty.\n\n**Your task:**\n\n1. Clone it to `/srv/git-lab-clone`\n2. Inside the clone, create a file `README.md` with any content\n3. Add and commit it\n4. Push your commit back to the remote (`origin`)", + "hints": [ + { + "title": "The full sequence", + "body": "`git clone` copies a remote repository (bare or not) into a new working directory, automatically configuring it as `origin`. `git push origin main` sends your local commits back to it.", + "command": "git clone /srv/git-lab-remote.git /srv/git-lab-clone\ncd /srv/git-lab-clone\necho '# My Project' > README.md\ngit add README.md\ngit commit -m 'Add README'\ngit push origin main" + } + ], + "setup_commands": [ + { "command": "git config --global init.defaultBranch main" }, + { "command": "git config --global user.email student@rootnode.local" }, + { "command": "git config --global user.name 'RootNode Student'" }, + { "command": "rm -rf /srv/git-lab-remote.git /srv/git-lab-clone" }, + { "command": "git init -q --bare /srv/git-lab-remote.git" } + ], + "validation": { + "commands": [ + { "description": "the clone has origin configured pointing at the remote", "command": "git -C /srv/git-lab-clone remote get-url origin 2>/dev/null", "expected_output": "/srv/git-lab-remote.git", "match": "exact" }, + { "description": "the commit actually reached the remote (not just the local clone)", "command": "git --git-dir=/srv/git-lab-remote.git log --oneline 2>/dev/null | wc -l | tr -d ' '", "expected_output": "^[1-9][0-9]*$", "match": "regex" }, + { "description": "README.md is part of what was pushed", "command": "git --git-dir=/srv/git-lab-remote.git show --name-only --format= HEAD 2>/dev/null", "expected_output": "README.md", "match": "exact" } + ] + }, + "default_namespace": "default", + "teardown_commands": [ + { "command": "rm -rf /srv/git-lab-remote.git /srv/git-lab-clone" } + ] +} diff --git a/scenarios/data/git-staging-area-mcq.json b/scenarios/data/git-staging-area-mcq.json new file mode 100644 index 0000000..7fc541f --- /dev/null +++ b/scenarios/data/git-staging-area-mcq.json @@ -0,0 +1,22 @@ +{ + "id": "git-staging-area-mcq", + "title": "A Changed File That Won't Commit", + "category": "Git", + "isolation_type": "shared_namespace", + "difficulty": "Easy", + "type": "mcq", + "weight": 3, + "description": "## A Changed File That Won't Commit\n\nYou edit `config.py`, then run `git commit -m \"update config\"`. The commit succeeds, but when you check `git show`, your changes to `config.py` aren't in it. What Git state should you inspect first?", + "options": [ + { "id": "a", "text": "Whether config.py is even tracked by Git at all" }, + { "id": "b", "text": "The staging area — run `git status` to check whether your changes were actually staged with `git add` before you committed" }, + { "id": "c", "text": "Whether your internet connection is working" }, + { "id": "d", "text": "The remote repository's branch protection settings" } + ], + "correct_option": "b", + "explanation": "`git commit` only records what's currently in the STAGING AREA, not every change in your working tree. A modified-but-unstaged file is invisible to the next commit — `git status` shows exactly this distinction (\"Changes not staged for commit\" vs. \"Changes to be committed\"), which is why checking the staging area is the right first step, not assuming the file isn't tracked or a network issue (Git is entirely local for this operation).", + "hints": [], + "setup_commands": [], + "default_namespace": "default", + "teardown_commands": [] +}