Compare commits

2 Commits

Author SHA1 Message Date
Bjarke Sporring
cdd695b250 fix: cleanup revert module 2026-01-15 16:29:06 +01:00
Bjarke Sporring
0474a6de0e fix: remove revert-middle challenge 2026-01-15 16:23:32 +01:00
3 changed files with 21 additions and 335 deletions

View File

@@ -18,10 +18,9 @@ Welcome to Module 06, where you'll learn the **safe, team-friendly way to undo c
By completing this module, you will: By completing this module, you will:
1. Revert commits safely while preserving surrounding changes 1. Revert commits safely while preserving surrounding changes
2. Revert old commits in the middle of history 2. Understand how revert creates new commits instead of erasing history
3. Understand how revert preserves commits before and after the target 3. Revert multiple commits at once
4. Revert multiple commits at once 4. Know when to use revert vs. other undo strategies
5. Know when to use revert vs. other undo strategies
## Prerequisites ## Prerequisites
@@ -38,9 +37,8 @@ Run the setup script to create the challenge environment:
.\setup.ps1 .\setup.ps1
``` ```
This creates a `challenge/` directory with three branches demonstrating different revert scenarios: This creates a `challenge/` directory with two branches demonstrating different revert scenarios:
- `regular-revert` - Basic commit reversion - `regular-revert` - Basic commit reversion
- `middle-revert` - Reverting a commit in the middle of history
- `multi-revert` - Multiple commit reversion - `multi-revert` - Multiple commit reversion
## Challenge 1: Reverting a Regular Commit ## Challenge 1: Reverting a Regular Commit
@@ -119,110 +117,7 @@ main.py (initial) → multiply (good) → divide (BAD) → modulo (good) → rev
The revert commit adds a new point in history that undoes the divide changes. The revert commit adds a new point in history that undoes the divide changes.
## Challenge 2: Reverting a Commit in the Middle ## Challenge 2: Reverting Multiple Commits
### Scenario
You're working on improving your calculator application. Several commits were made in sequence:
1. Added input validation (good)
2. Added output formatter (BAD - has bugs!)
3. Added configuration module (good - but came after the bad commit)
The formatter has critical bugs and needs to be removed, but you want to keep both the validation module (added before) and the configuration module (added after).
**This demonstrates an important Git principle:** Revert works on ANY commit in history, not just recent ones!
### Understanding History Preservation
Here's what the commit history looks like:
```
A (initial) → B (validation) → C (formatter BAD) → D (config)
We want to remove THIS
```
When you revert commit C:
```
A (initial) → B (validation) → C (formatter BAD) → D (config) → E (revert C)
Removes formatter, keeps validation & config
```
**Key insight:** The revert creates a NEW commit (E) that undoes commit C, but leaves B and D completely intact!
### Your Task
1. **Switch to the middle-revert branch:**
```pwsh
git switch middle-revert
```
2. **View the commit history:**
```pwsh
git log --oneline
```
You should see three commits after the initial:
- "Add input validation module"
- "Add broken formatter - needs to be reverted!"
- "Add configuration module"
3. **Find the broken formatter commit:**
- Look for the message: "Add broken formatter - needs to be reverted!"
- Note the commit hash (the 7-character code)
- Write it down
4. **Revert that middle commit** (replace `<commit-hash>` with actual hash):
```pwsh
git revert <commit-hash>
```
5. **Visual Studio Code will open** with the revert commit message:
- The default message is fine
- Close the editor window to accept it
- Git will create the revert commit
6. **Check the result:**
```pwsh
# View files - formatter.py should be gone
ls
# You should see validation.py and config.py but NOT formatter.py
# View the history
git log --oneline
# You should see the new revert commit at the top
```
### What to Observe
After reverting, notice:
```pwsh
# Check which files exist
ls
# You should see:
# - calculator.py (from initial commit)
# - validation.py (from commit BEFORE bad one) ✅
# - config.py (from commit AFTER bad one) ✅
# - formatter.py is GONE (reverted) ❌
```
**Important:** Git successfully removed the bad formatter while keeping everything else!
### Why This Matters
This scenario demonstrates revert's power in real-world situations:
- You discover a bug in code committed days or weeks ago
- Many commits have been made since then
- You can't just delete the old commit (that would break history)
- Revert lets you surgically remove just the bad commit
**Revert is your "undo button" for shared history!**
## Challenge 3: Reverting Multiple Commits
### Scenario ### Scenario
@@ -303,7 +198,7 @@ This is useful when reverting multiple commits and you want one combined revert
## Verification ## Verification
After completing all three challenges, verify your solutions: After completing both challenges, verify your solutions:
```pwsh ```pwsh
cd .. # Return to module directory (if you're in challenge/) cd .. # Return to module directory (if you're in challenge/)
@@ -320,7 +215,6 @@ The script checks that:
- ✅ Revert commits were created (not destructive deletion) - ✅ Revert commits were created (not destructive deletion)
- ✅ Bad code is removed - ✅ Bad code is removed
- ✅ Good code before and after is preserved - ✅ Good code before and after is preserved
- ✅ Revert works on commits in the middle of history
## Command Reference ## Command Reference
@@ -399,10 +293,10 @@ Use `git revert` when:
Consider alternatives when: Consider alternatives when:
- ❌ **Commits are still local** - Use `git reset` instead (Module 06) - ❌ **Commits are still local** - Use `git reset` instead (advanced module)
- ❌ **Just want to edit a commit** - Use `git commit --amend` - ❌ **Just want to edit a commit** - Use `git commit --amend`
- ❌ **Haven't pushed yet** - Reset is cleaner for local cleanup - ❌ **Haven't pushed yet** - Reset is cleaner for local cleanup, but more dangerous, stick to revert if in doubt
- ❌ **Need to combine commits** - Use interactive rebase - ❌ **Need to combine commits** - Use interactive rebase IF nothing has been pushed to cloud
- ❌ **Reverting creates complex conflicts** - Might need manual fix forward - ❌ **Reverting creates complex conflicts** - Might need manual fix forward
## Revert vs. Reset vs. Rebase ## Revert vs. Reset vs. Rebase
@@ -450,7 +344,7 @@ git revert --abort
### 1. Using Reset on Pushed Commits ### 1. Using Reset on Pushed Commits
```pwsh ```pwsh
# ❌ NEVER do this with pushed commits # ❌ NEVER do this with pushed commits. Or at least try your best to avoid it.
git reset --hard HEAD~3 git reset --hard HEAD~3
# ✅ Do this instead # ✅ Do this instead
@@ -504,100 +398,3 @@ git revert C
- Revert the minimum necessary - Revert the minimum necessary
- Don't bundle multiple unrelated reverts - Don't bundle multiple unrelated reverts
- One problem = one revert commit - One problem = one revert commit
## Troubleshooting
### "Empty Revert / No Changes"
**Problem:** Revert doesn't seem to do anything.
**Possible causes:**
- Commit was already reverted
- Subsequent commits already undid the changes
- Wrong commit hash
**Solution:**
```pwsh
# Check what the commit actually changed
git show <commit-hash>
# Check if already reverted
git log --grep="Revert"
```
### "Conflicts During Revert"
**Problem:** Revert causes merge conflicts.
**Why:** Subsequent commits modified the same code.
**Solution:**
1. Manually resolve conflicts in affected files
2. `git add <resolved-files>`
3. `git revert --continue`
Or consider fixing forward with a new commit instead of reverting.
### "Reverting Old Commit Breaks Something"
**Problem:** After reverting an old commit, something else stops working.
**Why:** The old commit might have been a dependency for later commits.
**Solution:**
1. Check what changed: `git diff HEAD~1 HEAD`
2. Either fix the issue with a new commit, or
3. Revert the revert if needed: `git revert <revert-commit-hash>`
## Advanced: Revert Internals
Understanding what revert does under the hood:
```pwsh
# Revert creates a new commit with inverse changes
git revert <commit-hash>
# This is equivalent to:
git diff <commit-hash>^..<commit-hash> > changes.patch
patch -R < changes.patch # Apply in reverse
git add .
git commit -m "Revert '<original message>'"
```
**Key insight:** Revert computes the diff of the target commit, inverts it, and applies it as a new commit.
## Going Further
Now that you understand revert, you're ready for:
- **Module 06: Git Reset** - Learn the dangerous but powerful local history rewriting
- **Module 07: Git Stash** - Temporarily set aside uncommitted changes
- **Module 08: Multiplayer Git** - Collaborate with advanced workflows
## Summary
You've learned:
- ✅ `git revert` creates new commits that undo previous changes
- ✅ Revert is safe for shared/pushed commits
- ✅ Revert works on any commit in history, even old ones
- ✅ Commits before and after the reverted commit are preserved
- ✅ Multiple commits can be reverted in one command
- ✅ Revert preserves complete history for audit trails
**The Golden Rule of Revert:** Use revert for any commit that might be shared with others.
## Next Steps
1. Complete all three challenge scenarios
2. Run `./verify.ps1` to check your solutions
3. Experiment with reverting different commits
4. Move on to Module 06: Git Reset (dangerous but powerful!)
---
**Need Help?**
- Review the command reference above
- Check the troubleshooting section
- Re-run `./setup.ps1` to start fresh
- Practice reverting in different orders to understand the behavior

