refactor: we're breaking out merge-conflicts

This commit is contained in:
Bjarke Sporring
2026-01-15 12:51:43 +01:00
parent ea5cbccc75
commit 7b638d27de
29 changed files with 1385 additions and 1310 deletions

File diff suppressed because it is too large Load Diff

Submodule 01-essentials/03-branching-and-merging/challenge added at 8ae52cc25c

View File

@@ -1,216 +1,23 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Resets the challenge environment to a specific checkpoint.
Resets the Module 03 challenge environment.
.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).
This script removes the challenge directory, allowing you to start fresh.
Run setup.ps1 again after resetting to recreate the environment.
#>
param(
[ValidateSet('start', 'merge', 'merge-conflict', '')]
[string]$Checkpoint = ''
)
Write-Host "`n=== Resetting Module 03 Challenge ===" -ForegroundColor Cyan
# Checkpoint to tag mapping
$checkpointTags = @{
'start' = 'checkpoint-start'
'merge' = 'checkpoint-merge'
'merge-conflict' = 'checkpoint-merge-conflict'
if (Test-Path "challenge") {
Write-Host "Removing challenge directory..." -ForegroundColor Yellow
Remove-Item -Recurse -Force "challenge"
Write-Host "`n[SUCCESS] Challenge environment reset complete!" -ForegroundColor Green
Write-Host "`nRun .\setup.ps1 to create a fresh challenge environment." -ForegroundColor Cyan
Write-Host ""
} else {
Write-Host "`n[INFO] No challenge directory found. Nothing to reset." -ForegroundColor Yellow
Write-Host "Run .\setup.ps1 to create the challenge environment." -ForegroundColor Cyan
Write-Host ""
}
# 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 <checkpoint>" -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

View File

@@ -1,17 +1,13 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Sets up the Module 03 checkpoint-based challenge environment.
Sets up the Module 03 challenge environment for branching and merging.
.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
This script creates a challenge directory with a Git repository containing
a realistic project history with multiple merged branches. Students will see
what branching and merging looks like in practice, then create their own
branches to experiment.
#>
Write-Host "`n=== Setting up Module 03: Branching and Merging ===" -ForegroundColor Cyan
@@ -36,113 +32,75 @@ git config user.name "Workshop Student"
git config user.email "student@example.com"
# ============================================================================
# PHASE 1: Branching Basics - Initial commits on main
# Create a realistic project history with multiple merged branches
# ============================================================================
Write-Host "`nPhase 1: Creating initial project structure..." -ForegroundColor Cyan
Write-Host "Creating project history with multiple branches..." -ForegroundColor Cyan
# Commit 1: Initial commit
$mainContent = @"
# main.py - Main application file
# Initial commits on main
$readmeContent = @"
# My Application
def main():
print("Welcome to the Application!")
print("This is the main branch")
if __name__ == "__main__":
main()
A sample application for learning Git branching and merging.
"@
Set-Content -Path "main.py" -Value $mainContent
Set-Content -Path "README.md" -Value $readmeContent
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
git commit -m "Add main application file" | Out-Null
# ============================================================================
# PHASE 2: Create feature-login branch (what students will do in checkpoint 1)
# Branch 1: feature-login (will be merged)
# ============================================================================
Write-Host "Phase 2: Creating feature-login branch..." -ForegroundColor Cyan
# Create and switch to feature-login branch
Write-Host "Creating feature-login branch..." -ForegroundColor Cyan
git switch -c feature-login | Out-Null
# Commit 3: Add login module
$loginContent = @"
# login.py - User login module
# login.py - User authentication
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}")
print(f"Logging in 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
# login.py - User authentication
def validate_password(password):
"""Validate password strength."""
if len(password) < 8:
return False
return True
return len(password) >= 8
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}")
print(f"Logging in 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
# Switch back to main and make more commits
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
# app.py - Application entry point
from main import main
@@ -150,7 +108,6 @@ def run():
"""Run the application."""
print("Starting application...")
main()
print("Application finished.")
if __name__ == "__main__":
run()
@@ -159,16 +116,65 @@ Set-Content -Path "app.py" -Value $appContent
git add .
git commit -m "Add app.py entry point" | Out-Null
# Commit 6: Add README
# Merge feature-login into main
Write-Host "Merging feature-login into main..." -ForegroundColor Green
git merge feature-login --no-edit | Out-Null
# ============================================================================
# Branch 2: feature-api (will be merged)
# ============================================================================
Write-Host "Creating feature-api branch..." -ForegroundColor Cyan
git switch -c feature-api | Out-Null
$apiContent = @"
# api.py - API endpoints
def get_data():
"""Retrieve data from API."""
return {"status": "ok", "data": []}
def post_data(data):
"""Send data to API."""
print(f"Posting data: {data}")
return {"status": "ok"}
"@
Set-Content -Path "api.py" -Value $apiContent
git add .
git commit -m "Add API module" | Out-Null
$apiContent = @"
# api.py - API endpoints
def get_data():
"""Retrieve data from API."""
return {"status": "ok", "data": []}
def post_data(data):
"""Send data to API."""
print(f"Posting data: {data}")
return {"status": "ok"}
def delete_data(id):
"""Delete data by ID."""
print(f"Deleting data: {id}")
return {"status": "ok"}
"@
Set-Content -Path "api.py" -Value $apiContent
git add .
git commit -m "Add delete endpoint to API" | Out-Null
# Switch back to main and add documentation
git switch main | Out-Null
$readmeContent = @"
# My Application
Welcome to my application!
A sample application for learning Git branching and merging.
## Features
- Main functionality
- More features coming soon
- User authentication
- Main application logic
## Setup
@@ -176,104 +182,107 @@ Run: python app.py
"@
Set-Content -Path "README.md" -Value $readmeContent
git add .
git commit -m "Add README documentation" | Out-Null
git commit -m "Update README with setup instructions" | Out-Null
# Tag checkpoint-merge (students begin merging here - divergent branches ready)
Write-Host "Creating checkpoint: merge" -ForegroundColor Green
git tag checkpoint-merge
# Merge feature-api into main
Write-Host "Merging feature-api into main..." -ForegroundColor Green
git merge feature-api --no-edit | Out-Null
# ============================================================================
# PHASE 3: Merge feature-login into main (what students will do in checkpoint 2)
# Branch 3: feature-database (will be merged)
# ============================================================================
Write-Host "Phase 3: Merging feature-login into main..." -ForegroundColor Cyan
Write-Host "Creating feature-database branch..." -ForegroundColor Cyan
git switch -c feature-database | Out-Null
# Merge feature-login into main (will create three-way merge commit)
git merge feature-login --no-edit | Out-Null
$dbContent = @"
# database.py - Database operations
# ============================================================================
# PHASE 4: Create conflict scenario (what students will do in checkpoint 3)
# ============================================================================
Write-Host "Phase 4: Creating merge conflict scenario..." -ForegroundColor Cyan
class Database:
def __init__(self):
self.connection = None
# Create config.json file on main
$initialConfig = @"
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000
}
}
def connect(self):
"""Connect to database."""
print("Connecting to database...")
self.connection = True
def query(self, sql):
"""Execute SQL query."""
print(f"Executing: {sql}")
return []
"@
Set-Content -Path "config.json" -Value $initialConfig
git add config.json
git commit -m "Add initial configuration" | Out-Null
Set-Content -Path "database.py" -Value $dbContent
git add .
git commit -m "Add database module" | Out-Null
# On main branch: Add timeout setting
$mainConfig = @"
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000,
"timeout": 5000
}
}
$dbContent = @"
# database.py - Database operations
class Database:
def __init__(self):
self.connection = None
def connect(self):
"""Connect to database."""
print("Connecting to database...")
self.connection = True
def disconnect(self):
"""Disconnect from database."""
print("Disconnecting from database...")
self.connection = None
def query(self, sql):
"""Execute SQL query."""
print(f"Executing: {sql}")
return []
"@
Set-Content -Path "config.json" -Value $mainConfig
git add config.json
git commit -m "Add timeout configuration" | Out-Null
Set-Content -Path "database.py" -Value $dbContent
git add .
git commit -m "Add disconnect method" | 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
# Switch to main and merge
git switch main | Out-Null
Write-Host "Merging feature-database into main..." -ForegroundColor Green
git merge feature-database --no-edit | 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
# Final update on main
$readmeContent = @"
# My Application
# ============================================================================
# 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
A sample application for learning Git branching and merging.
## Features
- User authentication
- API endpoints
- Database operations
- Main application logic
## Setup
Run: python app.py
## Requirements
- Python 3.6+
"@
Set-Content -Path "README.md" -Value $readmeContent
git add .
git commit -m "Update README with all features" | 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 "`nThe repository contains a realistic project history:" -ForegroundColor Yellow
Write-Host " - Multiple feature branches (login, api, database)" -ForegroundColor White
Write-Host " - All branches have been merged into main" -ForegroundColor White
Write-Host " - View the history: git log --oneline --graph --all" -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 " 3. Explore the repository history: git log --oneline --graph --all" -ForegroundColor White
Write-Host " 4. Create your own branches and practice merging!" -ForegroundColor White
Write-Host ""

