From a0a9a5a0d98de11ff3d8b135b8215365d2df3d38 Mon Sep 17 00:00:00 2001 From: Bjarke Sporring Date: Sun, 11 Jan 2026 14:50:10 +0100 Subject: [PATCH] feat: initial branching+merge+conflicts module merge --- .../03-branching-and-merging/README.md | 839 ++++++++++++++++++ .../03-branching-and-merging/challenge | 1 + .../03-branching-and-merging/reset.ps1 | 216 +++++ .../03-branching-and-merging/setup.ps1 | 279 ++++++ .../03-branching-and-merging/verify.ps1 | 320 +++++++ 01_essentials/03-branching/README.md | 92 -- 01_essentials/03-branching/reset.ps1 | 26 - 01_essentials/03-branching/setup.ps1 | 85 -- 01_essentials/03-branching/verify.ps1 | 105 --- .../README.md | 0 .../reset.ps1 | 0 .../setup.ps1 | 0 .../verify.ps1 | 0 01_essentials/04-merging/README.md | 229 ----- 01_essentials/04-merging/reset.ps1 | 26 - 01_essentials/04-merging/setup.ps1 | 246 ----- 01_essentials/04-merging/verify.ps1 | 122 --- 01_essentials/05-merge-conflicts/README.md | 481 ---------- 01_essentials/05-merge-conflicts/reset.ps1 | 22 - 01_essentials/05-merge-conflicts/setup.ps1 | 97 -- 01_essentials/05-merge-conflicts/verify.ps1 | 151 ---- .../README.md | 0 .../reset.ps1 | 0 .../setup.ps1 | 0 .../verify.ps1 | 0 .../{08-stash => 06-stash}/README.md | 0 .../{08-stash => 06-stash}/reset.ps1 | 0 .../{08-stash => 06-stash}/setup.ps1 | 0 .../{08-stash => 06-stash}/verify.ps1 | 0 .../FACILITATOR-SETUP.md | 0 .../README.md | 0 README.md | 86 +- 32 files changed, 1696 insertions(+), 1727 deletions(-) create mode 100644 01_essentials/03-branching-and-merging/README.md create mode 160000 01_essentials/03-branching-and-merging/challenge create mode 100755 01_essentials/03-branching-and-merging/reset.ps1 create mode 100755 01_essentials/03-branching-and-merging/setup.ps1 create mode 100755 01_essentials/03-branching-and-merging/verify.ps1 delete mode 100644 01_essentials/03-branching/README.md delete mode 100644 01_essentials/03-branching/reset.ps1 delete mode 100644 01_essentials/03-branching/setup.ps1 delete mode 100644 01_essentials/03-branching/verify.ps1 rename 01_essentials/{06-cherry-pick => 04-cherry-pick}/README.md (100%) rename 01_essentials/{06-cherry-pick => 04-cherry-pick}/reset.ps1 (100%) rename 01_essentials/{06-cherry-pick => 04-cherry-pick}/setup.ps1 (100%) rename 01_essentials/{06-cherry-pick => 04-cherry-pick}/verify.ps1 (100%) delete mode 100644 01_essentials/04-merging/README.md delete mode 100644 01_essentials/04-merging/reset.ps1 delete mode 100644 01_essentials/04-merging/setup.ps1 delete mode 100644 01_essentials/04-merging/verify.ps1 delete mode 100644 01_essentials/05-merge-conflicts/README.md delete mode 100644 01_essentials/05-merge-conflicts/reset.ps1 delete mode 100644 01_essentials/05-merge-conflicts/setup.ps1 delete mode 100644 01_essentials/05-merge-conflicts/verify.ps1 rename 01_essentials/{07-reset-vs-revert => 05-reset-vs-revert}/README.md (100%) rename 01_essentials/{07-reset-vs-revert => 05-reset-vs-revert}/reset.ps1 (100%) rename 01_essentials/{07-reset-vs-revert => 05-reset-vs-revert}/setup.ps1 (100%) rename 01_essentials/{07-reset-vs-revert => 05-reset-vs-revert}/verify.ps1 (100%) rename 01_essentials/{08-stash => 06-stash}/README.md (100%) rename 01_essentials/{08-stash => 06-stash}/reset.ps1 (100%) rename 01_essentials/{08-stash => 06-stash}/setup.ps1 (100%) rename 01_essentials/{08-stash => 06-stash}/verify.ps1 (100%) rename 01_essentials/{09-multiplayer => 07-multiplayer}/FACILITATOR-SETUP.md (100%) rename 01_essentials/{09-multiplayer => 07-multiplayer}/README.md (100%) diff --git a/01_essentials/03-branching-and-merging/README.md b/01_essentials/03-branching-and-merging/README.md new file mode 100644 index 0000000..55c028b --- /dev/null +++ b/01_essentials/03-branching-and-merging/README.md @@ -0,0 +1,839 @@ +# Module 03: Branching and Merging + +## About This Module + +Welcome to Module 03! This module is different from the others - it uses a **checkpoint system** that lets you work through three related concepts in one continuous repository: + +1. **Branching Basics** - Create and work with feature branches +2. **Merging Branches** - Combine branches together +3. **Resolving Merge Conflicts** - Fix conflicts when Git can't merge automatically + +Instead of three separate modules, you'll progress through checkpoints in a single Git repository, building on each previous section. You can jump between checkpoints, skip ahead, or restart any section at any time! + +### Why Checkpoints? + +Branching, merging, and conflict resolution are naturally connected - you can't understand merging without branches, and you can't master conflicts without trying to merge. The checkpoint system lets you learn these concepts as a continuous workflow, just like real development. + +## Quick Start + +### Setup + +Create the challenge environment: + +```bash +.\setup.ps1 +``` + +This creates a complete Git repository with all checkpoints ready. + +### Working with Checkpoints + +**View available checkpoints:** +```bash +.\reset.ps1 +``` + +**Jump to a specific checkpoint:** +```bash +.\reset.ps1 start # Checkpoint 1: Branching Basics +.\reset.ps1 merge # Checkpoint 2: Merging Branches +.\reset.ps1 merge-conflict # Checkpoint 3: Resolving Conflicts +``` + +**Verify your progress:** +```bash +.\verify.ps1 # Verify all checkpoints complete +.\verify.ps1 start # Verify Checkpoint 1 only +.\verify.ps1 merge # Verify Checkpoint 2 only +.\verify.ps1 merge-conflict # Verify Checkpoint 3 only +``` + +### Recommended Workflow + +Complete checkpoints in order: +1. Start with Checkpoint 1 (Branching Basics) +2. Progress to Checkpoint 2 (Merging) +3. Finish with Checkpoint 3 (Merge Conflicts) + +Or skip to any checkpoint if you already know the earlier concepts! + +--- + +## Checkpoint 1: Branching Basics + +### Learning Objectives + +- Understand what a branch is in Git +- Create new branches with `git switch -c` +- Switch between branches with `git switch` +- View all branches with `git branch` +- Understand that branches are independent lines of development + +### Your Task + +Create a feature branch called `feature-login`, add a `login.py` file, and make commits to demonstrate that branches allow independent development. + +**Steps:** + +1. Navigate to the challenge directory: `cd challenge` +2. Create a new branch: `git switch -c feature-login` +3. Create a file: `login.py` (with any content you like) +4. Commit your file: `git add login.py && git commit -m "Add login module"` +5. Make another change to `login.py` and commit it +6. Switch back to main: `git switch main` +7. Notice that `login.py` doesn't exist on main! +8. Switch back to your feature: `git switch feature-login` +9. Notice that `login.py` exists again! + +**Verify:** Run `.\verify.ps1 start` to check your solution. + +### What is a Branch? + +A **branch** in Git is an independent line of development. Think of it as a parallel universe for your code - you can make changes without affecting the main timeline. + +**Visual representation:** + +``` +main: A---B---C + \ +feature-login: D---E +``` + +- Both branches share commits A and B +- Branch `main` continues with commit C +- Branch `feature-login` goes in a different direction with commits D and E +- Changes in one branch don't affect the other! + +### Why Use Branches? + +Branches let you: +- **Experiment safely** - Try new ideas without breaking main +- **Work in parallel** - Multiple features can be developed simultaneously +- **Organize work** - Each feature/fix gets its own branch +- **Collaborate better** - Team members work on separate branches + +### Key Concepts + +- **Branch**: A lightweight movable pointer to a commit +- **HEAD**: A pointer showing which branch you're currently on +- **main**: The default branch (formerly called "master") +- **Feature branch**: A branch created for a specific feature or task + +### Useful Commands + +```bash +# View all branches (current branch marked with *) +git branch + +# Create a new branch +git branch feature-login + +# Switch to a branch +git switch feature-login + +# Create AND switch in one command +git switch -c feature-login + +# Switch back to previous branch +git switch - + +# Delete a branch (only if merged) +git branch -d feature-login + +# Force delete a branch +git branch -D feature-login +``` + +### Understanding HEAD + +`HEAD` is Git's way of saying "you are here." It points to your current branch. + +When you run `git switch main`, HEAD moves to point to main. +When you run `git switch feature-login`, HEAD moves to point to feature-login. + +--- + +## Checkpoint 2: Merging Branches + +**Prerequisites:** Complete Checkpoint 1 OR run `.\reset.ps1 merge` + +### Learning Objectives + +- Understand what merging means in Git +- Merge a feature branch back into main +- Use `git merge` to combine branches +- Understand merge commits +- Visualize merged branches with `git log --graph` + +### Your Task + +You've completed work on your `feature-login` branch. Now merge it back into `main` to include the login functionality in your main codebase. + +**Scenario:** +- You created the `feature-login` branch and added login functionality +- Meanwhile, development continued on `main` (README and app.py were added) +- Now you need to merge your login feature into main + +**Steps:** + +1. Make sure you're in the challenge directory: `cd challenge` +2. Check which branch you're on: `git branch` +3. Switch to main if needed: `git switch main` +4. View the branch structure: `git log --oneline --graph --all` +5. Merge feature-login into main: `git merge feature-login` +6. View the result: `git log --oneline --graph --all` + +**Verify:** Run `.\verify.ps1 merge` to check your solution. + +### What is Merging? + +**Merging** is the process of combining changes from one branch into another. + +Think of it like combining two streams into one river - all the water (code) flows together. + +#### Before Merging + +You have two branches with different work: + +``` +main: A---B---C---D + \ +feature-login: E---F +``` + +- Main branch progressed with commits C and D +- Feature-login branch has commits E and F +- They diverged at commit B + +#### After Merging + +You bring the feature branch into main: + +``` +main: A---B---C---D---M + \ / +feature-login: E-----F +``` + +- Commit M is a **merge commit** - it combines both branches +- Main now has all the work from both branches +- Your login feature is now part of main! + +### How to Merge + +Merging is simple - just two steps: + +**1. Switch to the branch you want to merge INTO:** +```bash +git switch main +``` +This is the branch that will receive the changes. + +**2. Merge the other branch:** +```bash +git merge feature-login +``` +This brings changes from `feature-login` into `main`. + +**That's it!** Git automatically combines the changes. + +### Understanding Merge Commits + +When you merge, Git creates a special commit called a **merge commit**. + +**What makes it special?** +- It has TWO parent commits (one from each branch) +- It represents the point where branches come back together +- The message typically says "Merge branch 'feature-login'" + +**See your merge commit:** +```bash +git log --oneline +``` + +Look for the merge commit at the top - it will say something like: +``` +abc1234 Merge branch 'feature-login' +``` + +### Types of Merges + +**Three-way merge** (what you just did): +- Both branches have new commits +- Git creates a merge commit +- History shows both branches clearly + +**Fast-forward merge**: +- Main hasn't changed since the branch was created +- Git just moves the main pointer forward +- No merge commit needed! + +``` +# Before (fast-forward merge) +main: A---B + \ +feature: C---D + +# After (main just moves forward) +main: A---B---C---D +``` + +### Visualizing Branches + +The `--graph` flag is your best friend: + +```bash +git log --oneline --graph --all +``` + +**What the graph shows:** +- `*` = A commit +- `|` = A branch line +- `/` and `\` = Branches splitting/joining +- Branch names in parentheses + +**Example output:** +``` +* a1b2c3d (HEAD -> main) Merge branch 'feature-login' +|\ +| * e4f5g6h (feature-login) Add password validation +| * i7j8k9l Add login module +* | m1n2o3p Add README documentation +* | q4r5s6t Add app.py entry point +|/ +* u7v8w9x Add main functionality +* y1z2a3b Initial commit +``` + +### Useful Commands + +```bash +# Merge a branch into your current branch +git merge + +# Abort a merge if something goes wrong +git merge --abort + +# View merge commits only +git log --merges + +# View branch structure +git log --oneline --graph --all + +# See which branches have been merged into main +git branch --merged main + +# See which branches haven't been merged +git branch --no-merged main +``` + +--- + +## Checkpoint 3: Resolving Merge Conflicts + +**Prerequisites:** Complete Checkpoint 2 OR run `.\reset.ps1 merge-conflict` + +### Learning Objectives + +- Understand what merge conflicts are and why they occur +- Identify merge conflicts in your repository +- Read and interpret conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) +- Resolve merge conflicts manually +- Complete a merge after resolving conflicts + +### Your Task + +You have an `update-config` branch that modified `config.json`, and the main branch also modified `config.json` in a different way. When you try to merge, Git can't automatically combine them - you'll need to resolve the conflict manually. + +**Your mission:** +1. Attempt to merge the `update-config` branch into `main` +2. Git will tell you there's a conflict - don't panic! +3. Resolve the conflict by keeping BOTH settings (timeout AND debug) +4. Complete the merge + +**Steps:** + +1. Make sure you're in challenge directory: `cd challenge` +2. Verify you're on main: `git branch` +3. Try to merge: `git merge update-config` +4. Git will report a conflict! +5. Open `config.json` in your text editor +6. Follow the resolution guide below +7. Save the file +8. Stage the resolved file: `git add config.json` +9. Complete the merge: `git commit` + +**Verify:** Run `.\verify.ps1 merge-conflict` to check your solution. + +### What Are Merge Conflicts? + +A **merge conflict** occurs when Git cannot automatically combine changes because both branches modified the same part of the same file. + +**Example scenario:** +``` +main branch: changes line 5 to: "timeout": 5000 +update-config: changes line 5 to: "debug": true +``` + +Git doesn't know which one you want (or if you want both)! So it asks you to decide. + +**When do conflicts happen?** +- ✅ Two branches modify the same lines in a file +- ✅ One branch deletes a file that another branch modifies +- ✅ Complex changes Git can't merge automatically +- ❌ Different files are changed (no conflict!) +- ❌ Different parts of the same file are changed (no conflict!) + +**Don't fear conflicts!** They're a normal part of collaborative development. Git just needs your help to decide what the final code should look like. + +### Step-by-Step: Resolving Your First Conflict + +#### Step 1: Attempt the Merge + +```bash +cd challenge +git merge update-config +``` + +**You'll see:** +``` +Auto-merging config.json +CONFLICT (content): Merge conflict in config.json +Automatic merge failed; fix conflicts and then commit the result. +``` + +**Don't panic!** This is normal. Git is just asking for your help. + +#### Step 2: Check What Happened + +```bash +git status +``` + +**You'll see:** +``` +On branch main +You have unmerged paths. + (fix conflicts and run "git commit") + (use "git merge --abort" to abort the merge) + +Unmerged paths: + (use "git add ..." to mark resolution) + both modified: config.json +``` + +This tells you that `config.json` needs your attention! + +#### Step 3: Open the Conflicted File + +Open `config.json` in your text editor. You'll see special **conflict markers**: + +```json +{ + "app": { + "name": "MyApp", + "version": "1.0.0", + "port": 3000, +<<<<<<< HEAD + "timeout": 5000 +======= + "debug": true +>>>>>>> update-config + } +} +``` + +#### Step 4: Understand the Conflict Markers + +``` +<<<<<<< HEAD + "timeout": 5000 ← Your current branch (main) +======= + "debug": true ← The branch you're merging (update-config) +>>>>>>> update-config +``` + +**What each marker means:** +- `<<<<<<< HEAD` - Start of your changes (current branch) +- `=======` - Separator between the two versions +- `>>>>>>> update-config` - End of their changes (branch being merged) + +#### Step 5: Decide What to Keep + +You have three options: + +**Option 1: Keep ONLY your changes (timeout)** +```json + "timeout": 5000 +``` + +**Option 2: Keep ONLY their changes (debug)** +```json + "debug": true +``` + +**Option 3: Keep BOTH changes** ← This is what we want! +```json + "timeout": 5000, + "debug": true +``` + +For this challenge, choose **Option 3** - keep both settings! + +#### Step 6: Edit the File + +Delete ALL the conflict markers and keep both settings: + +**Before (with conflict markers):** +```json +{ + "app": { + "name": "MyApp", + "version": "1.0.0", + "port": 3000, +<<<<<<< HEAD + "timeout": 5000 +======= + "debug": true +>>>>>>> update-config + } +} +``` + +**After (resolved):** +```json +{ + "app": { + "name": "MyApp", + "version": "1.0.0", + "port": 3000, + "timeout": 5000, + "debug": true + } +} +``` + +**Important:** +- Remove `<<<<<<< HEAD` +- Remove `=======` +- Remove `>>>>>>> update-config` +- Keep both the timeout and debug settings +- Ensure valid JSON syntax (notice the comma after timeout!) + +#### Step 7: Save the File + +Save `config.json` with your changes. + +#### Step 8: Stage the Resolved File + +Tell Git you've resolved the conflict: + +```bash +git add config.json +``` + +#### Step 9: Check Status + +```bash +git status +``` + +**You'll see:** +``` +On branch main +All conflicts fixed but you are still merging. + (use "git commit" to conclude merge) +``` + +Perfect! Git confirms the conflict is resolved. + +#### Step 10: Complete the Merge + +Commit the merge: + +```bash +git commit +``` + +Git will open an editor with a default merge message. You can accept it or customize it. + +**Done!** Your merge is complete! + +### Common Mistakes to Avoid + +❌ **Forgetting to remove conflict markers** +```json +<<<<<<< HEAD ← Don't leave these in! + "timeout": 5000, + "debug": true +>>>>>>> update-config ← Don't leave these in! +``` +This breaks your code! Always remove ALL markers. + +❌ **Committing without staging** +```bash +git commit # Error! You didn't add the file +``` +Always `git add` the resolved file first! + +❌ **Keeping only one side when both are needed** +If you delete one setting, you lose that work. For this challenge, you need BOTH! + +❌ **Breaking syntax** +```json +"timeout": 5000 ← Missing comma! +"debug": true +``` +Always verify your file is valid after resolving! + +### Aborting a Merge + +Changed your mind? You can abort the merge anytime: + +```bash +git merge --abort +``` + +This returns your repository to the state before you started the merge. No harm done! + +### Useful Commands + +```bash +# Attempt a merge +git merge + +# Check which files have conflicts +git status + +# Abort the merge and start over +git merge --abort + +# After resolving conflicts: +git add +git commit + +# View conflicts in a different style +git diff --ours # Your changes +git diff --theirs # Their changes +git diff --base # Original version +``` + +### Pro Tips + +💡 **Prevent conflicts** +- Pull changes frequently: `git pull` +- Communicate with your team about who's working on what +- Keep branches short-lived and merge often + +💡 **Make conflicts easier** +- Work on different files when possible +- If you must edit the same file, coordinate with teammates +- Make small, focused commits + +💡 **When stuck** +- Read the conflict markers carefully +- Look at `git log` to understand what each side changed +- Ask a teammate to review your resolution +- Use a merge tool: `git mergetool` + +--- + +## Complete Command Reference + +### Branching + +```bash +git branch # List all branches +git branch feature-name # Create a new branch +git switch branch-name # Switch to a branch +git switch -c feature-name # Create and switch +git switch - # Switch to previous branch +git branch -d feature-name # Delete branch (if merged) +git branch -D feature-name # Force delete branch +``` + +### Merging + +```bash +git merge branch-name # Merge a branch into current branch +git merge --no-ff branch-name # Force a merge commit +git merge --abort # Abort a merge in progress +git log --merges # View only merge commits +``` + +### Viewing History + +```bash +git log --oneline --graph --all # Visual branch structure +git log --oneline # Compact commit list +git log --graph --decorate --all # Detailed branch view +git log main..feature-login # Commits in feature not in main +git diff main...feature-login # Changes between branches +``` + +### Conflict Resolution + +```bash +git status # See conflicted files +git diff # View conflicts +git add resolved-file # Mark file as resolved +git commit # Complete the merge +git merge --abort # Give up and start over +``` + +### Checkpoint Commands (This Module) + +```bash +.\reset.ps1 # Show available checkpoints +.\reset.ps1 start # Jump to Checkpoint 1 +.\reset.ps1 merge # Jump to Checkpoint 2 +.\reset.ps1 merge-conflict # Jump to Checkpoint 3 +.\verify.ps1 # Verify all complete +.\verify.ps1 start # Verify Checkpoint 1 +.\verify.ps1 merge # Verify Checkpoint 2 +.\verify.ps1 merge-conflict # Verify Checkpoint 3 +``` + +--- + +## Troubleshooting + +### "I'm on the wrong branch!" + +```bash +git switch main # Switch to main +git branch # Verify current branch +``` + +### "I made commits on the wrong branch!" + +Don't panic! You can move them: + +```bash +# You're on main but should be on feature-login +git switch feature-login # Switch to correct branch +git merge main # Bring the commits over +git switch main +git reset --hard HEAD~1 # Remove from main (careful!) +``` + +Or use cherry-pick (covered in a later module). + +### "The merge created a mess!" + +Abort and try again: + +```bash +git merge --abort +git status # Verify you're back to clean state +``` + +### "I want to start this checkpoint over!" + +Use the reset script: + +```bash +.\reset.ps1 start # Go back to Checkpoint 1 +``` + +This resets your repository to the beginning of that checkpoint. + +### "I can't find my branch!" + +List all branches: + +```bash +git branch --all # Shows all branches including remote +``` + +The branch might have been deleted after merging (this is normal!). + +### "How do I know which checkpoint I'm on?" + +```bash +.\reset.ps1 # Shows current checkpoint +git log --oneline --graph --all --decorate # Shows all tags/branches +``` + +--- + +## Real-World Workflow Example + +Here's how professional developers use these skills: + +**Day 1: Start a new feature** +```bash +git switch main +git pull # Get latest changes +git switch -c feature-dark-mode # New feature branch +# ... make changes ... +git add . +git commit -m "Add dark mode toggle" +``` + +**Day 2: Continue work** +```bash +git switch feature-dark-mode # Resume work +# ... make more changes ... +git add . +git commit -m "Add dark mode styles" +``` + +**Day 3: Ready to merge** +```bash +git switch main +git pull # Get latest main +git switch feature-dark-mode +git merge main # Bring main's changes into feature +# Resolve any conflicts +git switch main +git merge feature-dark-mode # Merge feature into main +git push # Share with team +git branch -d feature-dark-mode # Clean up +``` + +**This is exactly what you just practiced!** + +--- + +## What You've Learned + +By completing all three checkpoints, you now understand: + +### Checkpoint 1: Branching Basics +- ✅ Branches create independent lines of development +- ✅ `git switch -c` creates and switches to a new branch +- ✅ Changes in one branch don't affect others +- ✅ Branches are lightweight and easy to create + +### Checkpoint 2: Merging Branches +- ✅ Merging combines work from two branches +- ✅ Merge commits have two parent commits +- ✅ `git merge` brings changes into your current branch +- ✅ Three-way merges create a merge commit + +### Checkpoint 3: Resolving Merge Conflicts +- ✅ Conflicts happen when the same lines are changed differently +- ✅ Conflict markers show both versions +- ✅ You choose what the final code should look like +- ✅ Conflicts are normal and easy to resolve with practice + +--- + +## Next Steps + +**Completed the module?** Great work! You're ready to move on. + +**Want more practice?** Jump to any checkpoint and try again: +```bash +.\reset.ps1 start # Practice branching +.\reset.ps1 merge # Practice merging +.\reset.ps1 merge-conflict # Practice conflict resolution +``` + +**Ready for the next module?** +Continue to Module 04 to learn about cherry-picking specific commits! + +--- + +**Need help?** Review the relevant checkpoint section above, or run `git status` to see what Git suggests! diff --git a/01_essentials/03-branching-and-merging/challenge b/01_essentials/03-branching-and-merging/challenge new file mode 160000 index 0000000..40d5f6c --- /dev/null +++ b/01_essentials/03-branching-and-merging/challenge @@ -0,0 +1 @@ +Subproject commit 40d5f6c19ca1ed3a264d326118297304caabc2da diff --git a/01_essentials/03-branching-and-merging/reset.ps1 b/01_essentials/03-branching-and-merging/reset.ps1 new file mode 100755 index 0000000..7027dc4 --- /dev/null +++ b/01_essentials/03-branching-and-merging/reset.ps1 @@ -0,0 +1,216 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS + Resets the challenge environment to a specific checkpoint. + +.DESCRIPTION + This script allows you to jump to any checkpoint in the module, + resetting your repository to that state. Useful for skipping ahead, + starting over, or practicing specific sections. + +.PARAMETER Checkpoint + The checkpoint to reset to: start, merge, or merge-conflict. + If not specified, displays help information. + +.EXAMPLE + .\reset.ps1 + Shows available checkpoints and current status. + +.EXAMPLE + .\reset.ps1 start + Resets to the beginning (branching basics section). + +.EXAMPLE + .\reset.ps1 merge + Jumps to the merging section (feature-login branch already exists). + +.EXAMPLE + .\reset.ps1 merge-conflict + Jumps to the conflict resolution section (merge already complete). +#> + +param( + [ValidateSet('start', 'merge', 'merge-conflict', '')] + [string]$Checkpoint = '' +) + +# Checkpoint to tag mapping +$checkpointTags = @{ + 'start' = 'checkpoint-start' + 'merge' = 'checkpoint-merge' + 'merge-conflict' = 'checkpoint-merge-conflict' +} + +# Checkpoint descriptions +$checkpointDescriptions = @{ + 'start' = 'Branching Basics - Create and work with feature branches' + 'merge' = 'Merging Branches - Merge feature-login into main' + 'merge-conflict' = 'Resolving Conflicts - Fix merge conflicts in config.json' +} + +# ============================================================================ +# Display help if no checkpoint specified +# ============================================================================ +if ($Checkpoint -eq '') { + Write-Host "`n=== Module 03: Branching and Merging - Checkpoints ===" -ForegroundColor Cyan + Write-Host "`nAvailable checkpoints:" -ForegroundColor White + Write-Host "" + + foreach ($key in @('start', 'merge', 'merge-conflict')) { + $desc = $checkpointDescriptions[$key] + Write-Host " $key" -ForegroundColor Green -NoNewline + Write-Host " - $desc" -ForegroundColor White + } + + Write-Host "`nUsage:" -ForegroundColor Cyan + Write-Host " .\reset.ps1 " -ForegroundColor White + Write-Host "" + Write-Host "Examples:" -ForegroundColor Cyan + Write-Host " .\reset.ps1 start # Start from the beginning" -ForegroundColor White + Write-Host " .\reset.ps1 merge # Jump to merging section" -ForegroundColor White + Write-Host " .\reset.ps1 merge-conflict # Jump to conflict resolution" -ForegroundColor White + Write-Host "" + + # Try to detect current checkpoint + if (Test-Path "challenge/.git") { + Push-Location "challenge" + $currentBranch = git branch --show-current 2>$null + $currentCommit = git rev-parse HEAD 2>$null + + # Check which checkpoint we're at + $currentCheckpoint = $null + foreach ($cp in @('start', 'merge', 'merge-conflict')) { + $tagCommit = git rev-parse $checkpointTags[$cp] 2>$null + if ($currentCommit -eq $tagCommit) { + $currentCheckpoint = $cp + break + } + } + + if ($currentCheckpoint) { + Write-Host "Current checkpoint: " -ForegroundColor Yellow -NoNewline + Write-Host "$currentCheckpoint" -ForegroundColor Green -NoNewline + Write-Host " (on branch $currentBranch)" -ForegroundColor Yellow + } else { + Write-Host "Current status: " -ForegroundColor Yellow -NoNewline + Write-Host "In progress (on branch $currentBranch)" -ForegroundColor White + } + + Pop-Location + } + + Write-Host "" + exit 0 +} + +# ============================================================================ +# Validate challenge directory exists +# ============================================================================ +if (-not (Test-Path "challenge")) { + Write-Host "[ERROR] Challenge directory not found." -ForegroundColor Red + Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow + exit 1 +} + +if (-not (Test-Path "challenge/.git")) { + Write-Host "[ERROR] No git repository found in challenge directory." -ForegroundColor Red + Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow + exit 1 +} + +# Navigate to challenge directory +Push-Location "challenge" + +# ============================================================================ +# Verify the checkpoint tag exists +# ============================================================================ +$targetTag = $checkpointTags[$Checkpoint] +$tagExists = git tag -l $targetTag + +if (-not $tagExists) { + Write-Host "[ERROR] Checkpoint tag '$targetTag' not found." -ForegroundColor Red + Write-Host "Run ..\setup.ps1 to recreate the challenge environment." -ForegroundColor Yellow + Pop-Location + exit 1 +} + +# ============================================================================ +# Check for uncommitted changes +# ============================================================================ +$statusOutput = git status --porcelain 2>$null + +if ($statusOutput) { + Write-Host "`n[WARNING] You have uncommitted changes!" -ForegroundColor Yellow + Write-Host "The following changes will be lost:" -ForegroundColor Yellow + Write-Host "" + git status --short + Write-Host "" + + $response = Read-Host "Continue and discard all changes? (y/N)" + if ($response -ne 'y' -and $response -ne 'Y') { + Write-Host "`nReset cancelled." -ForegroundColor Cyan + Pop-Location + exit 0 + } +} + +# ============================================================================ +# Reset to checkpoint +# ============================================================================ +Write-Host "`nResetting to checkpoint: $Checkpoint" -ForegroundColor Cyan +Write-Host "Description: $($checkpointDescriptions[$Checkpoint])" -ForegroundColor White +Write-Host "" + +try { + # Reset to the checkpoint tag + git reset --hard $targetTag 2>&1 | Out-Null + + # Clean untracked files + git clean -fd 2>&1 | Out-Null + + # Ensure we're on main branch + $currentBranch = git branch --show-current + if ($currentBranch -ne 'main') { + git switch main 2>&1 | Out-Null + git reset --hard $targetTag 2>&1 | Out-Null + } + + Write-Host "[SUCCESS] Reset to checkpoint '$Checkpoint' complete!" -ForegroundColor Green + Write-Host "" + + # Show what to do next + switch ($Checkpoint) { + 'start' { + Write-Host "Next steps:" -ForegroundColor Cyan + Write-Host " 1. Create a new branch: git switch -c feature-login" -ForegroundColor White + Write-Host " 2. Create login.py and make 2+ commits" -ForegroundColor White + Write-Host " 3. Verify: ..\verify.ps1 start" -ForegroundColor White + } + 'merge' { + Write-Host "Next steps:" -ForegroundColor Cyan + Write-Host " 1. View branch structure: git log --oneline --graph --all" -ForegroundColor White + Write-Host " 2. Merge feature-login: git merge feature-login" -ForegroundColor White + Write-Host " 3. Verify: ..\verify.ps1 merge" -ForegroundColor White + } + 'merge-conflict' { + Write-Host "Next steps:" -ForegroundColor Cyan + Write-Host " 1. Attempt merge: git merge update-config" -ForegroundColor White + Write-Host " 2. Resolve conflicts in config.json" -ForegroundColor White + Write-Host " 3. Complete merge: git add config.json && git commit" -ForegroundColor White + Write-Host " 4. Verify: ..\verify.ps1 merge-conflict" -ForegroundColor White + } + } + + Write-Host "" + Write-Host "View current state: git log --oneline --graph --all" -ForegroundColor Cyan + Write-Host "" + +} catch { + Write-Host "[ERROR] Failed to reset to checkpoint." -ForegroundColor Red + Write-Host $_.Exception.Message -ForegroundColor Red + Pop-Location + exit 1 +} + +Pop-Location +exit 0 diff --git a/01_essentials/03-branching-and-merging/setup.ps1 b/01_essentials/03-branching-and-merging/setup.ps1 new file mode 100755 index 0000000..8d15534 --- /dev/null +++ b/01_essentials/03-branching-and-merging/setup.ps1 @@ -0,0 +1,279 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS + Sets up the Module 03 checkpoint-based challenge environment. + +.DESCRIPTION + This script creates a challenge directory with a complete Git repository + containing all commits and checkpoints for learning branching, merging, + and merge conflict resolution in one continuous workflow. + + The script creates three checkpoints: + - checkpoint-start: Beginning of branching basics + - checkpoint-merge: Beginning of merging section + - checkpoint-merge-conflict: Beginning of conflict resolution +#> + +Write-Host "`n=== Setting up Module 03: Branching and Merging ===" -ForegroundColor Cyan + +# Remove existing challenge directory if it exists +if (Test-Path "challenge") { + Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow + Remove-Item -Recurse -Force "challenge" +} + +# Create fresh challenge directory +Write-Host "Creating challenge directory..." -ForegroundColor Green +New-Item -ItemType Directory -Path "challenge" | Out-Null +Set-Location "challenge" + +# Initialize Git repository +Write-Host "Initializing Git repository..." -ForegroundColor Green +git init | Out-Null + +# Configure git for this repository +git config user.name "Workshop Student" +git config user.email "student@example.com" + +# ============================================================================ +# PHASE 1: Branching Basics - Initial commits on main +# ============================================================================ +Write-Host "`nPhase 1: Creating initial project structure..." -ForegroundColor Cyan + +# Commit 1: Initial commit +$mainContent = @" +# main.py - Main application file + +def main(): + print("Welcome to the Application!") + print("This is the main branch") + +if __name__ == "__main__": + main() +"@ +Set-Content -Path "main.py" -Value $mainContent +git add . +git commit -m "Initial commit" | Out-Null + +# Commit 2: Add main functionality +$mainContent = @" +# main.py - Main application file + +def main(): + print("Welcome to the Application!") + print("This is the main branch") + run_application() + +def run_application(): + print("Application is running...") + print("Ready for new features!") + +if __name__ == "__main__": + main() +"@ +Set-Content -Path "main.py" -Value $mainContent +git add . +git commit -m "Add main functionality" | Out-Null + +# Tag checkpoint-start (students begin here - will create feature-login) +Write-Host "Creating checkpoint: start" -ForegroundColor Green +git tag checkpoint-start + +# ============================================================================ +# PHASE 2: Create feature-login branch (what students will do in checkpoint 1) +# ============================================================================ +Write-Host "Phase 2: Creating feature-login branch..." -ForegroundColor Cyan + +# Create and switch to feature-login branch +git switch -c feature-login | Out-Null + +# Commit 3: Add login module +$loginContent = @" +# login.py - User login module + +def login(username, password): + """Authenticate a user.""" + print(f"Authenticating user: {username}") + # TODO: Add actual authentication logic + return True + +def logout(username): + """Log out a user.""" + print(f"Logging out user: {username}") + return True +"@ +Set-Content -Path "login.py" -Value $loginContent +git add . +git commit -m "Add login module" | Out-Null + +# Commit 4: Add password validation +$loginContent = @" +# login.py - User login module + +def validate_password(password): + """Validate password strength.""" + if len(password) < 8: + return False + return True + +def login(username, password): + """Authenticate a user.""" + if not validate_password(password): + print("Password too weak!") + return False + print(f"Authenticating user: {username}") + # TODO: Add actual authentication logic + return True + +def logout(username): + """Log out a user.""" + print(f"Logging out user: {username}") + return True +"@ +Set-Content -Path "login.py" -Value $loginContent +git add . +git commit -m "Add password validation" | Out-Null + +# Switch back to main +git switch main | Out-Null + +# Now create divergence - add commits to main while feature-login exists +Write-Host "Creating divergent history on main..." -ForegroundColor Cyan + +# Commit 5: Add app.py with basic functionality +$appContent = @" +# app.py - Main application entry point + +from main import main + +def run(): + """Run the application.""" + print("Starting application...") + main() + print("Application finished.") + +if __name__ == "__main__": + run() +"@ +Set-Content -Path "app.py" -Value $appContent +git add . +git commit -m "Add app.py entry point" | Out-Null + +# Commit 6: Add README +$readmeContent = @" +# My Application + +Welcome to my application! + +## Features + +- Main functionality +- More features coming soon + +## Setup + +Run: python app.py +"@ +Set-Content -Path "README.md" -Value $readmeContent +git add . +git commit -m "Add README documentation" | Out-Null + +# Tag checkpoint-merge (students begin merging here - divergent branches ready) +Write-Host "Creating checkpoint: merge" -ForegroundColor Green +git tag checkpoint-merge + +# ============================================================================ +# PHASE 3: Merge feature-login into main (what students will do in checkpoint 2) +# ============================================================================ +Write-Host "Phase 3: Merging feature-login into main..." -ForegroundColor Cyan + +# Merge feature-login into main (will create three-way merge commit) +git merge feature-login --no-edit | Out-Null + +# ============================================================================ +# PHASE 4: Create conflict scenario (what students will do in checkpoint 3) +# ============================================================================ +Write-Host "Phase 4: Creating merge conflict scenario..." -ForegroundColor Cyan + +# Create config.json file on main +$initialConfig = @" +{ + "app": { + "name": "MyApp", + "version": "1.0.0", + "port": 3000 + } +} +"@ +Set-Content -Path "config.json" -Value $initialConfig +git add config.json +git commit -m "Add initial configuration" | Out-Null + +# On main branch: Add timeout setting +$mainConfig = @" +{ + "app": { + "name": "MyApp", + "version": "1.0.0", + "port": 3000, + "timeout": 5000 + } +} +"@ +Set-Content -Path "config.json" -Value $mainConfig +git add config.json +git commit -m "Add timeout configuration" | Out-Null + +# Create update-config branch from the commit before timeout was added +git switch -c update-config HEAD~1 | Out-Null + +# On update-config branch: Add debug setting (conflicting change) +$featureConfig = @" +{ + "app": { + "name": "MyApp", + "version": "1.0.0", + "port": 3000, + "debug": true + } +} +"@ +Set-Content -Path "config.json" -Value $featureConfig +git add config.json +git commit -m "Add debug mode configuration" | Out-Null + +# Switch back to main +git switch main | Out-Null + +# Tag checkpoint-merge-conflict (students begin conflict resolution here - on main with timeout, update-config has debug) +Write-Host "Creating checkpoint: merge-conflict" -ForegroundColor Green +git tag checkpoint-merge-conflict + +# ============================================================================ +# Reset to checkpoint-start so students begin at the beginning +# ============================================================================ +Write-Host "`nResetting to checkpoint-start..." -ForegroundColor Yellow +git reset --hard checkpoint-start | Out-Null +git clean -fd | Out-Null + +# Return to module directory +Set-Location .. + +Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green +Write-Host "`nYour challenge environment is ready in the 'challenge/' directory." -ForegroundColor Cyan +Write-Host "`nThis module uses a CHECKPOINT SYSTEM:" -ForegroundColor Yellow +Write-Host " You'll work through 3 sections in one continuous repository:" -ForegroundColor White +Write-Host " 1. Branching Basics (checkpoint: start)" -ForegroundColor White +Write-Host " 2. Merging Branches (checkpoint: merge)" -ForegroundColor White +Write-Host " 3. Resolving Merge Conflicts (checkpoint: merge-conflict)" -ForegroundColor White +Write-Host "`nCommands:" -ForegroundColor Cyan +Write-Host " .\reset.ps1 - Show available checkpoints" -ForegroundColor White +Write-Host " .\reset.ps1 start - Jump to branching section" -ForegroundColor White +Write-Host " .\reset.ps1 merge - Jump to merging section" -ForegroundColor White +Write-Host " .\verify.ps1 - Verify all sections complete" -ForegroundColor White +Write-Host " .\verify.ps1 start - Verify only branching section" -ForegroundColor White +Write-Host "`nNext steps:" -ForegroundColor Cyan +Write-Host " 1. Read the README.md for detailed instructions" -ForegroundColor White +Write-Host " 2. cd challenge" -ForegroundColor White +Write-Host " 3. Start with Checkpoint 1: Branching Basics" -ForegroundColor White +Write-Host "" diff --git a/01_essentials/03-branching-and-merging/verify.ps1 b/01_essentials/03-branching-and-merging/verify.ps1 new file mode 100755 index 0000000..8311d87 --- /dev/null +++ b/01_essentials/03-branching-and-merging/verify.ps1 @@ -0,0 +1,320 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS + Verifies the Module 03 challenge solution (checkpoint-aware). + +.DESCRIPTION + This script can verify completion of individual checkpoints or + the entire module. Without arguments, it verifies all checkpoints. + +.PARAMETER Checkpoint + The checkpoint to verify: start, merge, or merge-conflict. + If not specified, verifies all checkpoints. + +.EXAMPLE + .\verify.ps1 + Verifies all three checkpoints are complete. + +.EXAMPLE + .\verify.ps1 start + Verifies only the branching basics checkpoint. + +.EXAMPLE + .\verify.ps1 merge + Verifies only the merging checkpoint. +#> + +param( + [ValidateSet('start', 'merge', 'merge-conflict', '')] + [string]$Checkpoint = '' +) + +$script:allChecksPassed = $true + +# ============================================================================ +# Helper Functions +# ============================================================================ + +function Write-Pass { + param([string]$Message) + Write-Host "[PASS] $Message" -ForegroundColor Green +} + +function Write-Fail { + param([string]$Message) + Write-Host "[FAIL] $Message" -ForegroundColor Red + $script:allChecksPassed = $false +} + +function Write-Hint { + param([string]$Message) + Write-Host "[HINT] $Message" -ForegroundColor Yellow +} + +# ============================================================================ +# Checkpoint 1: Branching Basics Verification +# ============================================================================ + +function Verify-Branching { + Write-Host "`n=== Checkpoint 1: Branching Basics ===" -ForegroundColor Cyan + + # Save current branch + $originalBranch = git branch --show-current 2>$null + + # Check if feature-login branch exists + $branchExists = git branch --list "feature-login" 2>$null + if ($branchExists) { + Write-Pass "Branch 'feature-login' exists" + } else { + Write-Fail "Branch 'feature-login' not found" + Write-Hint "Create the branch with: git switch -c feature-login" + return + } + + # Check if feature-login has commits beyond main (or if they've been merged) + $commitCount = git rev-list main..feature-login --count 2>$null + $mergeCommitExists = (git log --merges --oneline 2>$null | Select-String "Merge.*feature-login") + + if ($mergeCommitExists -and $commitCount -eq 0) { + # Commits were merged into main - this is correct! + Write-Pass "Branch 'feature-login' commits have been merged into main" + } elseif ($commitCount -ge 2) { + Write-Pass "Branch 'feature-login' has $commitCount new commits" + } else { + Write-Fail "Branch 'feature-login' needs at least 2 new commits (found: $commitCount)" + Write-Hint "Make sure you've committed login.py and made at least one more commit" + } + + # Switch to feature-login and check for login.py + git switch feature-login 2>$null | Out-Null + if (Test-Path "login.py") { + Write-Pass "File 'login.py' exists in feature-login branch" + } else { + Write-Fail "File 'login.py' not found in feature-login branch" + Write-Hint "Create login.py and commit it to the feature-login branch" + } + + # Switch to main and verify login.py doesn't exist there yet (unless merged) + git switch main 2>$null | Out-Null + + # Check if merge happened - if so, login.py can exist on main + $mergeCommitExists = (git log --merges --oneline 2>$null | Select-String "Merge.*feature-login") + + if (-not $mergeCommitExists) { + # No merge yet - login.py should NOT be on main + if (-not (Test-Path "login.py")) { + Write-Pass "File 'login.py' does NOT exist in main branch (branches are independent!)" + } else { + Write-Fail "File 'login.py' should not exist in main branch yet (before merge)" + Write-Hint "Make sure you created login.py only on the feature-login branch" + } + } + + # Switch back to original branch + if ($originalBranch) { + git switch $originalBranch 2>$null | Out-Null + } +} + +# ============================================================================ +# Checkpoint 2: Merging Verification +# ============================================================================ + +function Verify-Merging { + Write-Host "`n=== Checkpoint 2: Merging Branches ===" -ForegroundColor Cyan + + # Check current branch is main + $currentBranch = git branch --show-current 2>$null + if ($currentBranch -eq "main") { + Write-Pass "Currently on main branch" + } else { + Write-Fail "Should be on main branch (currently on: $currentBranch)" + Write-Hint "Switch to main with: git switch main" + } + + # Check if login.py exists on main (indicates merge happened) + if (Test-Path "login.py") { + Write-Pass "File 'login.py' exists on main branch (merged successfully)" + } else { + Write-Fail "File 'login.py' not found on main branch" + Write-Hint "Merge feature-login into main with: git merge feature-login" + } + + # Check for merge commit + $mergeCommitExists = (git log --merges --oneline 2>$null | Select-String "Merge.*feature-login") + + if ($mergeCommitExists) { + Write-Pass "Merge commit exists" + } else { + Write-Fail "No merge commit found" + Write-Hint "Create a merge commit with: git merge feature-login" + } + + # Check commit count (should have both branches' commits) + $commitCount = [int](git rev-list --count HEAD 2>$null) + if ($commitCount -ge 6) { + Write-Pass "Repository has $commitCount commits (merge complete)" + } else { + Write-Fail "Repository should have at least 6 commits after merge (found: $commitCount)" + } +} + +# ============================================================================ +# Checkpoint 3: Merge Conflicts Verification +# ============================================================================ + +function Verify-MergeConflicts { + Write-Host "`n=== Checkpoint 3: Resolving Merge Conflicts ===" -ForegroundColor Cyan + + # Check current branch is main + $currentBranch = git branch --show-current 2>$null + if ($currentBranch -eq "main") { + Write-Pass "Currently on main branch" + } else { + Write-Fail "Should be on main branch (currently on: $currentBranch)" + Write-Hint "Switch to main with: git switch main" + } + + # Check that merge is not in progress + if (Test-Path ".git/MERGE_HEAD") { + Write-Fail "Merge is still in progress (conflicts not resolved)" + Write-Hint "Resolve conflicts in config.json, then: git add config.json && git commit" + return + } else { + Write-Pass "No merge in progress (conflicts resolved)" + } + + # Check if config.json exists + if (Test-Path "config.json") { + Write-Pass "File 'config.json' exists" + } else { + Write-Fail "File 'config.json' not found" + Write-Hint "Merge update-config branch with: git merge update-config" + return + } + + # Verify config.json is valid JSON + try { + $configContent = Get-Content "config.json" -Raw + $config = $configContent | ConvertFrom-Json -ErrorAction Stop + Write-Pass "File 'config.json' is valid JSON" + } catch { + Write-Fail "File 'config.json' is not valid JSON" + Write-Hint "Make sure you removed all conflict markers (<<<<<<<, =======, >>>>>>>)" + return + } + + # Check for conflict markers + if ($configContent -match '<<<<<<<|=======|>>>>>>>') { + Write-Fail "Conflict markers still present in config.json" + Write-Hint "Remove all conflict markers (<<<<<<<, =======, >>>>>>>)" + return + } else { + Write-Pass "No conflict markers in config.json" + } + + # Verify both settings are present (timeout and debug) + if ($config.app.timeout -eq 5000) { + Write-Pass "Timeout setting preserved (5000)" + } else { + Write-Fail "Timeout setting missing or incorrect" + Write-Hint "Keep the timeout: 5000 setting from main branch" + } + + if ($config.app.debug -eq $true) { + Write-Pass "Debug setting preserved (true)" + } else { + Write-Fail "Debug setting missing or incorrect" + Write-Hint "Keep the debug: true setting from update-config branch" + } + + # Verify merge commit exists for update-config + $updateConfigMerge = (git log --merges --oneline 2>$null | Select-String "Merge.*update-config") + if ($updateConfigMerge) { + Write-Pass "Merge commit exists for update-config branch" + } else { + Write-Fail "No merge commit found for update-config" + Write-Hint "Complete the merge with: git commit (after resolving conflicts)" + } +} + +# ============================================================================ +# Main Script Logic +# ============================================================================ + +# Check if challenge directory exists +if (-not (Test-Path "challenge")) { + Write-Host "[ERROR] Challenge directory not found." -ForegroundColor Red + Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow + exit 1 +} + +Push-Location "challenge" + +# Check if git repository exists +if (-not (Test-Path ".git")) { + Write-Host "[ERROR] Not a git repository." -ForegroundColor Red + Write-Host "Run ..\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow + Pop-Location + exit 1 +} + +# Run appropriate verification +if ($Checkpoint -eq '') { + # Verify all checkpoints + Write-Host "`n=== Verifying All Checkpoints ===" -ForegroundColor Cyan + + Verify-Branching + Verify-Merging + Verify-MergeConflicts + +} else { + # Verify specific checkpoint + switch ($Checkpoint) { + 'start' { Verify-Branching } + 'merge' { Verify-Merging } + 'merge-conflict' { Verify-MergeConflicts } + } +} + +Pop-Location + +# Final summary +Write-Host "" +if ($script:allChecksPassed) { + Write-Host "=========================================" -ForegroundColor Green + Write-Host " CONGRATULATIONS! CHALLENGE PASSED!" -ForegroundColor Green + Write-Host "=========================================" -ForegroundColor Green + + if ($Checkpoint -eq '') { + Write-Host "`nYou've completed the entire module!" -ForegroundColor Cyan + Write-Host "You've mastered:" -ForegroundColor Cyan + Write-Host " ✓ Creating and working with branches" -ForegroundColor White + Write-Host " ✓ Merging branches together" -ForegroundColor White + Write-Host " ✓ Resolving merge conflicts" -ForegroundColor White + Write-Host "`nReady for the next module!" -ForegroundColor Green + } else { + Write-Host "`nCheckpoint '$Checkpoint' complete!" -ForegroundColor Cyan + + switch ($Checkpoint) { + 'start' { + Write-Host "Next: Move to the merging checkpoint" -ForegroundColor White + Write-Host " ..\reset.ps1 merge OR continue to merge feature-login" -ForegroundColor Yellow + } + 'merge' { + Write-Host "Next: Move to the conflict resolution checkpoint" -ForegroundColor White + Write-Host " ..\reset.ps1 merge-conflict" -ForegroundColor Yellow + } + 'merge-conflict' { + Write-Host "Module complete! Ready for the next module!" -ForegroundColor Green + } + } + } + Write-Host "" + exit 0 +} else { + Write-Host "[SUMMARY] Some checks failed. Review the hints above and try again." -ForegroundColor Red + Write-Host "[INFO] You can run this verification script as many times as needed." -ForegroundColor Yellow + Write-Host "" + exit 1 +} diff --git a/01_essentials/03-branching/README.md b/01_essentials/03-branching/README.md deleted file mode 100644 index cc361db..0000000 --- a/01_essentials/03-branching/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# Module 03: Branching Basics - -## Learning Objectives - -In this module, you will: -- Understand what a branch is in Git -- Create new branches using `git branch` or `git switch -c` -- Switch between branches using `git switch` -- View all branches with `git branch` -- Understand that branches allow parallel development - -## Challenge - -### Setup - -Run the setup script to create your challenge environment: - -```powershell -.\setup.ps1 -``` - -This will create a `challenge/` directory with a Git repository that has some initial commits on the main branch. - -### Your Task - -Your goal is to create a feature branch, make commits on it, and understand how branches work independently. - -**Steps:** - -1. Create a new branch called `feature-login` -2. Switch to the new branch -3. Create a new file `login.py` with some login functionality -4. Commit the new file to your feature branch -5. Make another change to `login.py` and commit it -6. Switch back to the main branch and observe that `login.py` doesn't exist there - -**Suggested Approach:** - -1. Navigate to the challenge directory: `cd challenge` -2. View existing branches: `git branch` -3. Create and switch to new branch: `git switch -c feature-login` -4. Create `login.py` with any content you like -5. Stage and commit: `git add login.py` and `git commit -m "Add login functionality"` -6. Modify `login.py`, then commit again -7. Switch back to main: `git switch main` -8. Run `ls` (or check your file explorer) and notice that `login.py` doesn't exist on main! -9. Switch back to feature-login: `git switch feature-login` -10. Run `ls` (or check your file explorer) again and see that `login.py` is back! - -> **Important Notes:** -> - Use `git switch` to change branches -> - `git switch -c ` creates and switches in one command -> - Branches are independent - files in one branch don't affect another until you merge -> - You can switch between branches as many times as you want - -## Key Concepts - -- **Branch**: A lightweight movable pointer to a commit. Branches allow you to work on different features independently. -- **HEAD**: A pointer to the current branch you're working on. When you switch branches, HEAD moves. -- **main/master**: The default branch name in Git (main is the modern convention, master is older). -- **Feature Branch**: A branch created to develop a specific feature, separate from the main codebase. - -## Useful Commands - -```bash -git branch # List all branches (* shows current) -git branch # Create a new branch -git switch # Switch to an existing branch -git switch -c # Create and switch to new branch -git switch - # Switch back to previous branch -git branch -d # Delete a branch (we won't use this yet) -``` - -## Verification - -Once you've completed the challenge, verify your solution: - -```powershell -.\verify.ps1 -``` - -The verification script will check that you've created the branch, made commits, and that the branches are independent. - -## Need to Start Over? - -If you want to reset the challenge and start fresh: - -```powershell -.\reset.ps1 -``` - -This will remove the challenge directory and run the setup script again, giving you a clean slate. diff --git a/01_essentials/03-branching/reset.ps1 b/01_essentials/03-branching/reset.ps1 deleted file mode 100644 index cd38f66..0000000 --- a/01_essentials/03-branching/reset.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS - Resets the Module 03 challenge environment. - -.DESCRIPTION - This script removes the existing challenge directory and runs - the setup script again to create a fresh challenge environment. -#> - -Write-Host "`n=== Resetting Module 03 Challenge ===" -ForegroundColor Cyan - -# Remove existing challenge directory if it exists -if (Test-Path "challenge") { - Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow - Remove-Item -Recurse -Force "challenge" -} else { - Write-Host "No existing challenge directory found." -ForegroundColor Cyan -} - -Write-Host "" -Write-Host "----------------------------------------" -ForegroundColor Cyan -Write-Host "" - -# Run setup script -& "$PSScriptRoot\setup.ps1" diff --git a/01_essentials/03-branching/setup.ps1 b/01_essentials/03-branching/setup.ps1 deleted file mode 100644 index 6548f40..0000000 --- a/01_essentials/03-branching/setup.ps1 +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS - Sets up the Module 03 challenge environment for learning about branches. - -.DESCRIPTION - This script creates a challenge directory with a Git repository that - contains a couple of commits on the main branch. Students will create - a feature branch and make commits on it. -#> - -Write-Host "`n=== Setting up Module 03 Challenge ===" -ForegroundColor Cyan - -# Remove existing challenge directory if it exists -if (Test-Path "challenge") { - Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow - Remove-Item -Recurse -Force "challenge" -} - -# Create fresh challenge directory -Write-Host "Creating challenge directory..." -ForegroundColor Green -New-Item -ItemType Directory -Path "challenge" | Out-Null -Set-Location "challenge" - -# Initialize Git repository -Write-Host "Initializing Git repository..." -ForegroundColor Green -git init | Out-Null - -# Configure git for this repository -git config user.name "Workshop Student" -git config user.email "student@example.com" - -# Commit 1: Initial commit -Write-Host "Creating initial project..." -ForegroundColor Green -$mainContent = @" -# main.py - Main application file - -def main(): - print("Welcome to the Application!") - print("This is the main branch") - -if __name__ == "__main__": - main() -"@ -Set-Content -Path "main.py" -Value $mainContent - -git add . -git commit -m "Initial commit" | Out-Null - -# Commit 2: Add main functionality -Write-Host "Adding main functionality..." -ForegroundColor Green -$mainContent = @" -# main.py - Main application file - -def main(): - print("Welcome to the Application!") - print("This is the main branch") - run_application() - -def run_application(): - print("Application is running...") - print("Ready for new features!") - -if __name__ == "__main__": - main() -"@ -Set-Content -Path "main.py" -Value $mainContent - -git add . -git commit -m "Add main functionality" | Out-Null - -# Return to module directory -Set-Location .. - -Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green -Write-Host "`nYour challenge environment is ready in the 'challenge/' directory." -ForegroundColor Cyan -Write-Host "`nNext steps:" -ForegroundColor Cyan -Write-Host " 1. cd challenge" -ForegroundColor White -Write-Host " 2. Create a new branch: git switch -c feature-login" -ForegroundColor White -Write-Host " 3. Create login.py and commit it" -ForegroundColor White -Write-Host " 4. Make another commit on the feature branch" -ForegroundColor White -Write-Host " 5. Switch back to main: git switch main" -ForegroundColor White -Write-Host " 6. Observe that login.py doesn't exist on main!" -ForegroundColor White -Write-Host " 7. Run '..\verify.ps1' to check your solution" -ForegroundColor White -Write-Host "" diff --git a/01_essentials/03-branching/verify.ps1 b/01_essentials/03-branching/verify.ps1 deleted file mode 100644 index b8b3eb0..0000000 --- a/01_essentials/03-branching/verify.ps1 +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS - Verifies the Module 03 challenge solution. - -.DESCRIPTION - This script checks that: - - The challenge directory exists - - A Git repository exists - - The feature-login branch exists - - The branch has at least 2 new commits - - login.py exists in the feature branch but not in main -#> - -Write-Host "`n=== Verifying Module 03 Solution ===" -ForegroundColor Cyan - -$allChecksPassed = $true - -# Check if challenge directory exists -if (-not (Test-Path "challenge")) { - Write-Host "[FAIL] Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red - exit 1 -} - -Set-Location "challenge" - -# Check if git repository exists -if (-not (Test-Path ".git")) { - Write-Host "[FAIL] Not a git repository. Did you run setup.ps1?" -ForegroundColor Red - Set-Location .. - exit 1 -} - -# Save current branch -$originalBranch = git branch --show-current 2>$null - -# Check if feature-login branch exists -$branchExists = git branch --list "feature-login" 2>$null -if ($branchExists) { - Write-Host "[PASS] Branch 'feature-login' exists" -ForegroundColor Green -} else { - Write-Host "[FAIL] Branch 'feature-login' not found" -ForegroundColor Red - Write-Host "[HINT] Create the branch with: git switch -c feature-login" -ForegroundColor Yellow - $allChecksPassed = $false - Set-Location .. - exit 1 -} - -# Check if feature-login has commits beyond main -$commitCount = git rev-list main..feature-login --count 2>$null -if ($commitCount -ge 2) { - Write-Host "[PASS] Branch 'feature-login' has $commitCount new commits" -ForegroundColor Green -} else { - Write-Host "[FAIL] Branch 'feature-login' needs at least 2 new commits (found: $commitCount)" -ForegroundColor Red - Write-Host "[HINT] Make sure you've committed login.py and made at least one more commit" -ForegroundColor Yellow - $allChecksPassed = $false -} - -# Switch to feature-login and check for login.py -git checkout feature-login 2>$null | Out-Null -if (Test-Path "login.py") { - Write-Host "[PASS] File 'login.py' exists in feature-login branch" -ForegroundColor Green -} else { - Write-Host "[FAIL] File 'login.py' not found in feature-login branch" -ForegroundColor Red - Write-Host "[HINT] Create login.py and commit it to the feature-login branch" -ForegroundColor Yellow - $allChecksPassed = $false -} - -# Switch to main and verify login.py doesn't exist -git switch main 2>$null | Out-Null -if (-not (Test-Path "login.py")) { - Write-Host "[PASS] File 'login.py' does NOT exist in main branch (branches are independent!)" -ForegroundColor Green -} else { - Write-Host "[FAIL] File 'login.py' should not exist in main branch" -ForegroundColor Red - Write-Host "[HINT] Make sure you created login.py only on the feature-login branch" -ForegroundColor Yellow - $allChecksPassed = $false -} - -# Switch back to original branch -if ($originalBranch) { - git switch $originalBranch 2>$null | Out-Null -} - -Set-Location .. - -# Final summary -if ($allChecksPassed) { - Write-Host "`n" -NoNewline - Write-Host "=====================================" -ForegroundColor Green - Write-Host " CONGRATULATIONS! CHALLENGE PASSED!" -ForegroundColor Green - Write-Host "=====================================" -ForegroundColor Green - Write-Host "`nYou've successfully learned about Git branches!" -ForegroundColor Cyan - Write-Host "You now understand:" -ForegroundColor Cyan - Write-Host " - How to create branches with git switch -c" -ForegroundColor White - Write-Host " - How to switch between branches" -ForegroundColor White - Write-Host " - That branches are independent lines of development" -ForegroundColor White - Write-Host " - That files in one branch don't affect another" -ForegroundColor White - Write-Host "`nReady for the next module!" -ForegroundColor Green - Write-Host "" -} else { - Write-Host "`n[SUMMARY] Some checks failed. Review the hints above and try again." -ForegroundColor Red - Write-Host "[INFO] You can run this verification script as many times as needed." -ForegroundColor Yellow - Write-Host "" - exit 1 -} diff --git a/01_essentials/06-cherry-pick/README.md b/01_essentials/04-cherry-pick/README.md similarity index 100% rename from 01_essentials/06-cherry-pick/README.md rename to 01_essentials/04-cherry-pick/README.md diff --git a/01_essentials/06-cherry-pick/reset.ps1 b/01_essentials/04-cherry-pick/reset.ps1 similarity index 100% rename from 01_essentials/06-cherry-pick/reset.ps1 rename to 01_essentials/04-cherry-pick/reset.ps1 diff --git a/01_essentials/06-cherry-pick/setup.ps1 b/01_essentials/04-cherry-pick/setup.ps1 similarity index 100% rename from 01_essentials/06-cherry-pick/setup.ps1 rename to 01_essentials/04-cherry-pick/setup.ps1 diff --git a/01_essentials/06-cherry-pick/verify.ps1 b/01_essentials/04-cherry-pick/verify.ps1 similarity index 100% rename from 01_essentials/06-cherry-pick/verify.ps1 rename to 01_essentials/04-cherry-pick/verify.ps1 diff --git a/01_essentials/04-merging/README.md b/01_essentials/04-merging/README.md deleted file mode 100644 index b3c388c..0000000 --- a/01_essentials/04-merging/README.md +++ /dev/null @@ -1,229 +0,0 @@ -# Module 04: Merging Branches - -## Learning Objectives - -In this module, you will: -- Understand what merging means in Git -- Merge a feature branch back into main -- Use `git merge` to combine branches -- Visualize merged branches with `git log --graph` - -## Challenge - -### Setup - -Run the setup script to create your challenge environment: - -```powershell -.\setup.ps1 -``` - -This will create a `challenge/` directory with a Git repository that has a main branch and a feature branch. - -### Your Task - -You've been working on a new login feature in a separate branch. Now it's time to merge your work back into the main branch! - -**Scenario:** -- You created a `feature-login` branch to add login functionality -- You made some commits on that branch -- Meanwhile, your teammate updated the README on main -- Now you need to bring your login feature back into main - -**Steps:** - -1. Navigate to the challenge directory: `cd challenge` -2. Check which branch you're on: `git branch` -3. View all branches: `git log --oneline --graph --all` -4. Merge the feature-login branch into main: `git merge feature-login` -5. View the result: `git log --oneline --graph --all` - -> **That's it!** Merging is how you bring work from one branch into another. - -## What is Merging? - -**Merging** is the process of taking changes from one branch and bringing them into another branch. - -Think of it like combining two streams into one river - all the water (code) flows together. - -### Before Merging - -You have two branches with different work: - -``` -main: A---B---C - \ -feature-login: D---E -``` - -- Main branch has commits A, B, and C -- Feature-login branch has commits D and E -- They split apart at commit B - -### After Merging - -You bring the feature branch into main: - -``` -main: A---B---C---M - \ / -feature-login: D-E -``` - -- Commit M is a **merge commit** - it combines both branches -- Main now has all the work from both branches -- Your login feature is now part of main! - -## How to Merge - -Merging is simple - just two steps: - -**1. Switch to the branch you want to merge INTO** -```bash -git switch main -``` -This is the branch that will receive the changes. - -**2. Merge the other branch** -```bash -git merge feature-login -``` -This brings changes from feature-login into main. - -**That's it!** Git does the work of combining the changes. - -## Understanding the Merge Commit - -When you merge, Git creates a special commit called a **merge commit**. - -**What makes it special?** -- It has TWO parent commits (one from each branch) -- It represents the point where branches came back together -- Git writes a message like "Merge branch 'feature-login'" - -You can view the merge commit just like any other commit: -```bash -git show HEAD -``` - -## Visualizing Merges - -Use `git log --graph` to see how branches merged: - -```bash -git log --oneline --graph --all -``` - -**Example output:** -``` -* a1b2c3d (HEAD -> main) Merge branch 'feature-login' -|\ -| * e5f6g7h (feature-login) Implement login validation -| * h8i9j0k Add login form -* | k1l2m3n Update README with setup instructions -|/ -* n4o5p6q Initial project structure -``` - -**Reading the graph:** -- `*` = A commit -- `|` = Branch line -- `/` and `\` = Branches splitting or joining -- `(HEAD -> main)` = You are here - -The graph shows how the branches split and came back together! - -## Useful Commands - -```bash -# Merging -git merge # Merge a branch into current branch - -# Viewing -git log --oneline --graph # See branch history visually -git log --oneline --graph --all # Include all branches - -# Branch management -git branch # List branches -git switch # Switch to a branch -git branch -d # Delete a branch (after merging) -``` - -## Common Questions - -### "What if I'm on the wrong branch when I merge?" - -Don't worry! The branch you're currently on is the one that receives the changes. - -**Example:** -```bash -git switch main # Go to main -git merge feature-login # Bring feature-login INTO main -``` - -Always switch to the destination branch first! - -### "Can I undo a merge?" - -Yes! Before you push to a remote: -```bash -git reset --hard HEAD~1 -``` - -This removes the merge commit. (We'll cover this more in later modules) - -### "What happens to the feature branch after merging?" - -The feature branch still exists! The merge just copies its commits into main. - -You can delete it if you're done: -```bash -git branch -d feature-login # Safe delete (only if merged) -``` - -The commits are still in history - you're just removing the branch label. - -### "What if Git can't merge automatically?" - -Sometimes Git needs your help when the same lines were changed in both branches. This is called a **merge conflict**. - -Don't worry - we'll learn how to handle conflicts in the next module! - -If you encounter a conflict now and want to cancel: -```bash -git merge --abort -``` - -## Verification - -Once you've merged the feature-login branch, verify your solution: - -```powershell -.\verify.ps1 -``` - -The verification script will check that you've successfully merged. - -## Need to Start Over? - -If you want to reset the challenge and start fresh: - -```powershell -.\reset.ps1 -``` - -## What's Next? - -**Next module:** Merge Conflicts - Learn what to do when Git can't automatically merge changes. - -**Later:** In the advanced modules, you'll learn about different merging strategies and when to use them. For now, understanding basic merging is all you need! - -## Quick Summary - -✅ **Merging** combines work from one branch into another -✅ Switch to the destination branch, then run `git merge ` -✅ Git creates a **merge commit** to record the merge -✅ Use `git log --graph` to visualize how branches merged -✅ The feature branch still exists after merging - you can delete it if you want - -That's all there is to basic merging! 🎉 diff --git a/01_essentials/04-merging/reset.ps1 b/01_essentials/04-merging/reset.ps1 deleted file mode 100644 index 576a8fa..0000000 --- a/01_essentials/04-merging/reset.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS - Resets the Module 04 challenge environment. - -.DESCRIPTION - This script removes the existing challenge directory and runs - the setup script again to create a fresh challenge environment. -#> - -Write-Host "`n=== Resetting Module 04 Challenge ===" -ForegroundColor Cyan - -# Remove existing challenge directory if it exists -if (Test-Path "challenge") { - Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow - Remove-Item -Recurse -Force "challenge" -} else { - Write-Host "No existing challenge directory found." -ForegroundColor Cyan -} - -Write-Host "" -Write-Host "----------------------------------------" -ForegroundColor Cyan -Write-Host "" - -# Run setup script -& "$PSScriptRoot\setup.ps1" diff --git a/01_essentials/04-merging/setup.ps1 b/01_essentials/04-merging/setup.ps1 deleted file mode 100644 index b9f31ca..0000000 --- a/01_essentials/04-merging/setup.ps1 +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS - Sets up the Module 04 challenge environment for learning about merging. - -.DESCRIPTION - This script creates a challenge directory with a Git repository that - contains two divergent branches ready to merge (three-way merge scenario). -#> - -Write-Host "`n=== Setting up Module 04 Challenge ===" -ForegroundColor Cyan - -# Remove existing challenge directory if it exists -if (Test-Path "challenge") { - Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow - Remove-Item -Recurse -Force "challenge" -} - -# Create fresh challenge directory -Write-Host "Creating challenge directory..." -ForegroundColor Green -New-Item -ItemType Directory -Path "challenge" | Out-Null -Set-Location "challenge" - -# Initialize Git repository -Write-Host "Initializing Git repository..." -ForegroundColor Green -git init | Out-Null - -# Configure git for this repository -git config user.name "Workshop Student" -git config user.email "student@example.com" - -# Commit 1: Initial project structure on main -Write-Host "Creating initial project structure..." -ForegroundColor Green -$readmeContent = @" -# My Project - -A simple web application project. - -## Setup - -Coming soon... -"@ -Set-Content -Path "README.md" -Value $readmeContent - -$appContent = @" -# app.py - Main application file - -def main(): - print("Welcome to My App!") - pass - -if __name__ == "__main__": - main() -"@ -Set-Content -Path "app.py" -Value $appContent - -git add . -git commit -m "Initial project structure" | Out-Null - -# Commit 2: Add configuration file on main -Write-Host "Adding configuration..." -ForegroundColor Green -$configContent = @" -# config.py - Configuration settings - -APP_NAME = "My Project" -VERSION = "1.0.0" -DEBUG = False -"@ -Set-Content -Path "config.py" -Value $configContent - -git add . -git commit -m "Add basic configuration" | Out-Null - -# Commit 3: Add database utilities on main -Write-Host "Adding database utilities..." -ForegroundColor Green -$dbContent = @" -# database.py - Database utilities - -def connect(): - """Connect to database.""" - print("Connecting to database...") - return True - -def disconnect(): - """Disconnect from database.""" - print("Disconnecting...") - return True -"@ -Set-Content -Path "database.py" -Value $dbContent - -git add . -git commit -m "Add database utilities" | Out-Null - -# Create feature-login branch -Write-Host "Creating feature-login branch..." -ForegroundColor Green -git switch -c feature-login | Out-Null - -# Commit 4: Add login module on feature-login -Write-Host "Adding login functionality on feature-login..." -ForegroundColor Green -$loginContent = @" -# login.py - User login module - -def login(username, password): - """Authenticate a user.""" - print(f"Authenticating user: {username}") - # TODO: Add actual authentication logic - return True - -def logout(username): - """Log out a user.""" - print(f"Logging out user: {username}") - return True -"@ -Set-Content -Path "login.py" -Value $loginContent - -git add . -git commit -m "Add login module" | Out-Null - -# Commit 5: Add password validation on feature-login -$loginContent = @" -# login.py - User login module - -def validate_password(password): - """Validate password strength.""" - if len(password) < 8: - return False - return True - -def login(username, password): - """Authenticate a user.""" - if not validate_password(password): - print("Password too weak!") - return False - print(f"Authenticating user: {username}") - # TODO: Add actual authentication logic - return True - -def logout(username): - """Log out a user.""" - print(f"Logging out user: {username}") - return True -"@ -Set-Content -Path "login.py" -Value $loginContent - -git add . -git commit -m "Add password validation" | Out-Null - -# Commit 6: Integrate login with app on feature-login -$appContent = @" -# app.py - Main application file -from login import login, logout - -def main(): - print("Welcome to My App!") - # Add login integration - if login("testuser", "password123"): - print("Login successful!") - pass - -if __name__ == "__main__": - main() -"@ -Set-Content -Path "app.py" -Value $appContent - -git add . -git commit -m "Integrate login with main app" | Out-Null - -# Commit 7: Add session management on feature-login -$sessionContent = @" -# session.py - Session management - -class Session: - def __init__(self, username): - self.username = username - self.active = True - - def end(self): - """End the session.""" - self.active = False - print(f"Session ended for {self.username}") -"@ -Set-Content -Path "session.py" -Value $sessionContent - -git add . -git commit -m "Add session management" | Out-Null - -# Switch back to main branch -Write-Host "Switching back to main branch..." -ForegroundColor Green -git switch main | Out-Null - -# Commit 8: Update README on main (creates divergence) -Write-Host "Adding documentation on main (creates divergence)..." -ForegroundColor Green -$readmeContent = @" -# My Project - -A simple web application project. - -## Setup - -1. Install Python 3.8 or higher -2. Run: python app.py - -## Features - -- User authentication (coming soon) -- Data management (coming soon) - -## Contributing - -Please follow our coding standards when contributing. -"@ -Set-Content -Path "README.md" -Value $readmeContent - -git add . -git commit -m "Update README with setup instructions" | Out-Null - -# Commit 9: Update configuration on main -$configContent = @" -# config.py - Configuration settings - -APP_NAME = "My Project" -VERSION = "1.0.0" -DEBUG = False -DATABASE_PATH = "./data/app.db" -LOG_LEVEL = "INFO" -"@ -Set-Content -Path "config.py" -Value $configContent - -git add . -git commit -m "Add database path to config" | Out-Null - -# Return to module directory -Set-Location .. - -Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green -Write-Host "`nYour challenge environment is ready in the 'challenge/' directory." -ForegroundColor Cyan -Write-Host "`nScenario: You have two divergent branches!" -ForegroundColor Yellow -Write-Host " - main: Has 5 commits (config, database utils, README updates)" -ForegroundColor White -Write-Host " - feature-login: Has 4 commits (login, validation, session)" -ForegroundColor White -Write-Host "`nNext steps:" -ForegroundColor Cyan -Write-Host " 1. cd challenge" -ForegroundColor White -Write-Host " 2. View the branch structure: git log --oneline --graph --all" -ForegroundColor White -Write-Host " 3. Merge feature-login into main: git merge feature-login" -ForegroundColor White -Write-Host " 4. View the merge result: git log --oneline --graph --all" -ForegroundColor White -Write-Host " 5. Run '..\verify.ps1' to check your solution" -ForegroundColor White -Write-Host "" diff --git a/01_essentials/04-merging/verify.ps1 b/01_essentials/04-merging/verify.ps1 deleted file mode 100644 index 6c3f9cd..0000000 --- a/01_essentials/04-merging/verify.ps1 +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS - Verifies the Module 04 challenge solution. - -.DESCRIPTION - This script checks that: - - The challenge directory exists - - A Git repository exists - - Currently on main branch - - feature-login has been merged into main - - A merge commit exists (three-way merge) - - Login functionality is present on main -#> - -Write-Host "`n=== Verifying Module 04 Solution ===" -ForegroundColor Cyan - -$allChecksPassed = $true - -# Check if challenge directory exists -if (-not (Test-Path "challenge")) { - Write-Host "[FAIL] Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red - exit 1 -} - -Set-Location "challenge" - -# Check if git repository exists -if (-not (Test-Path ".git")) { - Write-Host "[FAIL] Not a git repository. Did you run setup.ps1?" -ForegroundColor Red - Set-Location .. - exit 1 -} - -# Check current branch is main -$currentBranch = git branch --show-current 2>$null -if ($currentBranch -eq "main") { - Write-Host "[PASS] Currently on main branch" -ForegroundColor Green -} else { - Write-Host "[FAIL] Not on main branch (currently on: $currentBranch)" -ForegroundColor Red - Write-Host "[HINT] Switch to main with: git switch main" -ForegroundColor Yellow - $allChecksPassed = $false -} - -# Check if feature-login branch exists -$featureLoginBranch = git branch --list "feature-login" 2>$null -if ($featureLoginBranch) { - Write-Host "[PASS] Branch 'feature-login' exists" -ForegroundColor Green -} else { - Write-Host "[INFO] Branch 'feature-login' not found (may have been deleted after merge)" -ForegroundColor Cyan -} - -# Check if login.py exists (should be on main after merge) -if (Test-Path "login.py") { - Write-Host "[PASS] File 'login.py' exists on main (from feature-login merge)" -ForegroundColor Green -} else { - Write-Host "[FAIL] File 'login.py' not found on main" -ForegroundColor Red - Write-Host "[HINT] This file should appear after merging feature-login into main" -ForegroundColor Yellow - $allChecksPassed = $false -} - -# Check if app.py contains login integration -if (Test-Path "app.py") { - $appContent = Get-Content "app.py" -Raw - if ($appContent -match "login") { - Write-Host "[PASS] app.py contains login integration" -ForegroundColor Green - } else { - Write-Host "[FAIL] app.py doesn't contain login integration" -ForegroundColor Red - Write-Host "[HINT] After merging, app.py should import and use the login module" -ForegroundColor Yellow - $allChecksPassed = $false - } -} else { - Write-Host "[FAIL] app.py not found" -ForegroundColor Red - $allChecksPassed = $false -} - -# Check for merge commit (indicates three-way merge happened) -$mergeCommits = git log --merges --oneline 2>$null -if ($mergeCommits) { - Write-Host "[PASS] Merge commit found (three-way merge completed)" -ForegroundColor Green - - # Get the merge commit message - $mergeMessage = git log --merges --format=%s -1 2>$null - Write-Host "[INFO] Merge commit message: '$mergeMessage'" -ForegroundColor Cyan -} else { - Write-Host "[FAIL] No merge commit found" -ForegroundColor Red - Write-Host "[HINT] Merge feature-login into main with: git merge feature-login" -ForegroundColor Yellow - $allChecksPassed = $false -} - -# Check if both branches contributed commits (true three-way merge) -$totalCommits = git rev-list --count HEAD 2>$null -if ($totalCommits -ge 4) { - Write-Host "[PASS] Repository has $totalCommits commits (branches diverged properly)" -ForegroundColor Green -} else { - Write-Host "[WARN] Repository has only $totalCommits commits (expected at least 4)" -ForegroundColor Yellow - Write-Host "[INFO] This might still be correct if you deleted commits" -ForegroundColor Cyan -} - -Set-Location .. - -# Final summary -if ($allChecksPassed) { - Write-Host "`n" -NoNewline - Write-Host "=====================================" -ForegroundColor Green - Write-Host " CONGRATULATIONS! CHALLENGE PASSED!" -ForegroundColor Green - Write-Host "=====================================" -ForegroundColor Green - Write-Host "`nYou've successfully completed your first branch merge!" -ForegroundColor Cyan - Write-Host "You now understand:" -ForegroundColor Cyan - Write-Host " - How to merge branches with git merge" -ForegroundColor White - Write-Host " - What a merge commit is and why it's created" -ForegroundColor White - Write-Host " - How divergent branches are combined" -ForegroundColor White - Write-Host " - How to visualize merges with git log --graph" -ForegroundColor White - Write-Host "`nNext up: Module 05 - Merge Conflicts!" -ForegroundColor Yellow - Write-Host "You'll learn what happens when Git can't automatically merge." -ForegroundColor Cyan - Write-Host "" -} else { - Write-Host "`n[SUMMARY] Some checks failed. Review the hints above and try again." -ForegroundColor Red - Write-Host "[INFO] You can run this verification script as many times as needed." -ForegroundColor Yellow - Write-Host "" - exit 1 -} diff --git a/01_essentials/05-merge-conflicts/README.md b/01_essentials/05-merge-conflicts/README.md deleted file mode 100644 index fb8ee67..0000000 --- a/01_essentials/05-merge-conflicts/README.md +++ /dev/null @@ -1,481 +0,0 @@ -# Module 05: Merge Conflicts - -## Learning Objectives - -By the end of this module, you will: -- Understand what merge conflicts are and why they occur -- Identify merge conflicts in your repository -- Read and interpret conflict markers -- Resolve merge conflicts manually step-by-step -- Complete a merge after resolving conflicts - -## Challenge - -### Setup - -Run the setup script to create your challenge environment: - -```powershell -.\setup.ps1 -``` - -This will create a `challenge/` directory with a repository that has a merge conflict waiting to happen! - -### Your Task - -You have a repository with a main branch and a feature branch called `update-config`. Both branches have modified the same configuration file in different ways, creating a merge conflict. - -**Your mission:** -1. Attempt to merge the `update-config` branch into `main` -2. Git will tell you there's a conflict - don't panic! -3. Resolve the conflict by keeping BOTH settings (timeout AND debug) -4. Complete the merge - -**Steps to follow:** - -1. Navigate to the challenge directory: `cd challenge` -2. Make sure you're on main: `git branch` -3. Try to merge: `git merge update-config` -4. Git will report a conflict! -5. Open `config.py` in your text editor -6. Follow the step-by-step guide below to resolve it -7. Save the file, stage it, and commit - -## What Are Merge Conflicts? - -A **merge conflict** occurs when Git cannot automatically combine changes because both branches modified the same lines in the same file. - -**Example scenario:** -``` -main branch changes line 5: TIMEOUT = 30 -feature branch changes line 5: DEBUG = True -``` - -Git doesn't know which one you want! So it asks you to decide. - -**When do conflicts happen?** -- ✅ Two branches modify the same line(s) -- ✅ One branch deletes a file that another branch modifies -- ❌ Different files are changed (no conflict!) -- ❌ Different lines in the same file are changed (no conflict!) - -## Step-by-Step: Resolving Your First Conflict - -### Step 1: Attempt the Merge - -```bash -cd challenge -git merge update-config -``` - -**You'll see:** -``` -Auto-merging config.py -CONFLICT (content): Merge conflict in config.py -Automatic merge failed; fix conflicts and then commit the result. -``` - -**Don't panic!** This is normal. Git is just asking for your help. - ---- - -### Step 2: Check What Happened - -```bash -git status -``` - -**You'll see:** -``` -On branch main -You have unmerged paths. - (fix conflicts and run "git commit") - (use "git merge --abort" to abort the merge) - -Unmerged paths: - (use "git add ..." to mark resolution) - both modified: config.py -``` - -This tells you that `config.py` needs your attention! - ---- - -### Step 3: Open the Conflicted File - -Open `config.py` in your text editor. You'll see something like this: - -```python -# config.py - Application configuration - -APP_NAME = "My Application" -VERSION = "1.0.0" -<<<<<<< HEAD -TIMEOUT = 30 -======= -DEBUG = True ->>>>>>> update-config -``` - -**Let's break down what you're seeing:** - ---- - -## Understanding Conflict Markers - -Git has added special markers to show you both versions: - -```python -<<<<<<< HEAD ← Start of YOUR version (current branch) -TIMEOUT = 30 ← What YOU have on main -======= ← Divider between versions -DEBUG = True ← What THEY have on update-config ->>>>>>> update-config ← End of THEIR version -``` - -**The three parts:** - -1. **`<<<<<<< HEAD`** - Everything between here and `=======` is YOUR current branch's version -2. **`=======`** - This separates the two versions -3. **`>>>>>>> update-config`** - Everything between `=======` and here is the INCOMING branch's version - ---- - -## Step 4: Decide What to Keep - -You have three options: - -**Option A: Keep YOUR version (main)** -```python -# config.py - Application configuration - -APP_NAME = "My Application" -VERSION = "1.0.0" -TIMEOUT = 30 -``` - -**Option B: Keep THEIR version (update-config)** -```python -# config.py - Application configuration - -APP_NAME = "My Application" -VERSION = "1.0.0" -DEBUG = True -``` - -**Option C: Keep BOTH (this is what we want!)** -```python -# config.py - Application configuration - -APP_NAME = "My Application" -VERSION = "1.0.0" -TIMEOUT = 30 -DEBUG = True -``` - ---- - -## Step 5: Edit the File to Resolve the Conflict - -**What the file looks like NOW (with conflict markers):** -```python -# config.py - Application configuration - -APP_NAME = "My Application" -VERSION = "1.0.0" -<<<<<<< HEAD -TIMEOUT = 30 -======= -DEBUG = True ->>>>>>> update-config -``` - -**What you need to do:** - -1. **Delete** the line `<<<<<<< HEAD` -2. **Keep** the line `TIMEOUT = 30` -3. **Delete** the line `=======` -4. **Keep** the line `DEBUG = True` -5. **Delete** the line `>>>>>>> update-config` - -**What the file should look like AFTER (conflict resolved):** -```python -# config.py - Application configuration - -APP_NAME = "My Application" -VERSION = "1.0.0" -TIMEOUT = 30 -DEBUG = True -``` - -**Save the file!** - ---- - -## Step 6: Mark the Conflict as Resolved - -Tell Git you've fixed the conflict by staging the file: - -```bash -git add config.py -``` - -This tells Git: "I've resolved the conflict in this file, it's ready to be committed." - ---- - -## Step 7: Check Your Status - -```bash -git status -``` - -**You should see:** -``` -On branch main -All conflicts fixed but you are still merging. - (use "git commit" to conclude merge) - -Changes to be committed: - modified: config.py -``` - -Great! Git knows the conflict is resolved and is ready for you to complete the merge. - ---- - -## Step 8: Complete the Merge - -```bash -git commit -``` - -Git will open your editor with a default merge message: -``` -Merge branch 'update-config' - -# Conflicts: -# config.py -``` - -You can keep this message or customize it. Save and close the editor. - -**Or use a one-liner:** -```bash -git commit -m "Merge update-config: resolve config conflict" -``` - ---- - -## Step 9: Verify the Merge - -```bash -git log --oneline --graph -``` - -You should see your merge commit! - -```bash -cat config.py -``` - -Verify the file has BOTH settings and NO conflict markers! - ---- - -## Visual Summary: Before and After - -### Before Resolution (WRONG ❌) -```python -# config.py -APP_NAME = "My Application" -VERSION = "1.0.0" -<<<<<<< HEAD -TIMEOUT = 30 -======= -DEBUG = True ->>>>>>> update-config -``` -**This will NOT run! Conflict markers are syntax errors!** - -### After Resolution (CORRECT ✅) -```python -# config.py -APP_NAME = "My Application" -VERSION = "1.0.0" -TIMEOUT = 30 -DEBUG = True -``` -**Clean code, no markers, both settings preserved!** - ---- - -## Common Mistakes to Avoid - -### ❌ Mistake 1: Forgetting to Remove Conflict Markers -```python -TIMEOUT = 30 -======= ← Still has conflict marker! -DEBUG = True -``` -**This is invalid Python code and will crash!** - -### ❌ Mistake 2: Committing Without Staging -```bash -# Wrong order: -git commit # Error! File not staged - -# Correct order: -git add config.py # Stage first -git commit # Then commit -``` - -### ❌ Mistake 3: Only Keeping One Side When You Need Both -```python -# If the task asks for BOTH settings, this is wrong: -TIMEOUT = 30 -# Missing DEBUG = True -``` - ---- - -## Useful Commands Reference - -```bash -# During a conflict -git status # See which files have conflicts -git diff # See the conflict in detail - -# Resolving -git add # Mark file as resolved -git commit # Complete the merge - -# If you want to start over -git merge --abort # Cancel the merge, go back to before - -# After resolving -git log --oneline --graph # See the merge commit -``` - ---- - -## Real-World Conflict Resolution Workflow - -**Here's what you'll do every time you have a conflict:** - -```bash -# 1. Attempt the merge -git merge feature-branch -# → Git says: "CONFLICT! Fix it!" - -# 2. Check what's wrong -git status -# → Shows which files have conflicts - -# 3. Open the file, find the markers -# <<<<<<< HEAD -# your version -# ======= -# their version -# >>>>>>> branch - -# 4. Edit the file to resolve -# Remove the markers, keep what you need - -# 5. Stage the resolved file -git add config.py - -# 6. Complete the merge -git commit -m "Resolve conflict in config.py" - -# 7. Celebrate! 🎉 -``` - ---- - -## What If You Get Stuck? - -### Option 1: Abort the Merge -```bash -git merge --abort -``` -This puts everything back to how it was before the merge. You can try again! - -### Option 2: Ask for Help -```bash -git status # See what's going on -git diff # See the conflict details -``` - ---- - -## Pro Tips - -✅ **Use `git status` constantly** - It tells you exactly what to do next - -✅ **Search for `<<<<<<<`** - Your editor's search function can find all conflicts quickly - -✅ **Test after resolving** - Make sure your code still works! - -✅ **Read both sides carefully** - Sometimes you need parts from each version - -✅ **Take your time** - Conflicts are not a race. Understand what changed and why. - ---- - -## Verification - -Once you've resolved the conflict and completed the merge, verify your solution: - -```powershell -.\verify.ps1 -``` - -The verification will check that: -- ✅ The merge conflict was resolved -- ✅ The merge was completed successfully -- ✅ BOTH settings are in the config file (TIMEOUT and DEBUG) -- ✅ NO conflict markers remain -- ✅ The merge commit exists in history - ---- - -## Need to Start Over? - -If you want to reset the challenge and start fresh: - -```powershell -.\reset.ps1 -``` - ---- - -## What You've Learned - -🎉 **Congratulations!** You can now: -- Recognize when a merge conflict occurs -- Read and understand conflict markers -- Edit files to resolve conflicts -- Stage resolved files with `git add` -- Complete a merge with `git commit` - -**This is a critical skill!** Every developer encounters merge conflicts. Now you know exactly what to do when they happen. - ---- - -## Quick Reference Card - -**When you see a conflict:** - -1. **Don't panic** ✅ -2. **Run `git status`** to see which files -3. **Open the file** in your editor -4. **Find the markers** (`<<<<<<<`, `=======`, `>>>>>>>`) -5. **Decide what to keep** (one side, other side, or both) -6. **Remove ALL markers** (the `<<<<<<<`, `=======`, `>>>>>>>` lines) -7. **Save the file** -8. **Stage it** (`git add filename`) -9. **Commit** (`git commit`) -10. **Verify** (`git status`, `git log --oneline --graph`) - -**Remember:** The conflict markers are NOT valid code - they MUST be removed! diff --git a/01_essentials/05-merge-conflicts/reset.ps1 b/01_essentials/05-merge-conflicts/reset.ps1 deleted file mode 100644 index d9c9ce0..0000000 --- a/01_essentials/05-merge-conflicts/reset.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env pwsh - -<# -.SYNOPSIS - Resets the merge conflicts challenge environment. - -.DESCRIPTION - Removes the existing challenge directory and runs setup.ps1 - to create a fresh challenge environment. -#> - -Write-Host "Resetting challenge environment..." -ForegroundColor Yellow - -# Remove existing challenge directory if present -if (Test-Path "challenge") { - Remove-Item -Path "challenge" -Recurse -Force - Write-Host "Removed existing challenge directory." -ForegroundColor Cyan -} - -# Run setup script -Write-Host "Running setup script...`n" -ForegroundColor Cyan -& ".\setup.ps1" diff --git a/01_essentials/05-merge-conflicts/setup.ps1 b/01_essentials/05-merge-conflicts/setup.ps1 deleted file mode 100644 index a9816c0..0000000 --- a/01_essentials/05-merge-conflicts/setup.ps1 +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env pwsh - -<# -.SYNOPSIS - Sets up the merge conflicts challenge environment. - -.DESCRIPTION - Creates a Git repository with a merge conflict scenario involving - a configuration file that has been modified differently on two branches. -#> - -# Remove existing challenge directory if present -if (Test-Path "challenge") { - Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow - Remove-Item -Path "challenge" -Recurse -Force -} - -# Create challenge directory -Write-Host "Creating challenge environment..." -ForegroundColor Cyan -New-Item -ItemType Directory -Path "challenge" | Out-Null -Set-Location "challenge" - -# Initialize git repository -git init | Out-Null -git config user.name "Workshop User" | Out-Null -git config user.email "user@workshop.local" | Out-Null - -# Create initial config.json file -$initialConfig = @" -{ - "app": { - "name": "MyApp", - "version": "1.0.0", - "port": 3000 - } -} -"@ - -Set-Content -Path "config.json" -Value $initialConfig -git add config.json -git commit -m "Initial configuration" | Out-Null - -# Create feature branch -git branch update-config | Out-Null - -# On main branch: Add timeout setting -$mainConfig = @" -{ - "app": { - "name": "MyApp", - "version": "1.0.0", - "port": 3000, - "timeout": 5000 - } -} -"@ - -Set-Content -Path "config.json" -Value $mainConfig -git add config.json -git commit -m "Add timeout configuration" | Out-Null - -# Switch to feature branch: Add debug setting (conflicting change) -git switch update-config | Out-Null - -$featureConfig = @" -{ - "app": { - "name": "MyApp", - "version": "1.0.0", - "port": 3000, - "debug": true - } -} -"@ - -Set-Content -Path "config.json" -Value $featureConfig -git add config.json -git commit -m "Add debug mode configuration" | Out-Null - -# Switch back to main branch -git switch main | Out-Null - -# Return to module directory -Set-Location .. - -Write-Host "`n========================================" -ForegroundColor Green -Write-Host "Challenge environment created!" -ForegroundColor Green -Write-Host "========================================" -ForegroundColor Green -Write-Host "`nYou are now on the 'main' branch." -ForegroundColor Cyan -Write-Host "There is a branch called 'update-config' with conflicting changes." -ForegroundColor Cyan -Write-Host "`nYour task:" -ForegroundColor Yellow -Write-Host "1. Navigate to the challenge directory: cd challenge" -ForegroundColor White -Write-Host "2. Try to merge the 'update-config' branch into 'main'" -ForegroundColor White -Write-Host "3. Resolve the merge conflict in config.json" -ForegroundColor White -Write-Host "4. Keep BOTH the timeout setting AND the debug setting" -ForegroundColor White -Write-Host "5. Complete the merge" -ForegroundColor White -Write-Host "`nRun '../verify.ps1' from the challenge directory to check your solution.`n" -ForegroundColor Cyan diff --git a/01_essentials/05-merge-conflicts/verify.ps1 b/01_essentials/05-merge-conflicts/verify.ps1 deleted file mode 100644 index 2abdca1..0000000 --- a/01_essentials/05-merge-conflicts/verify.ps1 +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env pwsh - -<# -.SYNOPSIS - Verifies the merge conflicts challenge solution. - -.DESCRIPTION - Checks that the user successfully resolved the merge conflict, - kept both configuration settings, and completed the merge. -#> - -Set-Location "challenge" -ErrorAction SilentlyContinue - -# Check if challenge directory exists -if (-not (Test-Path "../verify.ps1")) { - Write-Host "Error: Please run this script from the module directory" -ForegroundColor Red - exit 1 -} - -if (-not (Test-Path ".")) { - Write-Host "Error: Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red - Set-Location .. - exit 1 -} - -Write-Host "Verifying your solution..." -ForegroundColor Cyan - -# Check if git repository exists -if (-not (Test-Path ".git")) { - Write-Host "[FAIL] No git repository found." -ForegroundColor Red - Set-Location .. - exit 1 -} - -# Check current branch -$currentBranch = git branch --show-current 2>$null -if ($currentBranch -ne "main") { - Write-Host "[FAIL] You should be on the 'main' branch." -ForegroundColor Red - Write-Host "Current branch: $currentBranch" -ForegroundColor Yellow - Write-Host "Hint: Use 'git checkout main' to switch to main branch" -ForegroundColor Yellow - Set-Location .. - exit 1 -} - -# Check if there's an ongoing merge -if (Test-Path ".git/MERGE_HEAD") { - Write-Host "[FAIL] Merge is not complete. There are still unresolved conflicts." -ForegroundColor Red - Write-Host "Hint: After resolving conflicts in config.json, use:" -ForegroundColor Yellow - Write-Host " git add config.json" -ForegroundColor White - Write-Host " git commit" -ForegroundColor White - Set-Location .. - exit 1 -} - -# Check if config.json exists -if (-not (Test-Path "config.json")) { - Write-Host "[FAIL] config.json file not found." -ForegroundColor Red - Set-Location .. - exit 1 -} - -# Read and parse config.json -try { - $configContent = Get-Content "config.json" -Raw - $config = $configContent | ConvertFrom-Json -} catch { - Write-Host "[FAIL] config.json is not valid JSON." -ForegroundColor Red - Write-Host "Make sure you removed all conflict markers (<<<<<<, ======, >>>>>>)" -ForegroundColor Yellow - Set-Location .. - exit 1 -} - -# Check for conflict markers (in case user forgot to remove them) -if ($configContent -match "<<<<<<|======|>>>>>>") { - Write-Host "[FAIL] Conflict markers still present in config.json" -ForegroundColor Red - Write-Host "Remove all lines containing: <<<<<<, ======, >>>>>>" -ForegroundColor Yellow - Set-Location .. - exit 1 -} - -# Check if both timeout and debug settings exist -$hasTimeout = $null -ne $config.app.timeout -$hasDebug = $null -ne $config.app.debug - -if (-not $hasTimeout) { - Write-Host "[FAIL] The 'timeout' setting is missing from config.json" -ForegroundColor Red - Write-Host "Hint: The resolved file should include both timeout AND debug settings" -ForegroundColor Yellow - Set-Location .. - exit 1 -} - -if (-not $hasDebug) { - Write-Host "[FAIL] The 'debug' setting is missing from config.json" -ForegroundColor Red - Write-Host "Hint: The resolved file should include both timeout AND debug settings" -ForegroundColor Yellow - Set-Location .. - exit 1 -} - -# Validate the values -if ($config.app.timeout -ne 5000) { - Write-Host "[FAIL] The 'timeout' value should be 5000" -ForegroundColor Red - Set-Location .. - exit 1 -} - -if ($config.app.debug -ne $true) { - Write-Host "[FAIL] The 'debug' value should be true" -ForegroundColor Red - Set-Location .. - exit 1 -} - -# Check that merge commit exists -$commitCount = (git rev-list --count HEAD 2>$null) -if ($commitCount -lt 4) { - Write-Host "[FAIL] Not enough commits. Expected at least 4 commits (including merge commit)." -ForegroundColor Red - Write-Host "Current commits: $commitCount" -ForegroundColor Yellow - Set-Location .. - exit 1 -} - -# Check that the latest commit is a merge commit (has 2 parents) -$parentCount = (git rev-list --parents -n 1 HEAD 2>$null).Split(' ').Count - 1 -if ($parentCount -ne 2) { - Write-Host "[FAIL] The latest commit should be a merge commit." -ForegroundColor Red - Write-Host "Hint: Complete the merge with 'git commit' after resolving conflicts" -ForegroundColor Yellow - Set-Location .. - exit 1 -} - -# Check that both branches are merged -$branches = git branch --merged update-config 2>$null -Write-Host "$branches $($branches -notmatch 'update-config')" -if ($branches -notmatch "update-config") { - Write-Host "[FAIL] The 'update-config' branch was not merged." -ForegroundColor Red - Set-Location .. - exit 1 -} - -# Success! -Write-Host "`n========================================" -ForegroundColor Green -Write-Host "SUCCESS! Challenge completed!" -ForegroundColor Green -Write-Host "========================================" -ForegroundColor Green -Write-Host "`nYou have successfully:" -ForegroundColor Cyan -Write-Host "- Identified the merge conflict" -ForegroundColor White -Write-Host "- Resolved the conflict by keeping both settings" -ForegroundColor White -Write-Host "- Completed the merge with a proper merge commit" -ForegroundColor White -Write-Host "`nYou now understand how to handle merge conflicts!" -ForegroundColor Green -Write-Host "This is a critical skill for collaborative development.`n" -ForegroundColor Green - -Set-Location .. -exit 0 diff --git a/01_essentials/07-reset-vs-revert/README.md b/01_essentials/05-reset-vs-revert/README.md similarity index 100% rename from 01_essentials/07-reset-vs-revert/README.md rename to 01_essentials/05-reset-vs-revert/README.md diff --git a/01_essentials/07-reset-vs-revert/reset.ps1 b/01_essentials/05-reset-vs-revert/reset.ps1 similarity index 100% rename from 01_essentials/07-reset-vs-revert/reset.ps1 rename to 01_essentials/05-reset-vs-revert/reset.ps1 diff --git a/01_essentials/07-reset-vs-revert/setup.ps1 b/01_essentials/05-reset-vs-revert/setup.ps1 similarity index 100% rename from 01_essentials/07-reset-vs-revert/setup.ps1 rename to 01_essentials/05-reset-vs-revert/setup.ps1 diff --git a/01_essentials/07-reset-vs-revert/verify.ps1 b/01_essentials/05-reset-vs-revert/verify.ps1 similarity index 100% rename from 01_essentials/07-reset-vs-revert/verify.ps1 rename to 01_essentials/05-reset-vs-revert/verify.ps1 diff --git a/01_essentials/08-stash/README.md b/01_essentials/06-stash/README.md similarity index 100% rename from 01_essentials/08-stash/README.md rename to 01_essentials/06-stash/README.md diff --git a/01_essentials/08-stash/reset.ps1 b/01_essentials/06-stash/reset.ps1 similarity index 100% rename from 01_essentials/08-stash/reset.ps1 rename to 01_essentials/06-stash/reset.ps1 diff --git a/01_essentials/08-stash/setup.ps1 b/01_essentials/06-stash/setup.ps1 similarity index 100% rename from 01_essentials/08-stash/setup.ps1 rename to 01_essentials/06-stash/setup.ps1 diff --git a/01_essentials/08-stash/verify.ps1 b/01_essentials/06-stash/verify.ps1 similarity index 100% rename from 01_essentials/08-stash/verify.ps1 rename to 01_essentials/06-stash/verify.ps1 diff --git a/01_essentials/09-multiplayer/FACILITATOR-SETUP.md b/01_essentials/07-multiplayer/FACILITATOR-SETUP.md similarity index 100% rename from 01_essentials/09-multiplayer/FACILITATOR-SETUP.md rename to 01_essentials/07-multiplayer/FACILITATOR-SETUP.md diff --git a/01_essentials/09-multiplayer/README.md b/01_essentials/07-multiplayer/README.md similarity index 100% rename from 01_essentials/09-multiplayer/README.md rename to 01_essentials/07-multiplayer/README.md diff --git a/README.md b/README.md index 7c32828..7175f89 100644 --- a/README.md +++ b/README.md @@ -8,19 +8,17 @@ Perfect for developers who want to move beyond basic Git usage and master profes The workshop is organized into two tracks: -### 01 Essentials - Core Git Skills (9 modules) +### 01 Essentials - Core Git Skills (7 modules) Master fundamental Git concepts and collaborative workflows: - **Module 01: Git Basics** - Initialize repositories, stage changes, make commits - **Module 02: Viewing History** - Use git log and git diff to explore project history -- **Module 03: Branching Basics** - Create, switch, and manage branches -- **Module 04: Merging** - Combine branches and understand merge workflows -- **Module 05: Merge Conflicts** - Identify, understand, and resolve merge conflicts step-by-step -- **Module 06: Cherry-Pick** - Apply specific commits from one branch to another -- **Module 07: Reset vs Revert** - Understand when to rewrite history vs create new commits -- **Module 08: Stash** - Temporarily save work without committing -- **Module 09: Multiplayer Git** - **The Great Print Project** - Real cloud-based collaboration with teammates +- **Module 03: Branching and Merging** - Create branches, merge them, and resolve conflicts (checkpoint-based) +- **Module 04: Cherry-Pick** - Apply specific commits from one branch to another +- **Module 05: Reset vs Revert** - Understand when to rewrite history vs create new commits +- **Module 06: Stash** - Temporarily save work without committing +- **Module 07: Multiplayer Git** - **The Great Print Project** - Real cloud-based collaboration with teammates ### 02 Advanced - Professional Techniques (6 modules) @@ -46,7 +44,7 @@ Advanced Git workflows for power users: **Quick Reference**: See [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) for a comprehensive list of all Git commands covered in this workshop. Don't worry about memorizing everything - use this as a reference when you need to look up command syntax! -### For Module 09: Multiplayer Git +### For Module 07: Multiplayer Git **This module is different!** It uses a real Git server for authentic collaboration: @@ -138,9 +136,9 @@ You should see your name and email printed. This is required to make commits in $PSVersionTable.PSVersion ``` -### Python (for Module 09 only) +### Python (for Module 07 only) -Module 09 (Multiplayer Git) uses Python: +Module 07 (Multiplayer Git) uses Python: - **Python 3.6+** required to run the Great Print Project - Check: `python --version` or `python3 --version` @@ -211,7 +209,7 @@ Follow the instructions in each module's README.md file. - **Progressive Difficulty**: Builds from basics to advanced Git techniques - **Reset Anytime**: Each local module includes a reset script for a fresh start - **Self-Paced**: Learn at your own speed with detailed README guides -- **Real Collaboration**: Module 09 uses an actual Git server for authentic teamwork +- **Real Collaboration**: Module 07 uses an actual Git server for authentic teamwork - **Comprehensive Coverage**: From `git init` to advanced rebasing and bisecting ## Learning Path @@ -220,19 +218,19 @@ The modules are designed to build on each other: ### Recommended Progression -**Phase 1: Core Fundamentals (Essentials 01-03)** -- Git Basics, History, Branching -- **Goal**: Understand commits and branches +**Phase 1: Core Fundamentals (Essentials 01-02)** +- Git Basics, History +- **Goal**: Understand commits and history -**Phase 2: Collaboration Basics (Essentials 04-05)** -- Merging, Merge Conflicts -- **Goal**: Work with multiple branches +**Phase 2: Collaboration Basics (Essentials 03)** +- Branching and Merging (checkpoint-based: branching, merging, conflicts) +- **Goal**: Work with multiple branches and resolve conflicts -**Phase 3: Workflow Tools (Essentials 06-08)** +**Phase 3: Workflow Tools (Essentials 04-06)** - Cherry-Pick, Reset vs Revert, Stash - **Goal**: Manage your work effectively -**Phase 4: Real Collaboration (Essentials 09)** +**Phase 4: Real Collaboration (Essentials 07)** - **Multiplayer Git - The Great Print Project** - **Goal**: Apply all skills with real teammates on a cloud server - **Note**: This is a capstone module - bring everything together! @@ -245,14 +243,14 @@ The modules are designed to build on each other: ### Alternative Paths **Fast Track (1 day workshop):** -- Essentials 01-05 + Essentials 09 (Multiplayer) +- Essentials 01-03 + Essentials 07 (Multiplayer) **Solo Learner:** -- Complete Essentials 01-08, skip 09 (requires partners and server) +- Complete Essentials 01-06, skip 07 (requires partners and server) - Or complete all Advanced modules for deep mastery **Team Workshop:** -- Essentials 01-05 then jump to 09 (Multiplayer) for collaborative practice +- Essentials 01-03 then jump to 07 (Multiplayer) for collaborative practice ## Tips for Success @@ -263,7 +261,7 @@ The modules are designed to build on each other: - **Use `git log --oneline --graph --all`** frequently to visualize repository state - **If stuck**, check the Key Concepts section in the module's README - **Consider installing glow** for better markdown reading experience -- **For Module 09**, work with a partner - collaboration is the point! +- **For Module 07**, work with a partner - collaboration is the point! ## Skills You'll Master @@ -307,7 +305,7 @@ Before distributing this workshop to attendees for self-study: 2. Each module's `challenge/` directory will become its own independent git repository when attendees run `setup.ps1` 3. This isolation ensures each module provides a clean learning environment -**Note**: Module 09 (Multiplayer) requires you to set up a Git server - see facilitator guide below. +**Note**: Module 07 (Multiplayer) requires you to set up a Git server - see facilitator guide below. ### Facilitated Workshop @@ -315,13 +313,13 @@ For running this as a full-day instructor-led workshop: 1. **See [WORKSHOP-AGENDA.md](WORKSHOP-AGENDA.md)** - Complete agenda with timing, activities, and facilitation tips 2. **See [PRESENTATION-OUTLINE.md](PRESENTATION-OUTLINE.md)** - Slide deck outline for presentations -3. **Workshop covers:** Essentials 01-05 + Module 09 (Multiplayer collaboration exercise) +3. **Workshop covers:** Essentials 01-05 + Module 07 (Multiplayer collaboration exercise) 4. **Duration:** 6-7 hours including breaks 5. **Format:** Mix of presentation, live demos, and hands-on challenges **Facilitator preparation:** - Review the workshop agenda thoroughly -- Set up Git server for Module 09 (see below) +- Set up Git server for Module 07 (see below) - Ensure all participants have prerequisites installed (Git, PowerShell, Python) - Prepare slides using the presentation outline - Test all modules on a clean machine @@ -329,9 +327,9 @@ For running this as a full-day instructor-led workshop: The workshop format combines instructor-led sessions with self-paced hands-on modules for an engaging learning experience. -### Setting Up Module 09: Multiplayer Git +### Setting Up Module 07: Multiplayer Git -Module 09 requires a Git server for authentic collaboration. You have two options: +Module 07 requires a Git server for authentic collaboration. You have two options: **Option 1: Self-Hosted Gitea Server (Recommended)** @@ -376,18 +374,16 @@ git-workshop/ ├── GITEA-SETUP.md # Self-hosted Git server setup ├── install-glow.ps1 # Install glow markdown renderer │ -├── 01_essentials/ # Core Git skills (9 modules) +├── 01_essentials/ # Core Git skills (7 modules) │ ├── 01-basics/ # Initialize, commit, status │ ├── 02-history/ # Log, diff, show -│ ├── 03-branching/ # Create and switch branches -│ ├── 04-merging/ # Merge branches -│ ├── 05-merge-conflicts/ # Resolve conflicts step-by-step -│ ├── 06-cherry-pick/ # Apply specific commits -│ ├── 07-reset-vs-revert/ # Undo changes safely -│ ├── 08-stash/ # Save work-in-progress -│ └── 09-multiplayer/ # Real collaboration (cloud-based) -│ ├── README.md # Student guide (1,408 lines) -│ └── FACILITATOR-SETUP.md # Server setup guide (904 lines) +│ ├── 03-branching-and-merging/ # Branches, merging, conflicts (checkpoint-based) +│ ├── 04-cherry-pick/ # Apply specific commits +│ ├── 05-reset-vs-revert/ # Undo changes safely +│ ├── 06-stash/ # Save work-in-progress +│ └── 07-multiplayer/ # Real collaboration (cloud-based) +│ ├── README.md # Student guide +│ └── FACILITATOR-SETUP.md # Server setup guide │ └── 02_advanced/ # Professional techniques (6 modules) ├── 01-rebasing/ # Linear history with rebase @@ -400,9 +396,9 @@ git-workshop/ ## What's Unique About This Workshop -### The Great Print Project (Module 09) +### The Great Print Project (Module 07) -Unlike any other Git tutorial, Module 09 provides **real collaborative experience**: +Unlike any other Git tutorial, Module 07 provides **real collaborative experience**: - **Real Git server**: Not simulated - actual cloud repository at https://git.frod.dk/multiplayer - **Real teammates**: Work in pairs on shared branches @@ -429,7 +425,7 @@ This is how professional developers actually work - no simulation, no shortcuts. **Q: Do I need to complete all modules?** A: No! Essentials 01-05 covers what most developers use daily. Complete 06-09 and Advanced modules to deepen your skills. -**Q: Can I do Module 09 (Multiplayer) without a partner?** +**Q: Can I do Module 07 (Multiplayer) without a partner?** A: Not recommended - collaboration is the point. If solo, skip to Advanced modules or wait until you can pair with someone. **Q: How long does the workshop take?** @@ -445,16 +441,16 @@ A: 2. Check [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) 3. Run `./reset.ps1` to start fresh 4. Use `git status` and `git log --graph` to understand current state -5. For Module 09, ask your partner or facilitator +5. For Module 07, ask your partner or facilitator **Q: Can I use this for a team workshop at my company?** A: Absolutely! See the "For Workshop Facilitators" section above. The materials are designed for both self-study and instructor-led workshops. **Q: Do I need internet access?** -A: Modules 01-08 work completely offline. Module 09 requires internet to access the Git server. +A: Modules 01-08 work completely offline. Module 07 requires internet to access the Git server. **Q: What if I prefer GitHub/GitLab instead of Gitea?** -A: The skills are identical across all Git platforms. Module 09 uses Gitea but everything you learn applies to GitHub, GitLab, Bitbucket, etc. +A: The skills are identical across all Git platforms. Module 07 uses Gitea but everything you learn applies to GitHub, GitLab, Bitbucket, etc. ---