View File

@@ -4,10 +4,9 @@
Sets up the Module 06 challenge environment for learning git revert. Sets up the Module 06 challenge environment for learning git revert.
.DESCRIPTION .DESCRIPTION
This script creates a challenge directory with three branches demonstrating This script creates a challenge directory with two branches demonstrating
different revert scenarios: different revert scenarios:
- regular-revert: Basic revert of a single bad commit at the end - regular-revert: Basic revert of a single bad commit
- middle-revert: Reverting a bad commit in the middle of history
- multi-revert: Reverting multiple commits at once - multi-revert: Reverting multiple commits at once
#> #>
@@ -104,68 +103,9 @@ git commit -m "Add modulo function" | Out-Null
Write-Host "[CREATED] regular-revert branch with bad divide commit" -ForegroundColor Green Write-Host "[CREATED] regular-revert branch with bad divide commit" -ForegroundColor Green
# ============================================================================ # ============================================================================
# SCENARIO 2: Revert in Middle of History # SCENARIO 2: Multi Revert (Multiple Bad Commits)
# ============================================================================ # ============================================================================
Write-Host "`nScenario 2: Creating middle-revert scenario..." -ForegroundColor Cyan Write-Host "`nScenario 2: Creating multi-revert branch..." -ForegroundColor Cyan
# Switch back to main
git switch $mainBranch | Out-Null
# Create middle-revert branch
git switch -c middle-revert | Out-Null
# Good commit: Add validation module
$validationContent = @"
# validation.py - Input validation
def validate_number(value):
"""Check if value is a valid number."""
try:
float(value)
return True
except ValueError:
return False
"@
Set-Content -Path "validation.py" -Value $validationContent
git add .
git commit -m "Add input validation module" | Out-Null
# BAD commit: Add broken formatter
$formatterContent = @"
# formatter.py - Output formatting
def format_result(result):
"""BROKEN: Doesn't handle None or errors properly!"""
return f"Result: {result.upper()}" # This crashes if result is not a string!
"@
Set-Content -Path "formatter.py" -Value $formatterContent
git add .
git commit -m "Add broken formatter - needs to be reverted!" | Out-Null
# Good commit: Add configuration (depends on validation, not formatter)
$configContent = @"
# config.py - Application configuration
from validation import validate_number
DEFAULT_PRECISION = 2
def set_precision(value):
"""Set calculation precision."""
if validate_number(value):
return int(value)
return DEFAULT_PRECISION
"@
Set-Content -Path "config.py" -Value $configContent
git add .
git commit -m "Add configuration module" | Out-Null
Write-Host "[CREATED] middle-revert branch with bad commit in the middle" -ForegroundColor Green
# ============================================================================
# SCENARIO 3: Multi Revert (Multiple Bad Commits)
# ============================================================================
Write-Host "`nScenario 3: Creating multi-revert branch..." -ForegroundColor Cyan
# Switch back to main # Switch back to main
git switch $mainBranch | Out-Null git switch $mainBranch | Out-Null
@@ -247,10 +187,9 @@ git switch regular-revert | Out-Null
Set-Location .. Set-Location ..
Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green
Write-Host "`nThree revert scenarios have been created:" -ForegroundColor Cyan Write-Host "`nTwo revert scenarios have been created:" -ForegroundColor Cyan
Write-Host " 1. regular-revert - Revert a bad commit at the end" -ForegroundColor White Write-Host " 1. regular-revert - Revert a single bad commit" -ForegroundColor White
Write-Host " 2. middle-revert - Revert a bad commit in the middle of history" -ForegroundColor White Write-Host " 2. multi-revert - Revert multiple bad commits" -ForegroundColor White
Write-Host " 3. multi-revert - Revert multiple bad commits" -ForegroundColor White
Write-Host "`nYou are currently on the 'regular-revert' branch." -ForegroundColor Cyan Write-Host "`nYou are currently on the 'regular-revert' branch." -ForegroundColor Cyan
Write-Host "`nNext steps:" -ForegroundColor Cyan Write-Host "`nNext steps:" -ForegroundColor Cyan
Write-Host " 1. cd challenge" -ForegroundColor White Write-Host " 1. cd challenge" -ForegroundColor White