View File

@@ -1,34 +1,15 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Verifies the Module 03 challenge solution (checkpoint-aware).
Verifies the Module 03 challenge solution.
.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.
This script checks that you've practiced branching and merging by:
- Creating at least one new branch (beyond the example branches)
- Making commits on your branch
- Merging your branch into main
#>
param(
[ValidateSet('start', 'merge', 'merge-conflict', '')]
[string]$Checkpoint = ''
)
$script:allChecksPassed = $true
# ============================================================================
@@ -51,198 +32,15 @@ function Write-Hint {
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
}
function Write-Info {
param([string]$Message)
Write-Host "[INFO] $Message" -ForegroundColor Cyan
}
# ============================================================================
# Checkpoint 2: Merging Verification
# Check challenge directory exists
# ============================================================================
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
@@ -251,7 +49,6 @@ if (-not (Test-Path "challenge")) {
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
@@ -259,62 +56,98 @@ if (-not (Test-Path ".git")) {
exit 1
}
# Run appropriate verification
if ($Checkpoint -eq '') {
# Verify all checkpoints
Write-Host "`n=== Verifying All Checkpoints ===" -ForegroundColor Cyan
Write-Host "`n=== Verifying Module 03: Branching and Merging ===" -ForegroundColor Cyan
Verify-Branching
Verify-Merging
Verify-MergeConflicts
# ============================================================================
# Count initial setup commits (should be 13 commits from setup)
# ============================================================================
$initialCommitCount = 13
# ============================================================================
# Check for new commits beyond setup
# ============================================================================
Write-Host "`nChecking your work..." -ForegroundColor Cyan
$totalCommits = [int](git rev-list --count HEAD 2>$null)
if ($totalCommits -gt $initialCommitCount) {
$newCommits = $totalCommits - $initialCommitCount
Write-Pass "Found $newCommits new commit(s) beyond the initial setup"
} else {
# Verify specific checkpoint
switch ($Checkpoint) {
'start' { Verify-Branching }
'merge' { Verify-Merging }
'merge-conflict' { Verify-MergeConflicts }
}
Write-Fail "No new commits found"
Write-Hint "Create a branch, make some commits, and merge it into main"
Write-Hint "Example: git switch -c my-feature"
}
# ============================================================================
# Check for branches (excluding the example branches)
# ============================================================================
$allBranches = git branch --list 2>$null | ForEach-Object { $_.Trim('* ') }
$exampleBranches = @('main', 'feature-login', 'feature-api', 'feature-database')
$studentBranches = $allBranches | Where-Object { $_ -notin $exampleBranches }
if ($studentBranches.Count -gt 0) {
Write-Pass "Created $($studentBranches.Count) new branch(es): $($studentBranches -join ', ')"
} else {
Write-Info "No new branches found (it's OK if you deleted them after merging)"
Write-Hint "To practice: git switch -c your-branch-name"
}
# ============================================================================
# Check for merge commits by the student
# ============================================================================
$setupUser = "Workshop Student"
$mergeCommits = git log --merges --format="%s" 2>$null
# Count how many merge commits exist beyond the initial 3
$totalMerges = ($mergeCommits | Measure-Object).Count
$setupMerges = 3 # feature-login, feature-api, feature-database
if ($totalMerges -gt $setupMerges) {
$studentMerges = $totalMerges - $setupMerges
Write-Pass "Performed $studentMerges merge(s) of your own work"
} else {
Write-Fail "No merge commits found beyond the example merges"
Write-Hint "Create a branch, add commits, then merge it: git merge your-branch-name"
}
# ============================================================================
# Check current branch
# ============================================================================
$currentBranch = git branch --show-current 2>$null
if ($currentBranch -eq "main") {
Write-Pass "Currently on main branch"
} else {
Write-Info "Currently on '$currentBranch' branch"
Write-Hint "Typically you merge feature branches INTO main"
}
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 "`nYou've successfully practiced:" -ForegroundColor Cyan
Write-Host " ✓ Creating branches" -ForegroundColor White
Write-Host " ✓ Making commits on branches" -ForegroundColor White
Write-Host " ✓ Merging branches together" -ForegroundColor White
Write-Host "`nReady 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 "[SUMMARY] Some checks failed. Review the hints above." -ForegroundColor Red
Write-Host ""
Write-Host "Quick guide:" -ForegroundColor Cyan
Write-Host " 1. Create a branch: git switch -c my-feature" -ForegroundColor White
Write-Host " 2. Make changes and commit them" -ForegroundColor White
Write-Host " 3. Switch to main: git switch main" -ForegroundColor White
Write-Host " 4. Merge your branch: git merge my-feature" -ForegroundColor White
Write-Host " 5. Run this verify script again" -ForegroundColor White
Write-Host ""
exit 1
}

View File

@@ -0,0 +1,487 @@
# Module 04: Merge Conflicts
## Learning Objectives
By the end of this module, you will:
- Understand what merge conflicts are and why they occur
- Use `git diff` to discover changes between branches
- Identify merge conflicts in your repository
- Read and interpret conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`)
- Resolve merge conflicts manually
- Complete a merge after resolving conflicts
## Setup
Create the challenge environment:
```bash
.\setup.ps1
```
This creates a repository with two feature branches that have conflicting changes.
## Overview
A **merge conflict** occurs when Git cannot automatically combine changes because both branches modified the same part of the same file in different ways.
**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.
## Your Task
### Part 1: Discover the Changes
Before merging, it's good practice to see what each branch changed:
```bash
cd challenge
# Check which branch you're on
git branch
# View all branches
git branch --all
```
You'll see three branches: `main`, `add-timeout`, and `add-debug`.
**Discover what each branch changed:**
```bash
# Compare main with add-timeout
git diff main add-timeout
# Compare main with add-debug
git diff main add-debug
# Compare the two feature branches directly
git diff add-timeout add-debug
```
**What did you discover?**
- Both branches modified `config.json`
- They both added a line in the same location (after `"port": 3000`)
- One adds `"timeout": 5000`
- The other adds `"debug": true`
This is a recipe for a conflict!
### Part 2: Merge the First Branch (No Conflict)
Let's merge `add-timeout` first:
```bash
# Make sure you're on main
git switch main
# Merge the first branch
git merge add-timeout
```
**Success!** This merge works because main hasn't changed since add-timeout was created.
```bash
# View the updated config
cat config.json
# Check the history
git log --oneline --graph --all
```
### Part 3: Try to Merge the Second Branch (Conflict!)
Now let's try to merge `add-debug`:
```bash
# Still on main
git merge add-debug
```
💥 **Boom!** 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 expected. Git is asking for your help.
### Part 4: Check the Status
```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 <file>..." to mark resolution)
both modified: config.json
```
This tells you that `config.json` needs your attention!
### Part 5: Open and Examine the Conflicted File
Open `config.json` in your text editor:
```bash
# On Windows
notepad config.json
# Or use VS Code
code config.json
```
You'll see special **conflict markers**:
```json
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000,
<<<<<<< HEAD
"timeout": 5000
=======
"debug": true
>>>>>>> add-debug
}
}
```
### Part 6: Understand the Conflict Markers
Let's break down what you're seeing:
```
<<<<<<< HEAD
"timeout": 5000 ← Your current branch (main, which has add-timeout merged)
=======
"debug": true ← The branch you're merging (add-debug)
>>>>>>> add-debug
```
**What each marker means:**
- `<<<<<<< HEAD` - Start of your changes (current branch)
- `=======` - Separator between the two versions
- `>>>>>>> add-debug` - End of their changes (branch being merged)
### Part 7: Resolve the Conflict
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****Do this!**
```json
"timeout": 5000,
"debug": true
```
### Part 8: Edit the File
For this challenge, we want **both settings**, so:
1. Delete ALL the conflict markers:
- Remove `<<<<<<< HEAD`
- Remove `=======`
- Remove `>>>>>>> add-debug`
2. Keep both settings:
**Before (with conflict markers):**
```json
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000,
<<<<<<< HEAD
"timeout": 5000
=======
"debug": true
>>>>>>> add-debug
}
}
```
**After (resolved):**
```json
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000,
"timeout": 5000,
"debug": true
}
}
```
**Important:**
- Remove ALL markers
- Add a comma after `"timeout": 5000` (for valid JSON)
- Ensure the file is valid JSON
3. Save the file
### Part 9: Mark the Conflict as Resolved
Tell Git you've resolved the conflict:
```bash
# Stage the resolved file
git add config.json
# Check status
git status
```
You should 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.
### Part 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, then save and close.
**Done!** Your merge is complete!
```bash
# View the final result
cat config.json
# View the history
git log --oneline --graph --all
```
You should see both `timeout` and `debug` in the config!
### Part 11: Verify Your Solution
From the module directory (not inside challenge/):
```bash
.\verify.ps1
```
## Understanding Conflict Markers
### Anatomy of a Conflict
```
<<<<<<< HEAD ← Marker: Start of your version
Your changes here
======= ← Marker: Separator
Their changes here
>>>>>>> branch-name ← Marker: End of their version
```
### Common Conflict Patterns
**Simple conflict:**
```
<<<<<<< HEAD
print("Hello")
=======
print("Hi")
>>>>>>> feature
```
Decision: Which greeting do you want?
**Both are needed:**
```
<<<<<<< HEAD
timeout: 5000
=======
debug: true
>>>>>>> feature
```
Decision: Keep both (add comma)!
**Deletion conflict:**
```
<<<<<<< HEAD
# Function deleted on your branch
=======
def old_function():
pass
>>>>>>> feature
```
Decision: Delete or keep the function?
## Common Mistakes to Avoid
**Forgetting to remove conflict markers**
```json
<<<<<<< HEAD Don't leave these in!
"timeout": 5000,
"debug": true
>>>>>>> add-debug 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!
**Breaking syntax**
```json
"timeout": 5000 Missing comma!
"debug": true
```
Always verify your file is valid after resolving!
**Not testing the result**
Always check that your resolved code works!
## Aborting a Merge
Changed your mind? You can abort the merge anytime before committing:
```bash
git merge --abort
```
This returns your repository to the state before you started the merge. No harm done!
## Key Commands
```bash
# Discover changes before merging
git diff branch1 branch2
# Attempt a merge
git merge <branch-name>
# Check which files have conflicts
git status
# Abort the merge and start over
git merge --abort
# After resolving conflicts:
git add <resolved-file>
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
💡 **Use `git diff` first**
Always compare branches before merging:
```bash
git diff main..feature-branch
```
💡 **Prevent conflicts**
- Pull changes frequently
- 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
- Make small, focused commits
- If editing the same file, coordinate with teammates
💡 **When stuck**
- Read the conflict markers carefully
- Look at `git log` to understand what each side changed
- Use `git diff` to see the changes
- Ask a teammate to review your resolution
- Use a merge tool: `git mergetool`
## Merge Tools
Git supports visual merge tools that make resolving conflicts easier:
```bash
# Configure a merge tool (one-time setup)
git config --global merge.tool vscode # or meld, kdiff3, etc.
# Use the merge tool during a conflict
git mergetool
```
This opens a visual interface showing both versions side-by-side.
## Real-World Scenario
This exercise simulates a common real-world situation:
**Scenario:** Two developers working on the same file
- Alice adds a timeout configuration
- Bob adds debug mode configuration
- Both push their changes
- When Bob tries to merge, he gets a conflict
- Bob resolves it by keeping both changes
- Everyone's work is preserved!
This happens all the time in team development. Conflicts are normal!
## What You've Learned
After completing this module, you understand:
- ✅ Merge conflicts happen when the same lines are changed differently
-`git diff` helps you discover changes before merging
- ✅ Conflict markers show both versions
- ✅ You decide what the final code should look like
- ✅ Remove all markers before committing
- ✅ Test your resolution to ensure it works
- ✅ Conflicts are normal and easy to resolve with practice
## Next Steps
Ready to continue? The next module covers **cherry-picking** - selectively applying specific commits from one branch to another.
To start over:
```bash
.\reset.ps1
.\setup.ps1
```
**Need help?** Review the steps above, or run `git status` to see what Git suggests!

Submodule 01-essentials/04-merge-conflict/challenge added at 676b08e650

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Resets the Module 04 challenge environment.
.DESCRIPTION
This script removes the challenge directory, allowing you to start fresh.
Run setup.ps1 again after resetting to recreate the environment.
#>
Write-Host "`n=== Resetting Module 04 Challenge ===" -ForegroundColor Cyan
if (Test-Path "challenge") {
Write-Host "Removing challenge directory..." -ForegroundColor Yellow
Remove-Item -Recurse -Force "challenge"
Write-Host "`n[SUCCESS] Challenge environment reset complete!" -ForegroundColor Green
Write-Host "`nRun .\setup.ps1 to create a fresh challenge environment." -ForegroundColor Cyan
Write-Host ""
} else {
Write-Host "`n[INFO] No challenge directory found. Nothing to reset." -ForegroundColor Yellow
Write-Host "Run .\setup.ps1 to create the challenge environment." -ForegroundColor Cyan
Write-Host ""
}

