refactor: rewrite the merge-revert section
It is an advanced and difficult revert to accomplish and should probably be done through a reset instead, which means that we're modifying history which is dangerous and so should be handled by someone who understands these dangers.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# Module 05: Git Revert - Safe Undoing
|
||||
# Module 06: Git Revert - Safe Undoing
|
||||
|
||||
## About This Module
|
||||
|
||||
Welcome to Module 05, where you'll learn the **safe, team-friendly way to undo changes** in Git. Unlike destructive commands that erase history, `git revert` creates new commits that undo previous changes while preserving the complete project history.
|
||||
Welcome to Module 06, where you'll learn the **safe, team-friendly way to undo changes** in Git. Unlike destructive commands that erase history, `git revert` creates new commits that undo previous changes while preserving the complete project history.
|
||||
|
||||
**Why revert is important:**
|
||||
- ✅ Safe for shared/pushed commits
|
||||
@@ -17,19 +17,18 @@ Welcome to Module 05, where you'll learn the **safe, team-friendly way to undo c
|
||||
|
||||
By completing this module, you will:
|
||||
|
||||
1. Revert regular commits safely while preserving surrounding changes
|
||||
2. Revert merge commits using the `-m` flag
|
||||
3. Understand merge commit parent numbering
|
||||
4. Handle the re-merge problem that occurs after reverting merges
|
||||
5. Revert multiple commits at once
|
||||
6. Know when to use revert vs. other undo strategies
|
||||
1. Revert commits safely while preserving surrounding changes
|
||||
2. Revert old commits in the middle of history
|
||||
3. Understand how revert preserves commits before and after the target
|
||||
4. Revert multiple commits at once
|
||||
5. Know when to use revert vs. other undo strategies
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting this module, you should be comfortable with:
|
||||
- Creating commits (`git commit`)
|
||||
- Viewing commit history (`git log`)
|
||||
- Understanding branches and merging (Module 03)
|
||||
- Understanding branches (Module 03)
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -41,7 +40,7 @@ Run the setup script to create the challenge environment:
|
||||
|
||||
This creates a `challenge/` directory with three branches demonstrating different revert scenarios:
|
||||
- `regular-revert` - Basic commit reversion
|
||||
- `merge-revert` - Merge commit reversion
|
||||
- `middle-revert` - Reverting a commit in the middle of history
|
||||
- `multi-revert` - Multiple commit reversion
|
||||
|
||||
## Challenge 1: Reverting a Regular Commit
|
||||
@@ -120,140 +119,108 @@ main.py (initial) → multiply (good) → divide (BAD) → modulo (good) → rev
|
||||
|
||||
The revert commit adds a new point in history that undoes the divide changes.
|
||||
|
||||
## Challenge 2: Reverting a Merge Commit
|
||||
## Challenge 2: Reverting a Commit in the Middle
|
||||
|
||||
### Scenario
|
||||
|
||||
Your team merged a `feature-auth` branch that added authentication functionality. After deployment, you discovered the authentication system has critical security issues. You need to revert the entire merge while the security team redesigns the feature.
|
||||
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)
|
||||
|
||||
**This is different from reverting a regular commit!** Merge commits have **two parents**, so you must tell Git which parent to keep.
|
||||
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).
|
||||
|
||||
### Understanding Merge Commit Parents
|
||||
**This demonstrates an important Git principle:** Revert works on ANY commit in history, not just recent ones!
|
||||
|
||||
When you merge a feature branch into main:
|
||||
### Understanding History Preservation
|
||||
|
||||
Here's what the commit history looks like:
|
||||
|
||||
```
|
||||
feature-auth (parent 2)
|
||||
↓
|
||||
C---D
|
||||
/ \
|
||||
A---B-----M ← Merge commit (has TWO parents)
|
||||
↑
|
||||
parent 1 (main)
|
||||
A (initial) → B (validation) → C (formatter BAD) → D (config)
|
||||
↑
|
||||
We want to remove THIS
|
||||
```
|
||||
|
||||
The merge commit `M` has:
|
||||
- **Parent 1**: The branch you merged INTO (main)
|
||||
- **Parent 2**: The branch you merged FROM (feature-auth)
|
||||
When you revert commit C:
|
||||
|
||||
When reverting a merge, you must specify which parent to keep using the `-m` flag:
|
||||
- `-m 1` means "keep parent 1" (main) - **Most common**
|
||||
- `-m 2` means "keep parent 2" (feature-auth) - Rare
|
||||
```
|
||||
A (initial) → B (validation) → C (formatter BAD) → D (config) → E (revert C)
|
||||
↑
|
||||
Removes formatter, keeps validation & config
|
||||
```
|
||||
|
||||
**In practice:** You almost always use `-m 1` to keep the main branch and undo the feature branch changes.
|
||||
**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 merge-revert branch:**
|
||||
1. **Switch to the middle-revert branch:**
|
||||
```pwsh
|
||||
git switch merge-revert
|
||||
git switch middle-revert
|
||||
```
|
||||
|
||||
2. **View the commit history with the graph:**
|
||||
2. **View the commit history:**
|
||||
```pwsh
|
||||
git log --oneline --graph
|
||||
git log --oneline
|
||||
```
|
||||
|
||||
Look for the merge commit message: "Merge feature-auth branch"
|
||||
- Note the commit hash
|
||||
- Write it down or copy it
|
||||
You should see three commits after the initial:
|
||||
- "Add input validation module"
|
||||
- "Add broken formatter - needs to be reverted!"
|
||||
- "Add configuration module"
|
||||
|
||||
3. **Revert the merge commit using `-m 1`** (replace `<merge-commit-hash>` with actual hash):
|
||||
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 -m 1 <merge-commit-hash>
|
||||
git revert <commit-hash>
|
||||
```
|
||||
|
||||
**What `-m 1` means:**
|
||||
- `-m 1` tells Git to keep parent 1 (the main branch side)
|
||||
- This undoes all changes from the feature-auth branch
|
||||
- Creates a new "revert merge" commit
|
||||
|
||||
4. **Visual Studio Code will open** with the revert commit message:
|
||||
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
|
||||
|
||||
5. **Check the result:**
|
||||
6. **Check the result:**
|
||||
```pwsh
|
||||
# View files - auth.py should be gone
|
||||
# View files - formatter.py should be gone
|
||||
ls
|
||||
# You should see calculator.py but NOT auth.py
|
||||
# You should see validation.py and config.py but NOT formatter.py
|
||||
|
||||
# Verify calculator.py no longer imports auth
|
||||
cat calculator.py
|
||||
# Should NOT see "from auth import" anywhere
|
||||
# View the history
|
||||
git log --oneline
|
||||
# You should see the new revert commit at the top
|
||||
```
|
||||
|
||||
### What Happens Without -m?
|
||||
### What to Observe
|
||||
|
||||
If you try to revert a merge commit without the `-m` flag:
|
||||
After reverting, notice:
|
||||
|
||||
```bash
|
||||
git revert <merge-commit-hash>
|
||||
# Error: commit <hash> is a merge but no -m option was given
|
||||
```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) ❌
|
||||
```
|
||||
|
||||
Git doesn't know which parent you want to keep, so it refuses to proceed.
|
||||
**Important:** Git successfully removed the bad formatter while keeping everything else!
|
||||
|
||||
### The Re-Merge Problem
|
||||
### Why This Matters
|
||||
|
||||
**Important gotcha:** After reverting a merge, you **cannot simply re-merge** the same branch!
|
||||
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
|
||||
|
||||
Here's why:
|
||||
|
||||
```
|
||||
Initial merge:
|
||||
A---B---M (merged feature-auth)
|
||||
↑
|
||||
All changes from feature-auth are now in main
|
||||
|
||||
After revert:
|
||||
A---B---M---R (reverted merge)
|
||||
↑
|
||||
Changes removed, but Git remembers they were merged
|
||||
|
||||
Attempting to re-merge:
|
||||
A---B---M---R---M2 (try to merge feature-auth again)
|
||||
↑
|
||||
Git thinks: "I already merged these commits,
|
||||
nothing new to add!" (Empty merge)
|
||||
```
|
||||
|
||||
**Solutions if you need to re-merge:**
|
||||
|
||||
1. **Revert the revert** (recommended):
|
||||
```bash
|
||||
git revert <revert-commit-hash>
|
||||
```
|
||||
This brings back all the feature-auth changes.
|
||||
|
||||
2. **Cherry-pick new commits** from the feature branch:
|
||||
```bash
|
||||
git cherry-pick <new-commits>
|
||||
```
|
||||
|
||||
3. **Merge with --no-ff** and resolve conflicts manually (advanced).
|
||||
|
||||
### When to Revert Merges
|
||||
|
||||
Revert merge commits when:
|
||||
- ✅ Feature causes production issues
|
||||
- ✅ Need to temporarily remove a feature
|
||||
- ✅ Discovered critical bugs after merging
|
||||
- ✅ Security issues require immediate rollback
|
||||
|
||||
Don't revert merges when:
|
||||
- ❌ You just need to fix a small bug (fix it with a new commit instead)
|
||||
- ❌ You plan to re-merge the same branch soon (use reset if local, or revert-the-revert later)
|
||||
**Revert is your "undo button" for shared history!**
|
||||
|
||||
## Challenge 3: Reverting Multiple Commits
|
||||
|
||||
@@ -311,7 +278,7 @@ Two separate commits added broken mathematical functions (`square_root` and `log
|
||||
|
||||
**Reverting a range of commits:**
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# Revert commits from A to B (inclusive)
|
||||
git revert A^..B
|
||||
|
||||
@@ -321,7 +288,7 @@ git revert HEAD~3..HEAD
|
||||
|
||||
**Reverting without auto-commit:**
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# Stage revert changes without committing
|
||||
git revert --no-commit <commit-hash>
|
||||
|
||||
@@ -353,8 +320,7 @@ The script checks that:
|
||||
- ✅ Revert commits were created (not destructive deletion)
|
||||
- ✅ Bad code is removed
|
||||
- ✅ Good code before and after is preserved
|
||||
- ✅ Merge commits still exist in history
|
||||
- ✅ Proper use of `-m` flag for merge reverts
|
||||
- ✅ Revert works on commits in the middle of history
|
||||
|
||||
## Command Reference
|
||||
|
||||
@@ -371,14 +337,17 @@ git revert HEAD
|
||||
git revert HEAD~1
|
||||
```
|
||||
|
||||
### Merge Commit Revert
|
||||
### Reverting Old Commits
|
||||
|
||||
```pwsh
|
||||
# Revert a merge commit (keep parent 1)
|
||||
git revert -m 1 <merge-commit-hash>
|
||||
# Revert a specific commit from any point in history
|
||||
git revert <commit-hash>
|
||||
|
||||
# Revert a merge commit (keep parent 2) - rare
|
||||
git revert -m 2 <merge-commit-hash>
|
||||
# Revert a commit from 5 commits ago
|
||||
git revert HEAD~5
|
||||
|
||||
# View what a commit changed before reverting
|
||||
git show <commit-hash>
|
||||
```
|
||||
|
||||
### Multiple Commits
|
||||
@@ -450,7 +419,7 @@ Consider alternatives when:
|
||||
|
||||
Sometimes reverting causes conflicts if subsequent changes touched the same code:
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# Start revert
|
||||
git revert <commit-hash>
|
||||
|
||||
@@ -463,47 +432,24 @@ git revert <commit-hash>
|
||||
|
||||
1. Open conflicted files and fix conflicts (look for `<<<<<<<` markers)
|
||||
2. Stage resolved files:
|
||||
```bash
|
||||
```pwsh
|
||||
git add <resolved-files>
|
||||
```
|
||||
3. Continue the revert:
|
||||
```bash
|
||||
```pwsh
|
||||
git revert --continue
|
||||
```
|
||||
|
||||
Or abort if you change your mind:
|
||||
```bash
|
||||
```pwsh
|
||||
git revert --abort
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### 1. Forgetting -m for Merge Commits
|
||||
### 1. Using Reset on Pushed Commits
|
||||
|
||||
```bash
|
||||
# ❌ Wrong - will fail
|
||||
git revert <merge-commit>
|
||||
|
||||
# ✅ Correct
|
||||
git revert -m 1 <merge-commit>
|
||||
```
|
||||
|
||||
### 2. Trying to Re-Merge After Revert
|
||||
|
||||
```bash
|
||||
# After reverting a merge:
|
||||
git revert -m 1 <merge-commit>
|
||||
|
||||
# ❌ This won't work as expected
|
||||
git merge feature-branch # Empty merge!
|
||||
|
||||
# ✅ Do this instead
|
||||
git revert <the-revert-commit> # Revert the revert
|
||||
```
|
||||
|
||||
### 3. Using Reset on Pushed Commits
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# ❌ NEVER do this with pushed commits
|
||||
git reset --hard HEAD~3
|
||||
|
||||
@@ -511,11 +457,11 @@ git reset --hard HEAD~3
|
||||
git revert HEAD~3..HEAD
|
||||
```
|
||||
|
||||
### 4. Reverting Commits in Wrong Order
|
||||
### 2. Reverting Commits in Wrong Order
|
||||
|
||||
When reverting multiple related commits, revert from newest to oldest:
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# If you have: A → B → C (and C depends on B)
|
||||
|
||||
# ✅ Correct order
|
||||
@@ -530,7 +476,7 @@ git revert C
|
||||
## Best Practices
|
||||
|
||||
1. **Write clear revert messages:**
|
||||
```bash
|
||||
```pwsh
|
||||
git revert <hash> -m "Revert authentication - security issue #1234"
|
||||
```
|
||||
|
||||
@@ -561,15 +507,6 @@ git revert C
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Commit is a merge but no -m option was given"
|
||||
|
||||
**Problem:** Trying to revert a merge commit without `-m`.
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
git revert -m 1 <merge-commit-hash>
|
||||
```
|
||||
|
||||
### "Empty Revert / No Changes"
|
||||
|
||||
**Problem:** Revert doesn't seem to do anything.
|
||||
@@ -580,7 +517,7 @@ git revert -m 1 <merge-commit-hash>
|
||||
- Wrong commit hash
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
```pwsh
|
||||
# Check what the commit actually changed
|
||||
git show <commit-hash>
|
||||
|
||||
@@ -601,24 +538,22 @@ git log --grep="Revert"
|
||||
|
||||
Or consider fixing forward with a new commit instead of reverting.
|
||||
|
||||
### "Can't Re-Merge After Reverting Merge"
|
||||
### "Reverting Old Commit Breaks Something"
|
||||
|
||||
**Problem:** After reverting a merge, re-merging the branch brings no changes.
|
||||
**Problem:** After reverting an old commit, something else stops working.
|
||||
|
||||
**Solution:** Revert the revert commit:
|
||||
```bash
|
||||
# Find the revert commit
|
||||
git log --oneline
|
||||
**Why:** The old commit might have been a dependency for later commits.
|
||||
|
||||
# Revert the revert (brings changes back)
|
||||
git revert <revert-commit-hash>
|
||||
```
|
||||
**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:
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# Revert creates a new commit with inverse changes
|
||||
git revert <commit-hash>
|
||||
|
||||
@@ -645,9 +580,8 @@ You've learned:
|
||||
|
||||
- ✅ `git revert` creates new commits that undo previous changes
|
||||
- ✅ Revert is safe for shared/pushed commits
|
||||
- ✅ Merge commits require `-m 1` or `-m 2` flag
|
||||
- ✅ Parent 1 = branch merged into, Parent 2 = branch merged from
|
||||
- ✅ Can't simply re-merge after reverting a merge
|
||||
- ✅ 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
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#!/usr/bin/env pwsh
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Resets the Module 05 challenge environment to start fresh.
|
||||
Resets the Module 06 challenge environment to start fresh.
|
||||
|
||||
.DESCRIPTION
|
||||
This script removes the challenge directory and re-runs setup.ps1
|
||||
to create a fresh challenge environment.
|
||||
#>
|
||||
|
||||
Write-Host "`n=== Resetting Module 05: Git Revert Challenge ===" -ForegroundColor Cyan
|
||||
Write-Host "`n=== Resetting Module 06: Git Revert Challenge ===" -ForegroundColor Cyan
|
||||
|
||||
# Check if challenge directory exists
|
||||
if (Test-Path "challenge") {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#!/usr/bin/env pwsh
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets up the Module 05 challenge environment for learning git revert.
|
||||
Sets up the Module 06 challenge environment for learning git revert.
|
||||
|
||||
.DESCRIPTION
|
||||
This script creates a challenge directory with three branches demonstrating
|
||||
different revert scenarios:
|
||||
- regular-revert: Basic revert of a single bad commit
|
||||
- merge-revert: Reverting a merge commit with -m flag
|
||||
- regular-revert: Basic revert of a single bad commit at the end
|
||||
- middle-revert: Reverting a bad commit in the middle of history
|
||||
- multi-revert: Reverting multiple commits at once
|
||||
#>
|
||||
|
||||
Write-Host "`n=== Setting up Module 05: Git Revert Challenge ===" -ForegroundColor Cyan
|
||||
Write-Host "`n=== Setting up Module 06: Git Revert Challenge ===" -ForegroundColor Cyan
|
||||
|
||||
# Remove existing challenge directory if it exists
|
||||
if (Test-Path "challenge") {
|
||||
@@ -104,90 +104,63 @@ git commit -m "Add modulo function" | Out-Null
|
||||
Write-Host "[CREATED] regular-revert branch with bad divide commit" -ForegroundColor Green
|
||||
|
||||
# ============================================================================
|
||||
# SCENARIO 2: Merge Revert (Merge Commit with -m flag)
|
||||
# SCENARIO 2: Revert in Middle of History
|
||||
# ============================================================================
|
||||
Write-Host "`nScenario 2: Creating merge-revert scenario..." -ForegroundColor Cyan
|
||||
Write-Host "`nScenario 2: Creating middle-revert scenario..." -ForegroundColor Cyan
|
||||
|
||||
# Switch back to main
|
||||
git switch $mainBranch | Out-Null
|
||||
|
||||
# Create merge-revert branch
|
||||
git switch -c merge-revert | Out-Null
|
||||
# Create middle-revert branch
|
||||
git switch -c middle-revert | Out-Null
|
||||
|
||||
# Create a feature branch to merge
|
||||
git switch -c feature-auth | Out-Null
|
||||
# Good commit: Add validation module
|
||||
$validationContent = @"
|
||||
# validation.py - Input validation
|
||||
|
||||
# Add auth functionality
|
||||
$authContent = @"
|
||||
# auth.py - Authentication module
|
||||
|
||||
def login(username, password):
|
||||
\"\"\"Login user.\"\"\"
|
||||
print(f"Logging in {username}...")
|
||||
return True
|
||||
|
||||
def logout(username):
|
||||
\"\"\"Logout user.\"\"\"
|
||||
print(f"Logging out {username}...")
|
||||
return True
|
||||
"@
|
||||
Set-Content -Path "auth.py" -Value $authContent
|
||||
git add .
|
||||
git commit -m "Add authentication module" | Out-Null
|
||||
|
||||
# Add password validation
|
||||
$authContent = @"
|
||||
# auth.py - Authentication module
|
||||
|
||||
def validate_password(password):
|
||||
\"\"\"Validate password strength.\"\"\"
|
||||
return len(password) >= 8
|
||||
|
||||
def login(username, password):
|
||||
\"\"\"Login user.\"\"\"
|
||||
if not validate_password(password):
|
||||
print("Password too weak!")
|
||||
def validate_number(value):
|
||||
"""Check if value is a valid number."""
|
||||
try:
|
||||
float(value)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
print(f"Logging in {username}...")
|
||||
return True
|
||||
|
||||
def logout(username):
|
||||
\"\"\"Logout user.\"\"\"
|
||||
print(f"Logging out {username}...")
|
||||
return True
|
||||
"@
|
||||
Set-Content -Path "auth.py" -Value $authContent
|
||||
Set-Content -Path "validation.py" -Value $validationContent
|
||||
git add .
|
||||
git commit -m "Add password validation" | Out-Null
|
||||
git commit -m "Add input validation module" | Out-Null
|
||||
|
||||
# Integrate auth into calculator (part of the feature branch)
|
||||
$calcContent = @"
|
||||
# calculator.py - Simple calculator
|
||||
from auth import login
|
||||
# BAD commit: Add broken formatter
|
||||
$formatterContent = @"
|
||||
# formatter.py - Output formatting
|
||||
|
||||
def add(a, b):
|
||||
"""Add two numbers."""
|
||||
return a + b
|
||||
|
||||
def subtract(a, b):
|
||||
"""Subtract b from a."""
|
||||
return a - b
|
||||
|
||||
def secure_divide(a, b, username):
|
||||
"""Secure divide - requires authentication."""
|
||||
if login(username, "password123"):
|
||||
return a / b
|
||||
return None
|
||||
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 "calculator.py" -Value $calcContent
|
||||
Set-Content -Path "formatter.py" -Value $formatterContent
|
||||
git add .
|
||||
git commit -m "Integrate auth into calculator" | Out-Null
|
||||
git commit -m "Add broken formatter - needs to be reverted!" | Out-Null
|
||||
|
||||
# Switch back to merge-revert and merge feature-auth
|
||||
git switch merge-revert | Out-Null
|
||||
git merge feature-auth --no-ff -m "Merge feature-auth branch" | Out-Null
|
||||
# Good commit: Add configuration (depends on validation, not formatter)
|
||||
$configContent = @"
|
||||
# config.py - Application configuration
|
||||
|
||||
Write-Host "[CREATED] merge-revert branch with merge commit to revert" -ForegroundColor Green
|
||||
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)
|
||||
@@ -275,8 +248,8 @@ Set-Location ..
|
||||
|
||||
Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green
|
||||
Write-Host "`nThree revert scenarios have been created:" -ForegroundColor Cyan
|
||||
Write-Host " 1. regular-revert - Revert a single bad commit (basic)" -ForegroundColor White
|
||||
Write-Host " 2. merge-revert - Revert a merge commit with -m flag" -ForegroundColor White
|
||||
Write-Host " 1. regular-revert - Revert a bad commit at the end" -ForegroundColor White
|
||||
Write-Host " 2. middle-revert - Revert a bad commit in the middle of history" -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 "`nNext steps:" -ForegroundColor Cyan
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#!/usr/bin/env pwsh
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Verifies the Module 05 challenge solutions.
|
||||
Verifies the Module 06 challenge solutions.
|
||||
|
||||
.DESCRIPTION
|
||||
Checks that all three revert scenarios have been completed correctly:
|
||||
- regular-revert: Single commit reverted
|
||||
- merge-revert: Merge commit reverted with -m flag
|
||||
- middle-revert: Commit in middle of history reverted
|
||||
- multi-revert: Multiple commits reverted
|
||||
#>
|
||||
|
||||
Write-Host "`n=== Verifying Module 05: Git Revert Solutions ===" -ForegroundColor Cyan
|
||||
Write-Host "`n=== Verifying Module 06: Git Revert Solutions ===" -ForegroundColor Cyan
|
||||
|
||||
$allChecksPassed = $true
|
||||
$originalDir = Get-Location
|
||||
@@ -87,53 +87,50 @@ if ($LASTEXITCODE -ne 0) {
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# SCENARIO 2: Merge Revert Verification
|
||||
# SCENARIO 2: Middle Revert Verification
|
||||
# ============================================================================
|
||||
Write-Host "`n=== Scenario 2: Merge Revert ===" -ForegroundColor Cyan
|
||||
Write-Host "`n=== Scenario 2: Middle Revert ===" -ForegroundColor Cyan
|
||||
|
||||
git switch merge-revert 2>&1 | Out-Null
|
||||
git switch middle-revert 2>&1 | Out-Null
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[FAIL] merge-revert branch not found" -ForegroundColor Red
|
||||
Write-Host "[FAIL] middle-revert branch not found" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
} else {
|
||||
# Check that a revert commit for the merge exists
|
||||
$revertMerge = git log --oneline --grep="Revert.*Merge" 2>$null
|
||||
if ($revertMerge) {
|
||||
Write-Host "[PASS] Merge revert commit found" -ForegroundColor Green
|
||||
# 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 merge revert commit found" -ForegroundColor Red
|
||||
Write-Host "[HINT] Use: git revert -m 1 <merge-commit-hash>" -ForegroundColor Yellow
|
||||
Write-Host "[FAIL] No revert commit found" -ForegroundColor Red
|
||||
Write-Host "[HINT] Use: git revert <commit-hash>" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that the original merge commit still exists (revert doesn't erase it)
|
||||
$mergeCommit = git log --merges --oneline --grep="Merge feature-auth" 2>$null
|
||||
if ($mergeCommit) {
|
||||
Write-Host "[PASS] Original merge commit still in history (not erased)" -ForegroundColor Green
|
||||
# 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 "[INFO] Original merge commit not found (this is OK if you used a different approach)" -ForegroundColor Yellow
|
||||
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 auth.py no longer exists or its effects are reverted
|
||||
if (-not (Test-Path "auth.py")) {
|
||||
Write-Host "[PASS] auth.py removed (merge reverted successfully)" -ForegroundColor Green
|
||||
# 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 "[INFO] auth.py still exists (check if merge was fully reverted)" -ForegroundColor Yellow
|
||||
Write-Host "[FAIL] validation.py missing (should still exist)" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that calculator.py exists
|
||||
if (Test-Path "calculator.py") {
|
||||
$calcContent = Get-Content "calculator.py" -Raw
|
||||
|
||||
# After reverting the merge, calculator shouldn't import auth
|
||||
if ($calcContent -notmatch "from auth import") {
|
||||
Write-Host "[PASS] Auth integration reverted from calculator.py" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] calculator.py still imports auth (merge not fully reverted)" -ForegroundColor Red
|
||||
Write-Host "[HINT] Reverting the merge should remove the auth integration" -ForegroundColor Yellow
|
||||
$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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,11 +208,11 @@ if ($allChecksPassed) {
|
||||
Write-Host "=========================================" -ForegroundColor Green
|
||||
Write-Host "`nYou've mastered git revert!" -ForegroundColor Cyan
|
||||
Write-Host "You now understand:" -ForegroundColor Cyan
|
||||
Write-Host " ✓ Reverting regular commits safely" -ForegroundColor White
|
||||
Write-Host " ✓ Reverting merge commits with -m flag" -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 " ✓ Preserving history while undoing changes" -ForegroundColor White
|
||||
Write-Host "`nReady for Module 06: Git Reset!" -ForegroundColor Green
|
||||
Write-Host " ✓ Preserving commits before and after the reverted one" -ForegroundColor White
|
||||
Write-Host "`nReady for Module 07: Git Reset!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
exit 0
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user