View File

@@ -4,9 +4,8 @@
Verifies the Module 06 challenge solutions. Verifies the Module 06 challenge solutions.
.DESCRIPTION .DESCRIPTION
Checks that all three revert scenarios have been completed correctly: Checks that both revert scenarios have been completed correctly:
- regular-revert: Single commit reverted - regular-revert: Single commit reverted
- middle-revert: Commit in middle of history reverted
- multi-revert: Multiple commits reverted - multi-revert: Multiple commits reverted
#> #>
@@ -87,57 +86,9 @@ if ($LASTEXITCODE -ne 0) {
} }
# ============================================================================ # ============================================================================
# SCENARIO 2: Middle Revert Verification # SCENARIO 2: Multi Revert Verification
# ============================================================================ # ============================================================================
Write-Host "`n=== Scenario 2: Middle Revert ===" -ForegroundColor Cyan Write-Host "`n=== Scenario 2: Multi Revert ===" -ForegroundColor Cyan
git switch middle-revert 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host "[FAIL] middle-revert branch not found" -ForegroundColor Red
$allChecksPassed = $false
} else {
# Check that a revert commit exists
$revertCommit = git log --oneline --grep="Revert" 2>$null
if ($revertCommit) {
Write-Host "[PASS] Revert commit found" -ForegroundColor Green
} else {
Write-Host "[FAIL] No revert commit found" -ForegroundColor Red
Write-Host "[HINT] Use: git revert <commit-hash>" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check that formatter.py is removed (reverted)
if (-not (Test-Path "formatter.py")) {
Write-Host "[PASS] Broken formatter.py successfully reverted (file removed)" -ForegroundColor Green
} else {
Write-Host "[FAIL] formatter.py still exists (should be reverted)" -ForegroundColor Red
Write-Host "[HINT] The bad commit should be reverted, removing formatter.py" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check that validation.py still exists (good commit before bad one)
if (Test-Path "validation.py") {
Write-Host "[PASS] validation.py preserved (good commit before bad one)" -ForegroundColor Green
} else {
Write-Host "[FAIL] validation.py missing (should still exist)" -ForegroundColor Red
$allChecksPassed = $false
}
# Check that config.py still exists (good commit after bad one)
if (Test-Path "config.py") {
Write-Host "[PASS] config.py preserved (good commit after bad one)" -ForegroundColor Green
} else {
Write-Host "[FAIL] config.py missing (should still exist)" -ForegroundColor Red
Write-Host "[HINT] Only revert the bad commit, not the good ones after it" -ForegroundColor Yellow
$allChecksPassed = $false
}
}
# ============================================================================
# SCENARIO 3: Multi Revert Verification
# ============================================================================
Write-Host "`n=== Scenario 3: Multi Revert ===" -ForegroundColor Cyan
git switch multi-revert 2>&1 | Out-Null git switch multi-revert 2>&1 | Out-Null
@@ -209,9 +160,8 @@ if ($allChecksPassed) {
Write-Host "`nYou've mastered git revert!" -ForegroundColor Cyan Write-Host "`nYou've mastered git revert!" -ForegroundColor Cyan
Write-Host "You now understand:" -ForegroundColor Cyan Write-Host "You now understand:" -ForegroundColor Cyan
Write-Host " ✓ Reverting commits safely without erasing history" -ForegroundColor White Write-Host " ✓ Reverting commits safely without erasing history" -ForegroundColor White
Write-Host " ✓ Reverting old commits in the middle of history" -ForegroundColor White
Write-Host " ✓ Reverting multiple commits at once" -ForegroundColor White Write-Host " ✓ Reverting multiple commits at once" -ForegroundColor White
Write-Host " ✓ Preserving commits before and after the reverted one" -ForegroundColor White Write-Host " ✓ Preserving all other commits while undoing specific changes" -ForegroundColor White
Write-Host "`nReady for Module 07: Git Reset!" -ForegroundColor Green Write-Host "`nReady for Module 07: Git Reset!" -ForegroundColor Green
Write-Host "" Write-Host ""
exit 0 exit 0