View File

@@ -0,0 +1,125 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Sets up the Module 04 challenge environment for merge conflicts.
.DESCRIPTION
This script creates a challenge directory with a Git repository containing
two feature branches that have conflicting changes to the same file.
Students will learn to identify, understand, and resolve merge conflicts.
#>
Write-Host "`n=== Setting up Module 04: Merge Conflicts ===" -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"
# ============================================================================
# Create base project
# ============================================================================
Write-Host "Creating base project..." -ForegroundColor Cyan
# Initial commit with config file
$configContent = @"
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000
}
}
"@
Set-Content -Path "config.json" -Value $configContent
git add .
git commit -m "Initial commit with config" | Out-Null
# Add README
$readmeContent = @"
# My Application
A simple application for learning merge conflicts.
## Configuration
Edit `config.json` to configure the application.
"@
Set-Content -Path "README.md" -Value $readmeContent
git add .
git commit -m "Add README" | Out-Null
# ============================================================================
# Branch 1: add-timeout (adds timeout setting)
# ============================================================================
Write-Host "Creating add-timeout branch..." -ForegroundColor Cyan
git switch -c add-timeout | Out-Null
$timeoutConfig = @"
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000,
"timeout": 5000
}
}
"@
Set-Content -Path "config.json" -Value $timeoutConfig
git add .
git commit -m "Add timeout configuration" | Out-Null
# ============================================================================
# Branch 2: add-debug (adds debug setting - CONFLICTS with timeout!)
# ============================================================================
Write-Host "Creating add-debug branch..." -ForegroundColor Cyan
git switch main | Out-Null
git switch -c add-debug | Out-Null
$debugConfig = @"
{
"app": {
"name": "MyApp",
"version": "1.0.0",
"port": 3000,
"debug": true
}
}
"@
Set-Content -Path "config.json" -Value $debugConfig
git add .
git commit -m "Add debug mode configuration" | Out-Null
# Switch back to main
git switch main | 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 "`nThe repository contains:" -ForegroundColor Yellow
Write-Host " - main branch: base configuration" -ForegroundColor White
Write-Host " - add-timeout branch: adds timeout setting" -ForegroundColor White
Write-Host " - add-debug branch: adds debug setting" -ForegroundColor White
Write-Host "`nBoth branches modify the same part of config.json!" -ForegroundColor Red
Write-Host "This will cause a merge conflict when you try to merge both." -ForegroundColor Red
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. Follow the guide to discover and resolve the conflict" -ForegroundColor White
Write-Host ""

View File

@@ -0,0 +1,208 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Verifies the Module 04 challenge solution.
.DESCRIPTION
This script checks that you've successfully resolved the merge conflict by:
- Merging both branches into main
- Resolving the conflict in config.json
- Keeping both timeout and debug settings
- Ensuring valid JSON syntax
#>
$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
}
function Write-Info {
param([string]$Message)
Write-Host "[INFO] $Message" -ForegroundColor Cyan
}
# ============================================================================
# Check 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"
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
}
Write-Host "`n=== Verifying Module 04: Merge Conflicts ===" -ForegroundColor Cyan
# ============================================================================
# Check current branch
# ============================================================================
$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"
Pop-Location
exit 1
} else {
Write-Pass "No merge in progress (conflicts resolved)"
}
# ============================================================================
# Check if config.json exists
# ============================================================================
if (-not (Test-Path "config.json")) {
Write-Fail "File 'config.json' not found"
Write-Hint "The config.json file should exist"
Pop-Location
exit 1
}
# ============================================================================
# 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 (<<<<<<<, =======, >>>>>>>)"
Write-Hint "Check for missing commas or brackets"
Pop-Location
exit 1
}
# ============================================================================
# Check for conflict markers
# ============================================================================
if ($configContent -match '<<<<<<<|=======|>>>>>>>') {
Write-Fail "Conflict markers still present in config.json"
Write-Hint "Remove all conflict markers (<<<<<<<, =======, >>>>>>>)"
Pop-Location
exit 1
} 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 add-timeout 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 add-debug branch"
}
# ============================================================================
# Verify both branches were merged
# ============================================================================
$addTimeoutMerged = git log --oneline --grep="add-timeout" 2>$null | Select-String "Merge"
$addDebugMerged = git log --oneline --grep="add-debug" 2>$null | Select-String "Merge"
if ($addTimeoutMerged) {
Write-Pass "add-timeout branch has been merged"
} else {
# Check if it was a fast-forward merge (commits exist but no merge commit)
$timeoutCommit = git log --oneline --grep="Add timeout configuration" 2>$null
if ($timeoutCommit) {
Write-Pass "add-timeout branch changes are in main"
} else {
Write-Fail "add-timeout branch not merged"
Write-Hint "Merge with: git merge add-timeout"
}
}
if ($addDebugMerged) {
Write-Pass "add-debug branch has been merged"
} else {
Write-Fail "add-debug branch not merged"
Write-Hint "Merge with: git merge add-debug"
}
# ============================================================================
# Check commit count (should have both merges)
# ============================================================================
$totalCommits = [int](git rev-list --count HEAD 2>$null)
if ($totalCommits -ge 5) {
Write-Pass "Repository has $totalCommits commits (all merges complete)"
} else {
Write-Info "Repository has $totalCommits commits"
Write-Hint "Make sure both branches are merged"
}
Pop-Location
# ============================================================================
# Final summary
# ============================================================================
Write-Host ""
if ($script:allChecksPassed) {
Write-Host "=========================================" -ForegroundColor Green
Write-Host " CONGRATULATIONS! CHALLENGE PASSED!" -ForegroundColor Green
Write-Host "=========================================" -ForegroundColor Green
Write-Host "`nYou've successfully:" -ForegroundColor Cyan
Write-Host " ✓ Discovered changes using git diff" -ForegroundColor White
Write-Host " ✓ Merged the first branch" -ForegroundColor White
Write-Host " ✓ Encountered a merge conflict" -ForegroundColor White
Write-Host " ✓ Resolved the conflict by keeping both changes" -ForegroundColor White
Write-Host " ✓ Completed the merge" -ForegroundColor White
Write-Host "`nYou're now ready to handle merge conflicts in real projects!" -ForegroundColor Green
Write-Host ""
exit 0
} else {
Write-Host "[SUMMARY] Some checks failed. Review the hints above." -ForegroundColor Red
Write-Host ""
Write-Host "Quick guide:" -ForegroundColor Cyan
Write-Host " 1. Make sure you're on main: git switch main" -ForegroundColor White
Write-Host " 2. Merge first branch: git merge add-timeout" -ForegroundColor White
Write-Host " 3. Merge second branch: git merge add-debug" -ForegroundColor White
Write-Host " 4. Resolve conflict: edit config.json, remove markers, keep both settings" -ForegroundColor White
Write-Host " 5. Stage resolved file: git add config.json" -ForegroundColor White
Write-Host " 6. Complete merge: git commit" -ForegroundColor White
Write-Host " 7. Run this verify script again" -ForegroundColor White
Write-Host ""
exit 1
}