Compare commits
22 Commits
c39573573f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c20041efde | ||
|
|
84ed357feb | ||
|
|
9659d82d2a | ||
|
|
dbba2da5f2 | ||
|
|
1d0003bb70 | ||
|
|
3a4fe8ce9e | ||
|
|
13dd2317f9 | ||
|
|
cac03b69e3 | ||
|
|
19cf66e23d | ||
|
|
a6b33a441e | ||
|
|
690b83cead | ||
|
|
c69b463f84 | ||
|
|
39d8ace75c | ||
|
|
4b9d2449c8 | ||
|
|
5582b9fcbd | ||
|
|
3a6eb0646b | ||
|
|
a898030a9f | ||
|
|
382a125076 | ||
|
|
d80fa74af9 | ||
|
|
7fc0c1342a | ||
|
|
cba2d9bb16 | ||
|
|
968a44f9a5 |
@@ -11,35 +11,35 @@
|
||||
- Committed both required files (welcome.txt and instructions.txt)
|
||||
#>
|
||||
|
||||
. "$PSScriptRoot\..\..\util.ps1"
|
||||
|
||||
Write-Host "Verifying Module 01: Git Basics Challenge..." -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
$allChecksPassed = $true
|
||||
$challengeRoot = "$PSScriptRoot\challenge"
|
||||
|
||||
# Check if challenge directory exists
|
||||
if (-not (Test-Path "challenge")) {
|
||||
Write-Host "[FAIL] Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||
if (-not (Test-Path $challengeRoot)) {
|
||||
Write-Fail "Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Set-Location "challenge"
|
||||
|
||||
# Check if git repository exists
|
||||
if (-not (Test-Path ".git")) {
|
||||
Write-Host "[FAIL] No git repository found. Did you run 'git init'?" -ForegroundColor Red
|
||||
Set-Location ".."
|
||||
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||
Write-Fail "No git repository found. Did you run 'git init'?" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "[PASS] Git repository initialized" -ForegroundColor Green
|
||||
Write-Pass "Git repository initialized" -ForegroundColor Green
|
||||
|
||||
# Check if there are any commits
|
||||
$commitCount = (git rev-list --all --count 2>$null)
|
||||
if ($null -eq $commitCount -or $commitCount -eq 0) {
|
||||
Write-Host "[FAIL] No commits found. Have you committed your changes?" -ForegroundColor Red
|
||||
Write-Fail "No commits found. Have you committed your changes?" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
} else {
|
||||
Write-Host "[PASS] Found $commitCount commit(s)" -ForegroundColor Green
|
||||
Write-Pass "Found $commitCount commit(s)" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Check if both files are in the git history using git ls-tree
|
||||
@@ -47,16 +47,16 @@ if ($commitCount -gt 0) {
|
||||
$trackedFiles = git ls-tree -r HEAD --name-only 2>$null
|
||||
|
||||
if ($trackedFiles -match "welcome.txt") {
|
||||
Write-Host "[PASS] welcome.txt is committed" -ForegroundColor Green
|
||||
Write-Pass "welcome.txt is committed" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] welcome.txt is not in the commit history" -ForegroundColor Red
|
||||
Write-Fail "welcome.txt is not in the commit history" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
if ($trackedFiles -match "instructions.txt") {
|
||||
Write-Host "[PASS] instructions.txt is committed" -ForegroundColor Green
|
||||
Write-Pass "instructions.txt is committed" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] instructions.txt is not in the commit history" -ForegroundColor Red
|
||||
Write-Fail "instructions.txt is not in the commit history" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
}
|
||||
@@ -67,8 +67,6 @@ if ($statusOutput) {
|
||||
Write-Host "[INFO] You have uncommitted changes. This is OK, but make sure all required files are committed." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Set-Location ".."
|
||||
|
||||
Write-Host ""
|
||||
if ($allChecksPassed) {
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
|
||||
@@ -44,6 +44,7 @@ The setup script will create an `answers.md` file in the challenge directory wit
|
||||
7. View specific commits: `git show <commit-hash>`
|
||||
8. Compare specific commits: `git diff <commit1> <commit2> <file>`
|
||||
9. Fill in your answers in `answers.md`
|
||||
10. Remember to save `answers.md`
|
||||
|
||||
> **Important Notes:**
|
||||
> - You can use any Git commands you like to explore the repository
|
||||
|
||||
@@ -10,52 +10,53 @@
|
||||
- answers.txt exists with correct information about commit history
|
||||
#>
|
||||
|
||||
. "$PSScriptRoot\..\..\util.ps1"
|
||||
|
||||
Write-Host "`n=== Verifying Module 02 Solution ===" -ForegroundColor Cyan
|
||||
|
||||
$allChecksPassed = $true
|
||||
$challengeRoot = "$PSScriptRoot\challenge"
|
||||
|
||||
|
||||
# Check if challenge directory exists
|
||||
if (-not (Test-Path "challenge")) {
|
||||
Write-Host "[FAIL] Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red
|
||||
if (-not (Test-Path $challengeRoot)) {
|
||||
Write-Fail "Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Set-Location "challenge"
|
||||
|
||||
# Check if git repository exists
|
||||
if (-not (Test-Path ".git")) {
|
||||
Write-Host "[FAIL] Not a git repository. Did you run setup.ps1?" -ForegroundColor Red
|
||||
Set-Location ..
|
||||
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||
Write-Fail "Not a git repository. Did you run setup.ps1?" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if answers.md exists
|
||||
if (-not (Test-Path "answers.md")) {
|
||||
Write-Host "[FAIL] answers.md not found. Did you run setup.ps1?" -ForegroundColor Red
|
||||
Write-Host "[HINT] The setup script should have created answers.md for you" -ForegroundColor Yellow
|
||||
if (-not (Test-Path "$challengeRoot\answers.md")) {
|
||||
Write-Fail "answers.md not found. Did you run setup.ps1?" -ForegroundColor Red
|
||||
Write-Hint "The setup script should have created answers.md for you" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
} else {
|
||||
Write-Host "[PASS] answers.md exists" -ForegroundColor Green
|
||||
Write-Pass "answers.md exists" -ForegroundColor Green
|
||||
|
||||
# Read the answers file
|
||||
$answers = Get-Content "answers.md" -Raw
|
||||
$answers = Get-Content "$challengeRoot\answers.md" -Raw
|
||||
$answersLower = $answers.ToLower()
|
||||
|
||||
# Check 1: Contains "5" or "five" for commit count
|
||||
if ($answersLower -match "5|five|fem") {
|
||||
Write-Host "[PASS] Correct commit count found" -ForegroundColor Green
|
||||
Write-Pass "Correct commit count found" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] Commit count not found or incorrect" -ForegroundColor Red
|
||||
Write-Host "[HINT] Use 'git log --oneline' to count commits easily" -ForegroundColor Yellow
|
||||
Write-Fail "Commit count not found or incorrect" -ForegroundColor Red
|
||||
Write-Hint "Use 'git log --oneline' to count commits easily" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check 2: Contains "database" keyword for third commit
|
||||
if ($answersLower -match "database") {
|
||||
Write-Host "[PASS] Third commit message identified" -ForegroundColor Green
|
||||
Write-Pass "Third commit message identified" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] Third commit message not found" -ForegroundColor Red
|
||||
Write-Host "[HINT] Use 'git log' to see commit messages in order" -ForegroundColor Yellow
|
||||
Write-Fail "Third commit message not found" -ForegroundColor Red
|
||||
Write-Hint "Use 'git log' to see commit messages in order" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
@@ -64,38 +65,37 @@ if (-not (Test-Path "answers.md")) {
|
||||
$hasDatabase = $answersLower -match "database"
|
||||
|
||||
if ($hasAuth -and $hasDatabase) {
|
||||
Write-Host "[PASS] Both files identified for bug fix commit" -ForegroundColor Green
|
||||
Write-Pass "Both files identified for bug fix commit" -ForegroundColor Green
|
||||
} elseif ($hasAuth -or $hasDatabase) {
|
||||
Write-Host "[PARTIAL] Only one file found - there are TWO files modified in this commit" -ForegroundColor Yellow
|
||||
Write-Host "[HINT] Use 'git log --stat' or 'git show <commit-hash> --name-only' to see ALL files changed" -ForegroundColor Yellow
|
||||
Write-Hint "Use 'git log --stat' or 'git show <commit-hash> --name-only' to see ALL files changed" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
} else {
|
||||
Write-Host "[FAIL] Files modified in bug fix commit not found" -ForegroundColor Red
|
||||
Write-Host "[HINT] Use 'git log --stat' to see which files were changed in each commit" -ForegroundColor Yellow
|
||||
Write-Fail "Files modified in bug fix commit not found" -ForegroundColor Red
|
||||
Write-Hint "Use 'git log --stat' to see which files were changed in each commit" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check 4: Contains "config" keyword for staged file
|
||||
if ($answersLower -match "config.py") {
|
||||
Write-Host "[PASS] Staged file identified" -ForegroundColor Green
|
||||
Write-Pass "Staged file identified" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] Staged file not identified" -ForegroundColor Red
|
||||
Write-Host "[HINT] Use 'git status' or 'git diff --staged' to see staged changes" -ForegroundColor Yellow
|
||||
Write-Fail "Staged file not identified" -ForegroundColor Red
|
||||
Write-Hint "Use 'git status' or 'git diff --staged' to see staged changes" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check 5: Contains "unicorn" for the secret code
|
||||
if ($answersLower -match "unicorn") {
|
||||
Write-Host "[PASS] Secret code found!" -ForegroundColor Green
|
||||
Write-Pass "Secret code found!" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] Secret code not found" -ForegroundColor Red
|
||||
Write-Host "[HINT] Use 'git diff <commit3> <commit4> database.py' to find the secret code" -ForegroundColor Yellow
|
||||
Write-Fail "Secret code not found" -ForegroundColor Red
|
||||
Write-Hint "Use 'git diff <commit3> <commit4> database.py' to find the secret code" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Set-Location ..
|
||||
|
||||
# Final summary
|
||||
if ($allChecksPassed) {
|
||||
|
||||
@@ -94,7 +94,8 @@ Now practice creating your own branch:
|
||||
2. Check the changes you committed before. You'll notice that they're gone!
|
||||
3. Now edit a file or create a new file (perhaps GUIDE.md, content of the file doesn't matter) and add it and commit it on your `main` branch (hint: `git add .`, `git commit -m`)
|
||||
- This way we create diverging branches. The `main` branch has changes as well as your new `my-feature` branch.
|
||||
- Run `git log --oneline --graph --all` to see how the tree is looking
|
||||
- To see changes on the branch you're on, just run `git log --oneline --graph`
|
||||
- Run `git log --oneline --graph --all` to see how the tree is looking, `main` should have diverged
|
||||
4. Switch back to your branch `git switch my-feature`
|
||||
5. The changes from the `main` branch are now gone. Check the changes you committed before. You'll notice they're back!
|
||||
|
||||
@@ -104,12 +105,14 @@ Bring your work into main:
|
||||
|
||||
1. Go back to the main branch `git switch main`
|
||||
2. Run a `git log --oneline --graph --all` to see that the `HEAD` is on your `main` branch
|
||||
3. It might be wise to first ensure that we're using Visual Studio Code to handle merge messages. If you haven't already set `git config --global core.editor "code --wait"` this sets Visual Studio Code to be the default editor for anything Git related.
|
||||
- Hint: your `HEAD` is git's way of telling you <q>you're here</q>
|
||||
3. It might be wise to first ensure that we're using Visual Studio Code to handle merge messages. If you haven't already set `git config --global core.editor "code --wait"` this sets Visual Studio Code to be the default editor for anything git related
|
||||
4. Let's merge the recently created branch `git merge my-feature`
|
||||
5. Visual Studio Code should open with a commit message. In order to solidify the commit simply close the window. That tells Git that the commit message has been written and the change should be committed.
|
||||
5. Visual Studio Code should open with a commit message. In order to solidify the commit simply close the window. That tells git that the commit message has been written and the change should be committed
|
||||
6. Now run `git log --oneline --graph --all` and see your changes merge into the `main` branch!
|
||||
7. Now let's clean up a bit, run `git branch -d my-feature` to remove the recently merged branch.
|
||||
- If you hadn't merged the branch first this command would fail as Git will warn you that you have changes not merged into the `main` branch
|
||||
7. Now let's clean up a bit, run `git branch -d my-feature` to remove the recently merged branch
|
||||
- If you hadn't merged the branch first this command would fail as git will warn you that you have changes not merged into the `main` branch Remember, once we've deleted the branch, we can no longer access it, and it's lost forever. That's why there is a safeguard when changes are unmerged when running
|
||||
- Technically it's possible to recover the branch, however this requires using `git reflog` within the git garbage collection period which is usually 30 days-ish. This is however advanced, but I'd recommend asking your local LLM a question like <q>How can I restore a deleted branch</q>. It will probably come up with the right answer
|
||||
|
||||
You should see your feature branch merged into main!
|
||||
|
||||
@@ -139,7 +142,7 @@ git merge another-feature
|
||||
|
||||
### What is a Branch?
|
||||
|
||||
A **branch** is a lightweight movable pointer to a commit. When you create a branch, Git creates a new pointer - it doesn't copy all your files!
|
||||
A **branch** is a lightweight movable pointer to a commit. When you create a branch, git creates a new pointer - it doesn't copy all your files!
|
||||
|
||||
```
|
||||
main: A---B---C
|
||||
@@ -154,7 +157,7 @@ my-feature: D---E
|
||||
|
||||
### What is HEAD?
|
||||
|
||||
`HEAD` points to your current branch. It's Git's way of saying "you are here."
|
||||
`HEAD` points to your current branch. It's git's way of saying "you are here."
|
||||
|
||||
```pwsh
|
||||
# HEAD points to main
|
||||
@@ -181,7 +184,7 @@ main: A---B---C---M
|
||||
feature: D---E
|
||||
```
|
||||
|
||||
Git creates a merge commit `M` that has two parents (C and E).
|
||||
git creates a merge commit `M` that has two parents (C and E).
|
||||
|
||||
**Fast-forward merge**:
|
||||
```
|
||||
@@ -194,7 +197,7 @@ After merge:
|
||||
main: A---B---C---D
|
||||
```
|
||||
|
||||
If main hasn't changed, Git just moves the pointer forward. No merge commit needed!
|
||||
If main hasn't changed, git just moves the pointer forward. No merge commit needed!
|
||||
|
||||
## Key Commands
|
||||
|
||||
@@ -340,7 +343,7 @@ After completing this module, you understand:
|
||||
|
||||
## Next Steps
|
||||
|
||||
Ready to continue? The next module covers **merge conflicts** - what happens when Git can't automatically merge changes.
|
||||
Ready to continue? The next module covers **merge conflicts** - what happens when git can't automatically merge changes.
|
||||
|
||||
To start over:
|
||||
```pwsh
|
||||
@@ -348,4 +351,4 @@ To start over:
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
**Need help?** Review the commands above, or run `git status` to see what Git suggests!
|
||||
**Need help?** Review the commands above, or run `git status` to see what git suggests!
|
||||
|
||||
@@ -12,47 +12,20 @@
|
||||
|
||||
$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
|
||||
}
|
||||
|
||||
$challengeRoot = "$PSScriptRoot\challenge"
|
||||
# ============================================================================
|
||||
# Check challenge directory exists
|
||||
# ============================================================================
|
||||
|
||||
if (-not (Test-Path "challenge")) {
|
||||
if (-not (Test-Path $challengeRoot)) {
|
||||
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")) {
|
||||
if (-not (Test-Path "$challengeRoot\.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
|
||||
}
|
||||
|
||||
@@ -62,24 +35,7 @@ Write-Host "`n=== Verifying Module 03: Branching and Merging ===" -ForegroundCol
|
||||
# Detect the main branch name (could be main, master, etc.)
|
||||
# ============================================================================
|
||||
# Try to get the default branch from remote origin first
|
||||
$mainBranch = git symbolic-ref refs/remotes/origin/HEAD 2>$null | Split-Path -Leaf
|
||||
if (-not $mainBranch) {
|
||||
# Fallback: try to detect from local branches
|
||||
$allBranches = git branch --list 2>$null | ForEach-Object { $_.Trim('* ') }
|
||||
if ($allBranches -contains "main") {
|
||||
$mainBranch = "main"
|
||||
} elseif ($allBranches -contains "master") {
|
||||
$mainBranch = "master"
|
||||
} else {
|
||||
# Get the default branch from git config
|
||||
$mainBranch = git config --get init.defaultBranch
|
||||
if (-not $mainBranch) {
|
||||
# Ultimate fallback: use the first branch
|
||||
$mainBranch = $allBranches | Select-Object -First 1
|
||||
if (-not $mainBranch) { $mainBranch = "main" }
|
||||
}
|
||||
}
|
||||
}
|
||||
$mainBranch = Get-MainBranch
|
||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
||||
|
||||
# ============================================================================
|
||||
|
||||
@@ -22,16 +22,16 @@ This creates a repository with two feature branches that have conflicting change
|
||||
|
||||
## 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.
|
||||
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
|
||||
- ✅ 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.
|
||||
**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
|
||||
|
||||
@@ -249,7 +249,7 @@ For this challenge, we want **both settings**, so:
|
||||
|
||||
### Part 9: Mark the Conflict as Resolved
|
||||
|
||||
Tell Git you've resolved the conflict:
|
||||
Tell git you've resolved the conflict:
|
||||
|
||||
```bash
|
||||
# Stage the resolved file
|
||||
@@ -267,7 +267,7 @@ All conflicts fixed but you are still merging.
|
||||
(use "git commit" to conclude merge)
|
||||
```
|
||||
|
||||
Perfect! Git confirms the conflict is resolved.
|
||||
Perfect! git confirms the conflict is resolved.
|
||||
|
||||
### Part 10: Complete the Merge
|
||||
|
||||
@@ -277,7 +277,7 @@ Commit the merge:
|
||||
git commit
|
||||
```
|
||||
|
||||
Git will open an editor with a default merge message. You can accept it or customize it, then save and close.
|
||||
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!
|
||||
|
||||
@@ -436,7 +436,7 @@ git diff main..feature-branch
|
||||
|
||||
## Merge Tools
|
||||
|
||||
Git supports visual merge tools that make resolving conflicts easier:
|
||||
git supports visual merge tools that make resolving conflicts easier:
|
||||
|
||||
```bash
|
||||
# Configure a merge tool (one-time setup)
|
||||
@@ -484,4 +484,4 @@ To start over:
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
**Need help?** Review the steps above, or run `git status` to see what Git suggests!
|
||||
**Need help?** Review the steps above, or run `git status` to see what git suggests!
|
||||
|
||||
@@ -11,49 +11,26 @@
|
||||
- Ensuring valid JSON syntax
|
||||
#>
|
||||
|
||||
. "$PSScriptRoot\..\..\util.ps1"
|
||||
|
||||
$script:allChecksPassed = $true
|
||||
$challengeRoot = "$PSScriptRoot\challenge"
|
||||
|
||||
# ============================================================================
|
||||
# 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
|
||||
}
|
||||
Write-Host $PSScriptRoot
|
||||
|
||||
# ============================================================================
|
||||
# Check challenge directory exists
|
||||
# ============================================================================
|
||||
|
||||
if (-not (Test-Path "challenge")) {
|
||||
Write-Host "[ERROR] Challenge directory not found." -ForegroundColor Red
|
||||
if (-not (Test-Path $challengeRoot)) {
|
||||
Write-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
|
||||
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||
Write-Error "Not a git repository." -ForegroundColor Red
|
||||
Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -63,24 +40,7 @@ Write-Host "`n=== Verifying Module 04: Merge Conflicts ===" -ForegroundColor Cya
|
||||
# Detect the main branch name (could be main, master, etc.)
|
||||
# ============================================================================
|
||||
# Try to get the default branch from remote origin first
|
||||
$mainBranch = git symbolic-ref refs/remotes/origin/HEAD 2>$null | Split-Path -Leaf
|
||||
if (-not $mainBranch) {
|
||||
# Fallback: try to detect from local branches
|
||||
$allBranches = git branch --list 2>$null | ForEach-Object { $_.Trim('* ') }
|
||||
if ($allBranches -contains "main") {
|
||||
$mainBranch = "main"
|
||||
} elseif ($allBranches -contains "master") {
|
||||
$mainBranch = "master"
|
||||
} else {
|
||||
# Get the default branch from git config
|
||||
$mainBranch = git config --get init.defaultBranch
|
||||
if (-not $mainBranch) {
|
||||
# Ultimate fallback: use the first branch
|
||||
$mainBranch = $allBranches | Select-Object -First 1
|
||||
if (-not $mainBranch) { $mainBranch = "main" }
|
||||
}
|
||||
}
|
||||
}
|
||||
$mainBranch = Get-MainBranch
|
||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
||||
|
||||
# ============================================================================
|
||||
@@ -97,22 +57,20 @@ if ($currentBranch -eq $mainBranch) {
|
||||
# ============================================================================
|
||||
# Check that merge is not in progress
|
||||
# ============================================================================
|
||||
if (Test-Path ".git/MERGE_HEAD") {
|
||||
if (Test-Path "$challengeRoot\.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")) {
|
||||
if (-not (Test-Path "$challengeRoot\config.json")) {
|
||||
Write-Fail "File 'config.json' not found"
|
||||
Write-Hint "The config.json file should exist"
|
||||
Pop-Location
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -120,14 +78,13 @@ if (-not (Test-Path "config.json")) {
|
||||
# Verify config.json is valid JSON
|
||||
# ============================================================================
|
||||
try {
|
||||
$configContent = Get-Content "config.json" -Raw
|
||||
$configContent = Get-Content "$challengeRoot\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
|
||||
}
|
||||
|
||||
@@ -137,7 +94,6 @@ try {
|
||||
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"
|
||||
@@ -163,8 +119,11 @@ if ($config.app.debug -eq $true) {
|
||||
# ============================================================================
|
||||
# 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"
|
||||
git merge-base --is-ancestor add-timeout main
|
||||
$addTimeoutMerged = $LASTEXITCODE -eq 0
|
||||
|
||||
git merge-base --is-ancestor add-debug main
|
||||
$addDebugMerged = $LASTEXITCODE -eq 0
|
||||
|
||||
if ($addTimeoutMerged) {
|
||||
Write-Pass "add-timeout branch has been merged"
|
||||
@@ -197,7 +156,6 @@ if ($totalCommits -ge 5) {
|
||||
Write-Hint "Make sure both branches are merged"
|
||||
}
|
||||
|
||||
Pop-Location
|
||||
|
||||
# ============================================================================
|
||||
# Final summary
|
||||
|
||||
@@ -52,10 +52,13 @@ First, see what commits are on the development branch:
|
||||
```pwsh
|
||||
cd challenge
|
||||
|
||||
# View all commits on development branch
|
||||
git log --oneline development
|
||||
# First let's see what files are in the current branch and notice that there is a file security.py
|
||||
ls
|
||||
|
||||
# View the full commit graph
|
||||
# View all commits on development branch
|
||||
git log --oneline --graph
|
||||
|
||||
# View the full commit graph for all branches
|
||||
git log --oneline --graph --all
|
||||
```
|
||||
|
||||
@@ -87,6 +90,9 @@ git switch main
|
||||
|
||||
# Verify you're on main
|
||||
git branch
|
||||
|
||||
# See what files exist. Notice that we no longer have a security.py file
|
||||
ls
|
||||
```
|
||||
|
||||
The `*` should be next to `main`.
|
||||
@@ -96,8 +102,6 @@ The `*` should be next to `main`.
|
||||
# See main's commits
|
||||
git log --oneline
|
||||
|
||||
# See what files exist
|
||||
ls
|
||||
```
|
||||
|
||||
Main should only have the initial app and README - no bug fixes yet, no experimental features.
|
||||
@@ -113,6 +117,7 @@ Now copy the bug fix commits from development to main:
|
||||
2. Cherry-pick the security fix:
|
||||
```pwsh
|
||||
git cherry-pick <security-fix-hash>
|
||||
ls # we now have the security.py file!
|
||||
|
||||
# Example if the hash is abc1234:
|
||||
# git cherry-pick abc1234
|
||||
@@ -125,6 +130,7 @@ Now copy the bug fix commits from development to main:
|
||||
5. Cherry-pick the performance fix:
|
||||
```pwsh
|
||||
git cherry-pick <performance-fix-hash>
|
||||
ls # we now have the cache.py file!
|
||||
```
|
||||
|
||||
6. Verify both fixes are now on main:
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
the bug fixes to the main branch.
|
||||
#>
|
||||
|
||||
. "$PSScriptRoot\..\..\util.ps1"
|
||||
|
||||
# Remove existing challenge directory if present
|
||||
if (Test-Path "challenge") {
|
||||
Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow
|
||||
@@ -42,11 +44,7 @@ git add app.py
|
||||
git commit -m "Initial app implementation" | Out-Null
|
||||
|
||||
# Detect the main branch name after first commit
|
||||
$mainBranch = git branch --show-current
|
||||
if (-not $mainBranch) {
|
||||
$mainBranch = git config --get init.defaultBranch
|
||||
if (-not $mainBranch) { $mainBranch = "main" }
|
||||
}
|
||||
$mainBranch = Get-MainBranch
|
||||
Write-Host "Default branch detected: $mainBranch" -ForegroundColor Yellow
|
||||
|
||||
$readme = @"
|
||||
|
||||
@@ -9,168 +9,136 @@
|
||||
to the main branch without merging the experimental features.
|
||||
#>
|
||||
|
||||
Set-Location "challenge" -ErrorAction SilentlyContinue
|
||||
. "$PSScriptRoot\..\..\util.ps1"
|
||||
|
||||
# Check if challenge directory exists
|
||||
if (-not (Test-Path "../verify.ps1")) {
|
||||
Write-Host "Error: Please run this script from the module directory" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
$challengeRoot = "$PSScriptRoot\challenge"
|
||||
|
||||
if (-not (Test-Path ".")) {
|
||||
if (-not (Test-Path $challengeRoot)) {
|
||||
Write-Host "Error: Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Verifying your solution..." -ForegroundColor Cyan
|
||||
|
||||
# Check if git repository exists
|
||||
if (-not (Test-Path ".git")) {
|
||||
Write-Host "[FAIL] No git repository found." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||
Write-Fail "No git repository found." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Detect the main branch name
|
||||
$allBranches = git branch --list 2>$null | ForEach-Object { $_.Trim('* ') }
|
||||
if ($allBranches -contains "main") {
|
||||
$mainBranch = "main"
|
||||
} elseif ($allBranches -contains "master") {
|
||||
$mainBranch = "master"
|
||||
} else {
|
||||
$mainBranch = git config --get init.defaultBranch
|
||||
if (-not $mainBranch) {
|
||||
$mainBranch = $allBranches | Select-Object -First 1
|
||||
if (-not $mainBranch) { $mainBranch = "main" }
|
||||
}
|
||||
}
|
||||
$mainBranch = Get-MainBranch
|
||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
||||
|
||||
# Check current branch
|
||||
$currentBranch = git branch --show-current 2>$null
|
||||
if ($currentBranch -ne $mainBranch) {
|
||||
Write-Host "[FAIL] You should be on the '$mainBranch' branch." -ForegroundColor Red
|
||||
Write-Fail "You should be on the '$mainBranch' branch." -ForegroundColor Red
|
||||
Write-Host "Current branch: $currentBranch" -ForegroundColor Yellow
|
||||
Write-Host "Hint: Use 'git checkout $mainBranch' to switch to $mainBranch branch" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
Write-Hint "Use 'git checkout $mainBranch' to switch to $mainBranch branch" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if there's an ongoing cherry-pick
|
||||
if (Test-Path ".git/CHERRY_PICK_HEAD") {
|
||||
Write-Host "[FAIL] Cherry-pick is not complete. There may be unresolved conflicts." -ForegroundColor Red
|
||||
Write-Host "Hint: Resolve any conflicts, then use:" -ForegroundColor Yellow
|
||||
if (Test-Path "$challengeRoot\.git\CHERRY_PICK_HEAD") {
|
||||
Write-Fail "Cherry-pick is not complete. There may be unresolved conflicts." -ForegroundColor Red
|
||||
Write-Hint "Resolve any conflicts, then use:" -ForegroundColor Yellow
|
||||
Write-Host " git add <file>" -ForegroundColor White
|
||||
Write-Host " git cherry-pick --continue" -ForegroundColor White
|
||||
Write-Host "Or abort with: git cherry-pick --abort" -ForegroundColor White
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check commit count on main (should be 4: 2 initial + 2 cherry-picked)
|
||||
$mainCommitCount = (git rev-list --count $mainBranch 2>$null)
|
||||
if ($mainCommitCount -ne 4) {
|
||||
Write-Host "[FAIL] Expected 4 commits on $mainBranch branch, found $mainCommitCount" -ForegroundColor Red
|
||||
Write-Fail "Expected 4 commits on $mainBranch branch, found $mainCommitCount" -ForegroundColor Red
|
||||
if ($mainCommitCount -lt 4) {
|
||||
Write-Host "Hint: You should cherry-pick 2 bug fix commits to $mainBranch" -ForegroundColor Yellow
|
||||
Write-Hint "You should cherry-pick 2 bug fix commits to $mainBranch" -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host "Hint: You should cherry-pick ONLY the 2 bug fix commits, not all commits" -ForegroundColor Yellow
|
||||
Write-Hint "You should cherry-pick ONLY the 2 bug fix commits, not all commits" -ForegroundColor Yellow
|
||||
}
|
||||
Write-Host "`nExpected commits on ${mainBranch}:" -ForegroundColor Yellow
|
||||
Write-Host " 1. Initial app implementation" -ForegroundColor White
|
||||
Write-Host " 2. Add README" -ForegroundColor White
|
||||
Write-Host " 3. Fix security vulnerability in input validation (cherry-picked)" -ForegroundColor White
|
||||
Write-Host " 4. Fix performance issue with data caching (cherry-picked)" -ForegroundColor White
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check for merge commits (should be none - cherry-pick doesn't create merge commits)
|
||||
$mergeCommits = git log --merges --oneline $mainBranch 2>$null
|
||||
if ($mergeCommits) {
|
||||
Write-Host "[FAIL] Found merge commits on $mainBranch. You should use cherry-pick, not merge." -ForegroundColor Red
|
||||
Write-Host "Hint: Use 'git cherry-pick <commit-hash>' instead of 'git merge'" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
Write-Fail "Found merge commits on $mainBranch. You should use cherry-pick, not merge." -ForegroundColor Red
|
||||
Write-Hint "Use 'git cherry-pick <commit-hash>' instead of 'git merge'" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that security.py exists (from the security fix commit)
|
||||
if (-not (Test-Path "security.py")) {
|
||||
Write-Host "[FAIL] security.py not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Host "Hint: You need to cherry-pick the 'Fix security vulnerability' commit" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
if (-not (Test-Path "$challengeRoot\security.py")) {
|
||||
Write-Fail "security.py not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Hint "You need to cherry-pick the 'Fix security vulnerability' commit" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that security.py has the security fix
|
||||
$securityContent = Get-Content "security.py" -Raw
|
||||
$securityContent = Get-Content "$challengeRoot\security.py" -Raw
|
||||
|
||||
if ($securityContent -notmatch "sanitize_input") {
|
||||
Write-Host "[FAIL] security.py is missing the sanitize_input function." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
Write-Fail "security.py is missing the sanitize_input function." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($securityContent -notmatch "validate_token") {
|
||||
Write-Host "[FAIL] security.py is missing the validate_token function." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
Write-Fail "security.py is missing the validate_token function." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that app.py exists
|
||||
if (-not (Test-Path "app.py")) {
|
||||
Write-Host "[FAIL] app.py not found." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
if (-not (Test-Path "$challengeRoot\app.py")) {
|
||||
Write-Fail "app.py not found." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that cache.py exists (from performance fix)
|
||||
if (-not (Test-Path "cache.py")) {
|
||||
Write-Host "[FAIL] cache.py not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Host "Hint: You need to cherry-pick the 'Fix performance issue' commit" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
if (-not (Test-Path "$challengeRoot\cache.py")) {
|
||||
Write-Fail "cache.py not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Hint "You need to cherry-pick the 'Fix performance issue' commit" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that cache.py has the DataCache class
|
||||
$cacheContent = Get-Content "cache.py" -Raw
|
||||
$cacheContent = Get-Content "$challengeRoot\cache.py" -Raw
|
||||
|
||||
if ($cacheContent -notmatch "DataCache") {
|
||||
Write-Host "[FAIL] cache.py is missing the DataCache class." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
Write-Fail "cache.py is missing the DataCache class." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($cacheContent -notmatch "def get\(") {
|
||||
Write-Host "[FAIL] cache.py is missing the get method." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
Write-Fail "cache.py is missing the get method." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that app.py does NOT have experimental features
|
||||
$appContent = Get-Content "app.py" -Raw
|
||||
$appContent = Get-Content "$challengeRoot\app.py" -Raw
|
||||
|
||||
# Should NOT have experimental features
|
||||
if ($appContent -match "experimental_mode") {
|
||||
Write-Host "[FAIL] app.py contains experimental features (experimental_mode)." -ForegroundColor Red
|
||||
Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||
Write-Fail "app.py contains experimental features (experimental_mode)." -ForegroundColor Red
|
||||
Write-Hint "You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||
Write-Host " The experimental feature commits should stay on development branch only" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($appContent -match "beta_features") {
|
||||
Write-Host "[FAIL] app.py contains experimental features (beta_features)." -ForegroundColor Red
|
||||
Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
Write-Fail "app.py contains experimental features (beta_features)." -ForegroundColor Red
|
||||
Write-Hint "You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($appContent -match "enable_experimental_features") {
|
||||
Write-Host "[FAIL] app.py contains experimental features (enable_experimental_features)." -ForegroundColor Red
|
||||
Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
Write-Fail "app.py contains experimental features (enable_experimental_features)." -ForegroundColor Red
|
||||
Write-Hint "You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -191,25 +159,22 @@ foreach ($commit in $commitArray) {
|
||||
}
|
||||
|
||||
if (-not $hasSecurityFix) {
|
||||
Write-Host "[FAIL] Security fix commit not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Host "Hint: Cherry-pick the 'Fix security vulnerability' commit from development" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
Write-Fail "Security fix commit not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Hint "Cherry-pick the 'Fix security vulnerability' commit from development" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not $hasPerformanceFix) {
|
||||
Write-Host "[FAIL] Performance fix commit not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Host "Hint: Cherry-pick the 'Fix performance issue' commit from development" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
Write-Fail "Performance fix commit not found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Hint "Cherry-pick the 'Fix performance issue' commit from development" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Verify development branch still has all commits
|
||||
$devCommitCount = (git rev-list --count development 2>$null)
|
||||
if ($devCommitCount -ne 6) {
|
||||
Write-Host "[FAIL] Development branch should still have 6 commits." -ForegroundColor Red
|
||||
Write-Fail "Development branch should still have 6 commits." -ForegroundColor Red
|
||||
Write-Host "Found: $devCommitCount commits" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -226,5 +191,4 @@ Write-Host "`nPerfect use of cherry-pick!" -ForegroundColor Green
|
||||
Write-Host "You selectively applied critical fixes without merging unfinished features.`n" -ForegroundColor Green
|
||||
Write-Host "Try 'git log --oneline --graph --all' to see both branches." -ForegroundColor Cyan
|
||||
|
||||
Set-Location ..
|
||||
exit 0
|
||||
|
||||
@@ -52,6 +52,9 @@ You're working on a calculator application. A developer added a `divide` functio
|
||||
1. **Navigate to the challenge directory:**
|
||||
```pwsh
|
||||
cd challenge
|
||||
|
||||
# and check the contents. We should notice that divide.py exists, this will be reverted
|
||||
ls
|
||||
```
|
||||
|
||||
2. **Check which branch you're on** (you should be on `regular-revert`):
|
||||
|
||||
@@ -9,23 +9,23 @@
|
||||
- multi-revert: Multiple commits reverted
|
||||
#>
|
||||
|
||||
. "$PSScriptRoot\..\..\util.ps1"
|
||||
|
||||
Write-Host "`n=== Verifying Module 06: Git Revert Solutions ===" -ForegroundColor Cyan
|
||||
|
||||
$allChecksPassed = $true
|
||||
$originalDir = Get-Location
|
||||
|
||||
$challengeRoot = "$PSScriptRoot\challenge"
|
||||
|
||||
# Check if challenge directory exists
|
||||
if (-not (Test-Path "challenge")) {
|
||||
Write-Host "[FAIL] Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||
if (-not (Test-Path "$challengeRoot")) {
|
||||
Write-Fail "Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Set-Location "challenge"
|
||||
|
||||
# Check if git repository exists
|
||||
if (-not (Test-Path ".git")) {
|
||||
Write-Host "[FAIL] Not a git repository. Run setup.ps1 first." -ForegroundColor Red
|
||||
Set-Location $originalDir
|
||||
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||
Write-Fail "Not a git repository. Run setup.ps1 first." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -37,50 +37,50 @@ Write-Host "`n=== Scenario 1: Regular Revert ===" -ForegroundColor Cyan
|
||||
git switch regular-revert 2>&1 | Out-Null
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[FAIL] regular-revert branch not found" -ForegroundColor Red
|
||||
Write-Fail "regular-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
|
||||
Write-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
|
||||
Write-Fail "No revert commit found" -ForegroundColor Red
|
||||
Write-Hint "Use: git revert <commit-hash>" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that divide.py is removed (was reverted)
|
||||
if (-not (Test-Path "divide.py")) {
|
||||
Write-Host "[PASS] Broken divide.py successfully reverted (file removed)" -ForegroundColor Green
|
||||
if (-not (Test-Path "$challengeRoot\divide.py")) {
|
||||
Write-Pass "Broken divide.py successfully reverted (file removed)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] divide.py still exists (should be reverted)" -ForegroundColor Red
|
||||
Write-Host "[HINT] The bad commit should be reverted, removing divide.py" -ForegroundColor Yellow
|
||||
Write-Fail "divide.py still exists (should be reverted)" -ForegroundColor Red
|
||||
Write-Hint "The bad commit should be reverted, removing divide.py" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that calculator.py exists and has correct content
|
||||
if (Test-Path "calculator.py") {
|
||||
$calcContent = Get-Content "calculator.py" -Raw
|
||||
if (Test-Path "$challengeRoot\calculator.py") {
|
||||
$calcContent = Get-Content "$challengeRoot\calculator.py" -Raw
|
||||
|
||||
# Check that modulo function still exists (should be preserved)
|
||||
if ($calcContent -match "def modulo") {
|
||||
Write-Host "[PASS] modulo function preserved (good commit after bad one)" -ForegroundColor Green
|
||||
Write-Pass "modulo function preserved (good commit after bad one)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] modulo function missing (should still exist)" -ForegroundColor Red
|
||||
Write-Host "[HINT] Only revert the bad commit, not the good ones after it" -ForegroundColor Yellow
|
||||
Write-Fail "modulo function missing (should still exist)" -ForegroundColor Red
|
||||
Write-Hint "Only revert the bad commit, not the good ones after it" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that multiply function exists (should be preserved)
|
||||
if ($calcContent -match "def multiply") {
|
||||
Write-Host "[PASS] multiply function preserved (good commit before bad one)" -ForegroundColor Green
|
||||
Write-Pass "multiply function preserved (good commit before bad one)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] multiply function missing" -ForegroundColor Red
|
||||
Write-Fail "multiply function missing" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
} else {
|
||||
Write-Host "[FAIL] calculator.py not found" -ForegroundColor Red
|
||||
Write-Fail "calculator.py not found" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,7 @@ Write-Host "`n=== Scenario 2: Multi Revert ===" -ForegroundColor Cyan
|
||||
git switch multi-revert 2>&1 | Out-Null
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[FAIL] multi-revert branch not found" -ForegroundColor Red
|
||||
Write-Fail "multi-revert branch not found" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
} else {
|
||||
# Count revert commits
|
||||
@@ -101,56 +101,54 @@ if ($LASTEXITCODE -ne 0) {
|
||||
$revertCount = ($revertCommits | Measure-Object).Count
|
||||
|
||||
if ($revertCount -ge 2) {
|
||||
Write-Host "[PASS] Found $revertCount revert commits (expected at least 2)" -ForegroundColor Green
|
||||
Write-Pass "Found $revertCount revert commits (expected at least 2)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] Found only $revertCount revert commit(s), need at least 2" -ForegroundColor Red
|
||||
Write-Host "[HINT] Revert both bad commits: git revert <commit1> <commit2>" -ForegroundColor Yellow
|
||||
Write-Fail "Found only $revertCount revert commit(s), need at least 2" -ForegroundColor Red
|
||||
Write-Hint "Revert both bad commits: git revert <commit1> <commit2>" -ForegroundColor Yellow
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that sqrt.py is removed (reverted)
|
||||
if (-not (Test-Path "sqrt.py")) {
|
||||
Write-Host "[PASS] Broken sqrt.py successfully reverted (file removed)" -ForegroundColor Green
|
||||
if (-not (Test-Path "$challengeRoot\sqrt.py")) {
|
||||
Write-Pass "Broken sqrt.py successfully reverted (file removed)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] sqrt.py still exists (should be reverted)" -ForegroundColor Red
|
||||
Write-Fail "sqrt.py still exists (should be reverted)" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that logarithm.py is removed (reverted)
|
||||
if (-not (Test-Path "logarithm.py")) {
|
||||
Write-Host "[PASS] Broken logarithm.py successfully reverted (file removed)" -ForegroundColor Green
|
||||
if (-not (Test-Path "$challengeRoot\logarithm.py")) {
|
||||
Write-Pass "Broken logarithm.py successfully reverted (file removed)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] logarithm.py still exists (should be reverted)" -ForegroundColor Red
|
||||
Write-Fail "logarithm.py still exists (should be reverted)" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check calculator.py content
|
||||
if (Test-Path "calculator.py") {
|
||||
$calcContent = Get-Content "calculator.py" -Raw
|
||||
if (Test-Path "$challengeRoot\calculator.py") {
|
||||
$calcContent = Get-Content "$challengeRoot\calculator.py" -Raw
|
||||
|
||||
# Check that power function still exists (good commit before bad ones)
|
||||
if ($calcContent -match "def power") {
|
||||
Write-Host "[PASS] power function preserved" -ForegroundColor Green
|
||||
Write-Pass "power function preserved" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] power function missing (should still exist)" -ForegroundColor Red
|
||||
Write-Fail "power function missing (should still exist)" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
|
||||
# Check that absolute function still exists (good commit after bad ones)
|
||||
if ($calcContent -match "def absolute") {
|
||||
Write-Host "[PASS] absolute function preserved" -ForegroundColor Green
|
||||
Write-Pass "absolute function preserved" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[FAIL] absolute function missing (should still exist)" -ForegroundColor Red
|
||||
Write-Fail "absolute function missing (should still exist)" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
} else {
|
||||
Write-Host "[FAIL] calculator.py not found" -ForegroundColor Red
|
||||
Write-Fail "calculator.py not found" -ForegroundColor Red
|
||||
$allChecksPassed = $false
|
||||
}
|
||||
}
|
||||
|
||||
Set-Location $originalDir
|
||||
|
||||
# Final summary
|
||||
Write-Host ""
|
||||
if ($allChecksPassed) {
|
||||
|
||||
@@ -95,13 +95,14 @@ Suddenly, your teammate reports a **critical security bug** in production! You n
|
||||
|
||||
2. **Check your current status:**
|
||||
```pwsh
|
||||
git status
|
||||
git status # See which files are changed
|
||||
git diff # See all the changes in a diffview
|
||||
```
|
||||
You should see modified `login.py` (uncommitted changes)
|
||||
|
||||
3. **Stash your work with a message:**
|
||||
```pwsh
|
||||
git stash save "WIP: login feature"
|
||||
git stash push -m "WIP: login feature"
|
||||
```
|
||||
|
||||
4. **Verify working directory is clean:**
|
||||
@@ -116,15 +117,12 @@ Suddenly, your teammate reports a **critical security bug** in production! You n
|
||||
```
|
||||
|
||||
6. **Open app.py and find the bug:**
|
||||
```pwsh
|
||||
cat app.py
|
||||
```
|
||||
Look for the comment "# BUG: This allows unauthenticated access!"
|
||||
|
||||
7. **Fix the bug** by editing app.py:
|
||||
- Remove the buggy comment line
|
||||
- You can leave the implementation as-is or improve it
|
||||
- The important thing is removing the comment that says "allows unauthenticated access"
|
||||
- The important thing is removing the comment that says "BUG: This allows unauthenticated access"
|
||||
|
||||
8. **Commit the fix:**
|
||||
```pwsh
|
||||
@@ -143,10 +141,8 @@ Suddenly, your teammate reports a **critical security bug** in production! You n
|
||||
```
|
||||
This applies the stash and removes it from the stash stack
|
||||
|
||||
11. **Complete the TODOs in login.py:**
|
||||
11. **Remove all the TODOs in login.py:**
|
||||
- Open login.py in your editor
|
||||
- Complete the login method (verify password and return session)
|
||||
- Add a logout method
|
||||
- Remove all TODO comments
|
||||
|
||||
12. **Commit your completed feature:**
|
||||
@@ -166,7 +162,7 @@ Suddenly, your teammate reports a **critical security bug** in production! You n
|
||||
|
||||
```pwsh
|
||||
# Stash current changes with a message
|
||||
git stash save "description"
|
||||
git stash push -m "description"
|
||||
|
||||
# Stash without a message (not recommended)
|
||||
git stash
|
||||
@@ -194,10 +190,7 @@ git stash pop
|
||||
git stash apply
|
||||
|
||||
# Apply a specific stash
|
||||
git stash apply stash@{1}
|
||||
|
||||
# Apply a specific stash by number
|
||||
git stash apply 1
|
||||
git stash apply "stash@{1}"
|
||||
```
|
||||
|
||||
### Managing Stashes
|
||||
@@ -207,7 +200,7 @@ git stash apply 1
|
||||
git stash drop
|
||||
|
||||
# Drop a specific stash
|
||||
git stash drop stash@{1}
|
||||
git stash drop "stash@{1}"
|
||||
|
||||
# Clear all stashes
|
||||
git stash clear
|
||||
@@ -273,7 +266,7 @@ The verification will check that:
|
||||
**Solution:**
|
||||
```pwsh
|
||||
# Stash your changes first
|
||||
git stash save "work in progress"
|
||||
git stash push -m "work in progress"
|
||||
|
||||
# Now you can switch
|
||||
git switch other-branch
|
||||
@@ -293,10 +286,10 @@ git stash pop
|
||||
git stash list
|
||||
|
||||
# Show summary of what changed
|
||||
git stash show stash@{0}
|
||||
git stash show "stash@{0}"
|
||||
|
||||
# Show full diff
|
||||
git stash show -p stash@{0}
|
||||
git stash show -p "stash@{0}"
|
||||
```
|
||||
|
||||
### "Stash conflicts when I apply"
|
||||
@@ -321,7 +314,7 @@ git stash show -p stash@{0}
|
||||
|
||||
## Tips for Success
|
||||
|
||||
💡 **Always add a message** - `git stash save "your message"` helps you remember what you stashed
|
||||
💡 **Always add a message** - `git stash push -m "your message"` helps you remember what you stashed
|
||||
💡 **Use pop, not apply** - Pop removes the stash automatically, keeping your stash list clean
|
||||
💡 **Stash before pulling** - Avoid merge conflicts when pulling updates
|
||||
💡 **Preview before applying** - Use `git stash show -p` to see what's in a stash
|
||||
@@ -333,7 +326,7 @@ git stash show -p stash@{0}
|
||||
### Quick Branch Switch
|
||||
```pwsh
|
||||
# You're working on feature-A
|
||||
git stash save "feature A progress"
|
||||
git stash push -m "feature A progress"
|
||||
git switch hotfix-branch
|
||||
# Fix the issue, commit
|
||||
git switch feature-A
|
||||
@@ -343,7 +336,7 @@ git stash pop
|
||||
### Pull with Local Changes
|
||||
```pwsh
|
||||
# You have uncommitted changes
|
||||
git stash save "local changes"
|
||||
git stash push -m "local changes"
|
||||
git pull
|
||||
git stash pop
|
||||
# Resolve conflicts if any
|
||||
@@ -352,7 +345,7 @@ git stash pop
|
||||
### Test Clean State
|
||||
```pwsh
|
||||
# Stash changes to test on clean code
|
||||
git stash save "testing clean state"
|
||||
git stash push -m "testing clean state"
|
||||
# Run tests
|
||||
git stash pop # Restore your changes
|
||||
```
|
||||
|
||||
@@ -9,48 +9,28 @@
|
||||
and completed the feature on the feature branch.
|
||||
#>
|
||||
|
||||
Set-Location "challenge" -ErrorAction SilentlyContinue
|
||||
$root = $PSScriptRoot
|
||||
|
||||
# Check if challenge directory exists
|
||||
if (-not (Test-Path "../verify.ps1")) {
|
||||
Write-Host "Error: Please run this script from the module directory" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not (Test-Path ".")) {
|
||||
Write-Host "Error: Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
if (-not (Test-Path "$root/challenge")) {
|
||||
Write-Error "Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Verifying your solution..." -ForegroundColor Cyan
|
||||
|
||||
# Check if git repository exists
|
||||
if (-not (Test-Path ".git")) {
|
||||
Write-Host "[FAIL] No git repository found." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
if (-not (Test-Path "$root/challenge/.git")) {
|
||||
Write-Fail "No git repository found." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Detect the main branch name
|
||||
$allBranches = git branch --list 2>$null | ForEach-Object { $_.Trim('* ') }
|
||||
if ($allBranches -contains "main") {
|
||||
$mainBranch = "main"
|
||||
} elseif ($allBranches -contains "master") {
|
||||
$mainBranch = "master"
|
||||
} else {
|
||||
$mainBranch = git config --get init.defaultBranch
|
||||
if (-not $mainBranch) {
|
||||
$mainBranch = $allBranches | Select-Object -First 1
|
||||
if (-not $mainBranch) { $mainBranch = "main" }
|
||||
}
|
||||
}
|
||||
$mainBranch = Get-MainBranch
|
||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
||||
|
||||
# Check current branch
|
||||
$currentBranch = git branch --show-current 2>$null
|
||||
if ($currentBranch -ne "feature-login") {
|
||||
Write-Host "[FAIL] You should be on the 'feature-login' branch." -ForegroundColor Red
|
||||
Write-Fail "You should be on the 'feature-login' branch." -ForegroundColor Red
|
||||
Write-Host "Current branch: $currentBranch" -ForegroundColor Yellow
|
||||
Write-Host "Hint: Switch back to feature-login after completing the challenge" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
@@ -60,8 +40,8 @@ if ($currentBranch -ne "feature-login") {
|
||||
# Check for uncommitted changes on feature-login
|
||||
$status = git status --porcelain 2>$null
|
||||
if ($status) {
|
||||
Write-Host "[FAIL] You have uncommitted changes on feature-login." -ForegroundColor Red
|
||||
Write-Host "Hint: After restoring from stash, you should complete and commit the feature" -ForegroundColor Yellow
|
||||
Write-Fail "You have uncommitted changes on feature-login." -ForegroundColor Red
|
||||
Write-Hint "After restoring from stash, you should complete and commit the feature" -ForegroundColor Yellow
|
||||
git status --short
|
||||
Set-Location ..
|
||||
exit 1
|
||||
@@ -69,7 +49,7 @@ if ($status) {
|
||||
|
||||
# Verify main branch has the security fix
|
||||
Write-Host "`nChecking $mainBranch branch for bug fix..." -ForegroundColor Cyan
|
||||
git checkout $mainBranch 2>$null | Out-Null
|
||||
git switch $mainBranch 2>$null | Out-Null
|
||||
|
||||
# Check for bug fix commit
|
||||
$mainCommits = git log --pretty=format:"%s" $mainBranch 2>$null
|
||||
@@ -82,17 +62,17 @@ foreach ($commit in $mainCommits) {
|
||||
}
|
||||
|
||||
if (-not $hasSecurityFix) {
|
||||
Write-Host "[FAIL] No security bug fix commit found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Fail "No security bug fix commit found on $mainBranch branch." -ForegroundColor Red
|
||||
Write-Host "Hint: After stashing, switch to $mainBranch and commit a bug fix" -ForegroundColor Yellow
|
||||
git checkout feature-login 2>$null | Out-Null
|
||||
git switch feature-login 2>$null | Out-Null
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that app.py has been fixed
|
||||
if (-not (Test-Path "app.py")) {
|
||||
Write-Host "[FAIL] app.py not found on $mainBranch branch." -ForegroundColor Red
|
||||
git checkout feature-login 2>$null | Out-Null
|
||||
Write-Fail "app.py not found on $mainBranch branch." -ForegroundColor Red
|
||||
git switch feature-login 2>$null | Out-Null
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
@@ -102,9 +82,9 @@ $appContent = Get-Content "app.py" -Raw
|
||||
# The bug was "return true" in authenticate - it should be fixed now
|
||||
# We'll check that the buggy comment is gone or the implementation is improved
|
||||
if ($appContent -match "allows unauthenticated access") {
|
||||
Write-Host "[FAIL] The security bug comment still exists in app.py." -ForegroundColor Red
|
||||
Write-Fail "The security bug comment still exists in app.py." -ForegroundColor Red
|
||||
Write-Host "Hint: Remove the bug from app.py and commit the fix" -ForegroundColor Yellow
|
||||
git checkout feature-login 2>$null | Out-Null
|
||||
git switch feature-login 2>$null | Out-Null
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
@@ -113,14 +93,14 @@ Write-Host "[PASS] Security bug fixed on main!" -ForegroundColor Green
|
||||
|
||||
# Switch back to feature-login
|
||||
Write-Host "`nChecking feature-login branch..." -ForegroundColor Cyan
|
||||
git checkout feature-login 2>$null | Out-Null
|
||||
git switch feature-login 2>$null | Out-Null
|
||||
|
||||
# Check for completed feature commit
|
||||
$featureCommits = git log --pretty=format:"%s" feature-login 2>$null
|
||||
$commitCount = ($featureCommits -split "`n").Count
|
||||
|
||||
if ($commitCount -lt 3) {
|
||||
Write-Host "[FAIL] Expected at least 3 commits on feature-login." -ForegroundColor Red
|
||||
Write-Fail "Expected at least 3 commits on feature-login." -ForegroundColor Red
|
||||
Write-Host "Hint: You should have the initial commits plus your completed feature commit" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
exit 1
|
||||
@@ -128,7 +108,7 @@ if ($commitCount -lt 3) {
|
||||
|
||||
# Check that login.py exists
|
||||
if (-not (Test-Path "login.py")) {
|
||||
Write-Host "[FAIL] login.py not found on feature-login branch." -ForegroundColor Red
|
||||
Write-Fail "login.py not found on feature-login branch." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
@@ -137,22 +117,22 @@ $loginContent = Get-Content "login.py" -Raw
|
||||
|
||||
# Check that login method exists and is implemented
|
||||
if ($loginContent -notmatch "def login") {
|
||||
Write-Host "[FAIL] login.py should have a login method." -ForegroundColor Red
|
||||
Write-Fail "login.py should have a login method." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that TODOs are completed (no TODO comments should remain)
|
||||
if ($loginContent -match "TODO") {
|
||||
Write-Host "[FAIL] login.py still contains TODO comments." -ForegroundColor Red
|
||||
Write-Host "Hint: Complete all the TODOs in login.py before committing" -ForegroundColor Yellow
|
||||
Write-Fail "login.py still contains TODO comments." -ForegroundColor Red
|
||||
Write-Hint "Complete all the TODOs in login.py before committing" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that password verification is implemented
|
||||
if ($loginContent -notmatch "password") {
|
||||
Write-Host "[FAIL] login method should verify the password." -ForegroundColor Red
|
||||
Write-Fail "login method should verify the password." -ForegroundColor Red
|
||||
Set-Location ..
|
||||
exit 1
|
||||
}
|
||||
@@ -160,7 +140,7 @@ if ($loginContent -notmatch "password") {
|
||||
# Check that the feature has been committed (not just in working directory)
|
||||
$lastCommit = git log -1 --pretty=format:"%s" 2>$null
|
||||
if ($lastCommit -notmatch "login|feature|complete|implement") {
|
||||
Write-Host "[FAIL] Your completed feature should be committed." -ForegroundColor Red
|
||||
Write-Fail "Your completed feature should be committed." -ForegroundColor Red
|
||||
Write-Host "Last commit: $lastCommit" -ForegroundColor Yellow
|
||||
Write-Host "Hint: After popping the stash and completing the TODOs, commit the feature" -ForegroundColor Yellow
|
||||
Set-Location ..
|
||||
|
||||
@@ -131,15 +131,6 @@ git add numbers.txt
|
||||
git commit -m "feat: add shuffled numbers for challenge"
|
||||
git push
|
||||
```
|
||||
|
||||
### Step 4: Verify Student Access
|
||||
|
||||
Students added to the project automatically have access. Verify:
|
||||
|
||||
1. Go to **Project Settings** → **Repositories** → **number-challenge**
|
||||
2. Click **Security** tab
|
||||
3. Verify project team has **Contribute** permission
|
||||
|
||||
---
|
||||
|
||||
## During the Workshop
|
||||
@@ -153,12 +144,12 @@ Students added to the project automatically have access. Verify:
|
||||
### The Exercise Flow
|
||||
|
||||
1. **Students pull** the latest changes
|
||||
2. **One person** moves a number to its correct position
|
||||
2. **One person** creates a branch, moves a number to its correct position
|
||||
3. **They commit and push**
|
||||
4. **Others pull** and see the change
|
||||
5. **Repeat** until sorted
|
||||
|
||||
### Creating Conflicts (The Learning Moment)
|
||||
### Same branch conflicts
|
||||
|
||||
Conflicts happen naturally when multiple people edit at once. You can encourage this:
|
||||
|
||||
@@ -166,13 +157,6 @@ Conflicts happen naturally when multiple people edit at once. You can encourage
|
||||
- Watch them experience the push rejection
|
||||
- Guide them through pulling and resolving the conflict
|
||||
|
||||
### Monitoring Progress
|
||||
|
||||
Check progress in Azure DevOps:
|
||||
|
||||
- **Repos → Commits**: See who's contributing
|
||||
- **Repos → Files → numbers.txt**: See current state
|
||||
|
||||
### Common Issues
|
||||
|
||||
**"I can't push!"**
|
||||
|
||||
@@ -20,7 +20,7 @@ SSH (Secure Shell) keys provide a secure way to authenticate with Azure DevOps w
|
||||
Before starting, ensure you have:
|
||||
|
||||
- **Git 2.23 or higher** installed
|
||||
```powershell
|
||||
```pwsh
|
||||
git --version
|
||||
```
|
||||
|
||||
@@ -28,7 +28,7 @@ Before starting, ensure you have:
|
||||
- If you don't ask your organisation for an invitation
|
||||
|
||||
- **PowerShell 7+ or Bash terminal** for running commands
|
||||
```powershell
|
||||
```pwsh
|
||||
pwsh --version
|
||||
```
|
||||
|
||||
@@ -42,7 +42,7 @@ SSH authentication uses a key pair: a private key (stays on your computer) and a
|
||||
|
||||
Open your terminal and run:
|
||||
|
||||
```powershell
|
||||
```pwsh
|
||||
ssh-keygen -t rsa
|
||||
```
|
||||
|
||||
@@ -73,7 +73,7 @@ Enter same passphrase again:
|
||||
Check that your keys were created:
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
```pwsh
|
||||
dir $HOME\.ssh\
|
||||
```
|
||||
|
||||
@@ -108,27 +108,17 @@ Now you'll upload your public key to Azure DevOps.
|
||||
|
||||
Open your terminal and display your public key:
|
||||
|
||||
**Linux/Mac:**
|
||||
```bash
|
||||
cat ~/.ssh/id_rsa.pub
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
```pwsh
|
||||
type $HOME\.ssh\id_rsa.pub
|
||||
```
|
||||
|
||||
**Windows Command Prompt:**
|
||||
```cmd
|
||||
type %USERPROFILE%\.ssh\id_rsa.pub
|
||||
```
|
||||
|
||||
The output will look like this:
|
||||
```
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2YbXnrSK5TTflZSwUv9KUedvI4p3JJ4dHgwp/SeJGqMNWnOMDbzQQzYT7E39w9Q8ItrdWsK4vRLGY2B1rQ+BpS6nn4KhTanMXLTaUFDlg6I1Yn5S3cTTe8dMAoa14j3CZfoSoRRgK8E+ktNb0o0nBMuZJlLkgEtPIz28fwU1vcHoSK7jFp5KL0pjf37RYZeHkbpI7hdCG2qHtdrC35gzdirYPJOekErF5VFRrLZaIRSSsX0V4XzwY2k1hxM037o/h6qcTLWfi5ugbyrdscL8BmhdGNH4Giwqd1k3MwSyiswRuAuclYv27oKnFVBRT+n649px4g3Vqa8dh014wM2HDjMGENIkHx0hcV9BWdfBfTSCJengmosGW+wQfmaNUo4WpAbwZD73ALNsoLg5Yl1tB6ZZ5mHwLRY3LG2BbQZMZRCELUyvbh8ZsRksNN/2zcS44RIQdObV8/4hcLse30+NQ7GRaMnJeAMRz4Rpzbb02y3w0wNQFp/evj1nN4WTz6l8= your@email.com
|
||||
```
|
||||
|
||||
**Copy the entire output** (from `ssh-rsa` to your email address).
|
||||
**Copy the entire output** (from `ssh-rsa` to and including your email address).
|
||||
|
||||
|
||||
### Paste and Name Your Key
|
||||
@@ -152,12 +142,12 @@ Now that SSH is configured, you can use it for all Git operations.
|
||||
|
||||
To clone a repository using SSH:
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
git clone git@ssh.dev.azure.com:v3/{organization}/{project}/{repository}
|
||||
```
|
||||
|
||||
**Example** (replace placeholders with your actual values):
|
||||
```bash
|
||||
```pwsh
|
||||
git clone git@ssh.dev.azure.com:v3/myorg/git-workshop/great-print-project
|
||||
```
|
||||
|
||||
@@ -175,7 +165,7 @@ git clone git@ssh.dev.azure.com:v3/myorg/git-workshop/great-print-project
|
||||
|
||||
All standard Git commands now work seamlessly with SSH:
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# Pull latest changes
|
||||
git pull
|
||||
|
||||
@@ -195,7 +185,6 @@ git push -u origin feature-branch
|
||||
|
||||
## Additional Resources
|
||||
- **Azure DevOps SSH Documentation**: [https://docs.microsoft.com/en-us/azure/devops/repos/git/use-ssh-keys-to-authenticate](https://docs.microsoft.com/en-us/azure/devops/repos/git/use-ssh-keys-to-authenticate)
|
||||
- **SSH Key Best Practices**: [https://security.stackexchange.com/questions/tagged/ssh-keys](https://security.stackexchange.com/questions/tagged/ssh-keys)
|
||||
- **Git with SSH**: [https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key](https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key)
|
||||
|
||||
---
|
||||
@@ -204,17 +193,14 @@ git push -u origin feature-branch
|
||||
|
||||
### Common Commands
|
||||
|
||||
```bash
|
||||
```pwsh
|
||||
# Generate RSA key
|
||||
ssh-keygen -t
|
||||
|
||||
# Display public key (Linux/Mac)
|
||||
cat ~/.ssh/id_rsa.pub
|
||||
|
||||
# Display public key (Windows)
|
||||
# Display public key
|
||||
type $HOME\.ssh\id_rsa.pub
|
||||
|
||||
# Clone with SSH
|
||||
# Clone with SSH. You can find this url on Azure DevOps
|
||||
git clone git@ssh.dev.azure.com:v3/{org}/{project}/{repo}
|
||||
|
||||
# Check remote URL
|
||||
|
||||
@@ -128,7 +128,8 @@ git pull
|
||||
|
||||
# Now we resolve the merge. We're merging the main branch INTO the feature-2 branch.
|
||||
git merge main
|
||||
# Resolve the merge conflict in numbers.txt
|
||||
# Resolve the merge conflict in numbers.txt by opening in VSCode and choosing the changes you want.
|
||||
# How you solve it is up to you.
|
||||
# Once resolved
|
||||
git add numbers.txt
|
||||
git commit
|
||||
@@ -142,30 +143,29 @@ git pull
|
||||
|
||||
| Command | What It Does |
|
||||
|---------|--------------|
|
||||
| `git switch -c <name>` | Create and switch to new branch |
|
||||
| `git push -u origin <branch>` | Push branch to Azure DevOps |
|
||||
| `git switch main` | Switch to main branch |
|
||||
| `git switch -c <branch-name>` | Create and switch to new branch |
|
||||
| `git switch <branch-name>` | Switch to branch |
|
||||
| `git push` | Push branch to Azure DevOps |
|
||||
| `git pull` | Get latest changes from remote |
|
||||
|
||||
---
|
||||
|
||||
## Common Issues
|
||||
## Cheatsheet
|
||||
|
||||
### "My PR has conflicts"
|
||||
1. Update your branch with latest main:
|
||||
```powershell
|
||||
git switch main
|
||||
git pull
|
||||
git switch <branch-name>
|
||||
git merge main
|
||||
```
|
||||
2. Resolve conflicts in VS Code
|
||||
3. Commit and push again
|
||||
### Solving merge conflicts
|
||||
```pwsh
|
||||
git switch main
|
||||
git pull
|
||||
git switch <branch-name>
|
||||
git merge main
|
||||
# ... Solve the conflicts
|
||||
git push
|
||||
```
|
||||
|
||||
### "I need to make more changes to my PR"
|
||||
|
||||
Just commit and push to the same branch - the PR updates automatically:
|
||||
```powershell
|
||||
```pwsh
|
||||
git add .
|
||||
git commit -m "fix: address review feedback"
|
||||
git push
|
||||
|
||||
@@ -56,7 +56,7 @@ This creates a new branch and switches to it.
|
||||
```powershell
|
||||
git add .
|
||||
git commit -m "fix: move 7 to correct position"
|
||||
git push feature-2
|
||||
git push
|
||||
```
|
||||
|
||||
Your branch is now on Azure DevOps.
|
||||
|
||||
279
02-GET-STARTED.md
Normal file
279
02-GET-STARTED.md
Normal file
@@ -0,0 +1,279 @@
|
||||
# Git Workshop
|
||||
|
||||
A hands-on Git workshop with 8 progressive modules covering essential Git skills from basic commits to real-world collaboration. Each module presents a practical scenario you must solve using Git commands, with automated verification to confirm your solution.
|
||||
|
||||
Perfect for developers who want to master Git fundamentals and professional workflows including branching, conflict resolution, and team collaboration.
|
||||
|
||||
## Workshop Structure
|
||||
|
||||
### Essentials - Core Git Skills (8 modules)
|
||||
|
||||
Master fundamental Git concepts and collaborative workflows:
|
||||
|
||||
- **Module 01: Git Basics** - Initialize repositories, stage changes, make commits
|
||||
- **Module 02: Viewing History** - Use git log and git diff to explore project history
|
||||
- **Module 03: Branching and Merging** - Create branches and merge them
|
||||
- **Module 04: Merge Conflicts** - Resolve conflicts when branches have competing changes
|
||||
- **Module 05: Cherry-Pick** - Apply specific commits from one branch to another
|
||||
- **Module 06: Git Revert** - Safe undoing - preserve history while reversing changes
|
||||
- **Module 07: Stash** - Temporarily save work without committing
|
||||
- **Module 08: Multiplayer Git** - **The Great Print Project** - Real cloud-based collaboration with teammates
|
||||
|
||||
## Requirements
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Install these tools before starting:
|
||||
|
||||
**PowerShell 7+**
|
||||
|
||||
Download here <https://learn.microsoft.com/en-us/powershell/scripting/install/install-powershell-on-windows?view=powershell-7.5#msi>.
|
||||
|
||||
```pwsh
|
||||
winget install Microsoft.PowerShell
|
||||
```
|
||||
|
||||
|
||||
**Git 2.23+**
|
||||
|
||||
Download here <https://git-scm.com/install/windows> or install using the command down below
|
||||
|
||||
```pwsh
|
||||
winget install Git.Git
|
||||
```
|
||||
|
||||
**Visual Studio Code**
|
||||
|
||||
Download here <https://code.visualstudio.com/download> or install using the command down below
|
||||
|
||||
```pwsh
|
||||
winget install Microsoft.VisualStudioCode
|
||||
```
|
||||
|
||||
You can also run the one-shot install script if the project is cloned locally. It will check if you have the prerequisites install and clone down the project if not already cloned. Then it will configure git to have sane default.
|
||||
```pwsh
|
||||
./install.ps1
|
||||
```
|
||||
or if you don't have the project locally run.
|
||||
|
||||
|
||||
REMEMBER read through the script before running it. As a general practice, you shouldn't get comfortable doing this kind of execution, and so it's important to review executing remote scripts.
|
||||
```pwsh
|
||||
Invoke-RestMethod -Uri https://git.frod.dk/floppydiscen/git-workshop/raw/branch/main/install.ps1 | Invoke-Expression
|
||||
```
|
||||
|
||||
## How to Use This Workshop
|
||||
|
||||
|
||||
### For Local Modules (01-07)
|
||||
|
||||
1. Navigate to a module directory (e.g., `01-essentials/01-basics`)
|
||||
2. Read the `README.md` to understand the challenge
|
||||
3. Run `./setup.ps1` to create the challenge environment
|
||||
4. Complete the challenge using git commands
|
||||
5. Run `./verify.ps1` to check if you've solved it correctly
|
||||
6. If you mess up the challenge just run `.\reset.ps1`
|
||||
6. Move to the next module
|
||||
|
||||
**Quick Reference**: See [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) for a comprehensive list of all Git commands covered in this workshop. Don't worry about memorizing everything - use this as a reference when you need to look up command syntax!
|
||||
|
||||
### For Module 08: Multiplayer Git
|
||||
|
||||
**This module is different!** It uses Azure DevOps for authentic cloud-based collaboration:
|
||||
|
||||
1. Navigate to `01-essentials/08-multiplayer`
|
||||
2. Read the `README.md` for complete instructions
|
||||
3. **No setup script** - you'll clone from Azure DevOps (URL provided by facilitator)
|
||||
4. Work with a partner on shared branches
|
||||
5. Experience real merge conflicts and pull requests
|
||||
6. Use SSH keys for secure authentication (best practice)
|
||||
7. **No verify script** - success is visual (your code appears in the final output)
|
||||
|
||||
**Facilitators**: See `01-essentials/08-multiplayer/FACILITATOR-SETUP.md` for server setup and workshop guidance.
|
||||
|
||||
## Running PowerShell Scripts
|
||||
|
||||
Most modules include setup, verification, and reset scripts.
|
||||
|
||||
If you encounter an "execution policy" error when running scripts, open PowerShell as Administrator and run:
|
||||
|
||||
```pwsh
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
```
|
||||
|
||||
And to revert back to the default policy
|
||||
|
||||
```pwsh
|
||||
Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope CurrentUser
|
||||
```
|
||||
|
||||
Then run scripts using:
|
||||
```pwsh
|
||||
.\setup.ps1
|
||||
.\verify.ps1
|
||||
.\reset.ps1
|
||||
```
|
||||
|
||||
## Git Configuration
|
||||
|
||||
Before starting the workshop, configure Git with your identity and recommended settings:
|
||||
|
||||
### Required: Set Your Identity
|
||||
|
||||
```pwsh
|
||||
git config --global user.name "Your Name"
|
||||
git config --global user.email "your.email@example.com"
|
||||
```
|
||||
|
||||
### Recommended: VS Code as Default Editor
|
||||
|
||||
Set VS Code as your default editor for commit messages, diffs, and merges:
|
||||
|
||||
```pwsh
|
||||
# Set VS Code as the default editor
|
||||
git config --global core.editor "code --wait"
|
||||
|
||||
# Set VS Code as the diff tool
|
||||
git config --global diff.tool vscode
|
||||
git config --global difftool.vscode.cmd "code --wait --diff $LOCAL $REMOTE"
|
||||
|
||||
# Set VS Code as the merge tool
|
||||
git config --global merge.tool vscode
|
||||
git config --global mergetool.vscode.cmd "code --wait --merge $MERGED"
|
||||
```
|
||||
|
||||
### Recommended: Set Default Branch Name
|
||||
|
||||
Set "main" as the default branch name for new repositories:
|
||||
|
||||
```pwsh
|
||||
git config --global init.defaultBranch main
|
||||
```
|
||||
|
||||
### Verify Your Configuration
|
||||
|
||||
Check that your settings are correct:
|
||||
|
||||
```pwsh
|
||||
git config --global --list
|
||||
```
|
||||
|
||||
**Verify Installation:**
|
||||
|
||||
Check that you have the required software installed:
|
||||
|
||||
```pwsh
|
||||
# Git 2.23+
|
||||
git --version
|
||||
|
||||
# PowerShell 7+
|
||||
pwsh --version
|
||||
```
|
||||
|
||||
### Basic Command Line Knowledge
|
||||
|
||||
You should know how to:
|
||||
- Navigate directories (`cd`, `ls` or `dir`)
|
||||
- See your current location (`pwd`)
|
||||
- Read text files (`cat` or `type`)
|
||||
|
||||
Don't worry if you're not an expert - we'll guide you through each step!
|
||||
|
||||
## Common Git Terms
|
||||
|
||||
New to Git? Here are the key terms you'll encounter:
|
||||
|
||||
- **Repository (or "repo")**: A project folder tracked by Git, containing your files and their complete history
|
||||
- **Commit**: A snapshot of your project at a specific point in time (like a save point in a video game)
|
||||
- **Staging Area**: A preparation area where you select which changes to include in your next commit
|
||||
- **Working Directory**: The actual files you see and edit on your computer
|
||||
- **Branch**: An independent line of development (like a parallel universe for your code)
|
||||
- **HEAD**: A pointer showing which commit you're currently working from
|
||||
- **main/master**: The primary branch in a repository (main is the modern convention)
|
||||
- **Merge**: Combining changes from different branches
|
||||
- **Remote**: A version of your repository hosted elsewhere (like GitHub, GitLab, or Gitea)
|
||||
- **Pull Request (PR)**: A request to merge your changes into another branch (used for code review)
|
||||
- **Conflict**: When Git can't automatically merge changes because both versions modified the same lines
|
||||
|
||||
Don't worry if these don't make sense yet - you'll learn them hands-on as you progress!
|
||||
|
||||
## Getting Started
|
||||
|
||||
Once installed, start with Essentials Module 01:
|
||||
|
||||
```pwsh
|
||||
cd 01-essentials\01-basics
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
Follow the instructions in each module's README.md file.
|
||||
|
||||
## What Makes This Workshop Different
|
||||
|
||||
- **Hands-On Practice**: Each module creates a real Git scenario you must solve
|
||||
- **Automated Verification**: Scripts check your solution instantly (modules 01-07)
|
||||
- **Progressive Difficulty**: Builds from basics to advanced Git techniques
|
||||
- **Reset Anytime**: Each local module includes a reset script for a fresh start
|
||||
- **Self-Paced**: Learn at your own speed with detailed README guides
|
||||
- **Real Collaboration**: Module 08 uses an actual Git server for authentic teamwork
|
||||
- **Comprehensive Coverage**: From `git init` to advanced rebasing and bisecting
|
||||
|
||||
## Learning Path
|
||||
|
||||
The modules are designed to build on each other:
|
||||
|
||||
### Recommended Progression
|
||||
|
||||
**Phase 1: Core Fundamentals (Essentials 01-02)**
|
||||
- Git Basics, History
|
||||
- **Goal**: Understand commits and history
|
||||
|
||||
**Phase 2: Collaboration Basics (Essentials 03-04)**
|
||||
- Branching, Merging, and Conflict Resolution
|
||||
- **Goal**: Work with multiple branches and resolve conflicts
|
||||
|
||||
**Phase 3: Workflow Tools (Essentials 05-07)**
|
||||
- Cherry-Pick, Revert, and Stash
|
||||
- **Goal**: Manage your work effectively
|
||||
|
||||
**Phase 4: Real Collaboration (Essentials 08)**
|
||||
- **Multiplayer Git - The Great Reordering of Numbers Project**
|
||||
- **Goal**: Apply all skills with real teammates on a cloud server
|
||||
- **Note**: This is a capstone module - bring everything together!
|
||||
|
||||
### Alternative Paths
|
||||
|
||||
**Fast Track (half-day workshop):**
|
||||
- Essentials 01-04 + Essentials 08 (Multiplayer)
|
||||
|
||||
**Team Workshop:**
|
||||
- Essentials 01-04 then jump to 08 (Multiplayer) for collaborative practice
|
||||
|
||||
## Tips for Success
|
||||
|
||||
- **Don't skip modules** - each builds on previous concepts
|
||||
- **Read the README.md thoroughly** before starting each challenge
|
||||
- **Keep [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) open** as a quick reference
|
||||
- **Experiment freely** - you can always run `./reset.ps1` to start over
|
||||
- **Use `git status` and `git log --oneline --graph --all`** frequently to visualize repository state
|
||||
- **If stuck**, check the Key Concepts section in the module's README
|
||||
- **For Module 08**, work with a partner - collaboration is the point!
|
||||
|
||||
## Skills You'll Master
|
||||
|
||||
By completing this workshop, you'll be able to:
|
||||
|
||||
- Create and manage Git repositories with confidence
|
||||
- Navigate project history and understand what changed when
|
||||
- Use branches effectively for parallel development
|
||||
- Merge branches and resolve conflicts like a pro
|
||||
- Apply specific commits with cherry-pick
|
||||
- Safely undo changes with revert
|
||||
- Use stash to manage work-in-progress without commits
|
||||
- **Collaborate with teammates on shared repositories**
|
||||
- **Resolve real merge conflicts in a team environment**
|
||||
- **Create and review pull requests**
|
||||
- **Use Git on a real cloud server (Azure DevOps)**
|
||||
- **Use SSH keys for secure Git authentication**
|
||||
|
||||
These are professional-level Git skills used daily by developers at tech companies.
|
||||
@@ -110,7 +110,7 @@ Nothing creates unnecessary conflicts like two people reformatting the same file
|
||||
|
||||
**Do this:**
|
||||
- Agree on code formatting standards as a team
|
||||
- Use automatic formatters (Prettier, Black, etc.)
|
||||
- Use automatic formatters (Prettier, Black, clang-format, etc.)
|
||||
- Configure your editor to format on save
|
||||
- Run formatters before committing
|
||||
|
||||
@@ -122,16 +122,22 @@ Renaming a widely-used function or moving files around will conflict with almost
|
||||
|
||||
**Do this:**
|
||||
- Announce refactors to the team before starting
|
||||
- This is important to coordinate merges of features that are being worked before the great refactoring.
|
||||
A large renaming of namespaces or moving of files becomes hard to deal with when you rely on the old file-structure before the great merge.
|
||||
Instead you should *freeze* any further features until the great refactoring has been completed and then resume feature-building
|
||||
- Do them quickly and push immediately
|
||||
- Consider doing them when others aren't actively working
|
||||
- Keep refactoring commits separate from feature work
|
||||
This keeps your commits clean and doesn't *dirty* the actual work with actual feature work (which also makes it easy to cherry-pick while minimizing conflicts).
|
||||
|
||||
## The Golden Rules
|
||||
|
||||
1. **Sync frequently** - Pull before you start, pull before you push
|
||||
2. **Commit small** - Many small commits beat one large commit
|
||||
A way to think of it is to keep commit *atomic*. In other words try to make them self-contained units that are easy to `cherry-pick` at a later time.
|
||||
3. **Talk to your team** - A quick message prevents hours of conflict resolution
|
||||
4. **Stay focused** - One branch = one purpose
|
||||
Communication is key. Even though alot is delegated to the process itself, it's still a good idea to keep communicating with the team regarding larger changes or features being built.
|
||||
4. **Stay focused** - One branch = one purpose (and ususally one person)
|
||||
5. **Push promptly** - Don't sit on finished work
|
||||
|
||||
## When Conflicts Do Happen
|
||||
@@ -140,7 +146,7 @@ Even with best practices, conflicts will occur. When they do:
|
||||
|
||||
1. **Don't panic** - Conflicts are normal, not failures
|
||||
2. **Read carefully** - Understand both sides before choosing
|
||||
3. **Test after resolving** - Make sure the merged code actually works
|
||||
3. **Test after resolving** - Make sure the merged code actually works. A usual, and rather basic test flow is build -> test -> run
|
||||
4. **Ask if unsure** - If you don't understand the other person's code, ask them
|
||||
|
||||
Remember: merge conflicts are a communication problem as much as a technical one. The best tool for reducing conflicts is talking to your team.
|
||||
@@ -287,7 +287,7 @@ git stash
|
||||
Save your uncommitted changes temporarily and revert to a clean working directory.
|
||||
|
||||
```bash
|
||||
git stash save "description"
|
||||
git stash push -m "<description>"
|
||||
```
|
||||
Stash changes with a descriptive message.
|
||||
|
||||
9
06-FAQ.md
Normal file
9
06-FAQ.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Questions
|
||||
|
||||
## Is it possible to recover lost branches or commits?
|
||||
|
||||
Yes it is, however this is dependent on whether or not git has done an internal garbage collection which there usually is a retention period of 30 days.
|
||||
|
||||
**Beware** this is advanced territory and is usually only relevant when you've messed up with a `git reset` or a deletion of a branch
|
||||
|
||||
To read more, you can read the documentation here <https://git-scm.com/docs/git-reflog>
|
||||
337
INSTALLATION.md
337
INSTALLATION.md
@@ -1,337 +0,0 @@
|
||||
# Installation Guide for Windows 11
|
||||
|
||||
This guide will help you install everything needed for the Git Workshop on Windows 11.
|
||||
|
||||
## Quick Start (Automated Installation)
|
||||
|
||||
**Easiest option:** Run our oneshot installation script that installs all prerequisites and clones the repository automatically.
|
||||
|
||||
```powershell
|
||||
irm https://git.frod.dk/floppydiscen/git-workshop/raw/branch/main/install.ps1 | iex
|
||||
```
|
||||
|
||||
This will:
|
||||
- Install PowerShell 7, Git 2.23+, and Visual Studio Code
|
||||
- Clone the git-workshop repository to `~/git-workshop`
|
||||
- Leave you ready to start the workshop immediately
|
||||
|
||||
**Alternative:** If you've already cloned the repository, you can run the local installation script:
|
||||
|
||||
1. Open **PowerShell** or **Windows Terminal**
|
||||
2. Navigate to the git-workshop directory
|
||||
3. Run the installation script:
|
||||
|
||||
```powershell
|
||||
.\install-prerequisites.ps1
|
||||
```
|
||||
|
||||
The script will:
|
||||
- Check if tools are already installed
|
||||
- Install PowerShell 7, Git 2.23+, and Visual Studio Code
|
||||
- Prompt you for optional tools (Python 3.12, Windows Terminal)
|
||||
- Show clear progress and verify each installation
|
||||
- Display Git configuration instructions when complete
|
||||
|
||||
**If you prefer manual installation**, continue with the detailed steps below.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You'll need administrator access to install software on your Windows 11 machine.
|
||||
|
||||
## What You'll Install
|
||||
|
||||
1. **PowerShell 7** - Modern cross-platform PowerShell (replaces the older Windows PowerShell 5.1)
|
||||
2. **Git** - Version control system (2.23 or later)
|
||||
3. **Visual Studio Code** - Modern code editor with excellent Git integration
|
||||
|
||||
## Manual Installation Steps
|
||||
|
||||
### 1. Install PowerShell 7
|
||||
|
||||
PowerShell 7 is the modern, cross-platform version of PowerShell. Windows 11 comes with PowerShell 5.1, but we recommend PowerShell 7 for the best experience.
|
||||
|
||||
**Option A: Using winget (Recommended)**
|
||||
|
||||
Open **Windows Terminal** or **Command Prompt** and run:
|
||||
|
||||
```powershell
|
||||
winget install --id Microsoft.PowerShell --source winget
|
||||
```
|
||||
|
||||
**Option B: Manual Download**
|
||||
|
||||
1. Visit https://github.com/PowerShell/PowerShell/releases/latest
|
||||
2. Download the file ending in `-win-x64.msi` (e.g., `PowerShell-7.4.1-win-x64.msi`)
|
||||
3. Run the installer
|
||||
4. Accept all defaults
|
||||
|
||||
**Verify Installation:**
|
||||
|
||||
Open a new terminal and run:
|
||||
|
||||
```powershell
|
||||
pwsh --version
|
||||
```
|
||||
|
||||
You should see version 7.x.x or higher.
|
||||
|
||||
**Important:** After installing PowerShell 7, use it instead of the older "Windows PowerShell 5.1". Look for "PowerShell 7" in your Start menu or Windows Terminal.
|
||||
|
||||
### 2. Install Git
|
||||
|
||||
Git is the version control system you'll learn in this workshop. You need version 2.23 or later.
|
||||
|
||||
**Option A: Using winget (Recommended)**
|
||||
|
||||
```powershell
|
||||
winget install --id Git.Git -e --source winget
|
||||
```
|
||||
|
||||
**Option B: Manual Download**
|
||||
|
||||
1. Visit https://git-scm.com/downloads
|
||||
2. Click "Windows"
|
||||
3. Download the 64-bit installer
|
||||
4. Run the installer with these recommended settings:
|
||||
- **Default editor**: Choose "Visual Studio Code" (we'll install it next)
|
||||
- **PATH environment**: Select "Git from the command line and also from 3rd-party software"
|
||||
- **Line ending conversions**: Choose "Checkout Windows-style, commit Unix-style line endings"
|
||||
- **Terminal emulator**: Choose "Use Windows' default console window"
|
||||
- All other settings: Accept defaults
|
||||
|
||||
**Verify Installation:**
|
||||
|
||||
Open a **new** PowerShell window and run:
|
||||
|
||||
```powershell
|
||||
git --version
|
||||
```
|
||||
|
||||
You should see version 2.23 or higher (e.g., `git version 2.43.0`).
|
||||
|
||||
### 3. Install Visual Studio Code
|
||||
|
||||
VS Code is a free, powerful code editor with excellent Git integration.
|
||||
|
||||
**Option A: Using winget (Recommended)**
|
||||
|
||||
```powershell
|
||||
winget install --id Microsoft.VisualStudioCode --source winget
|
||||
```
|
||||
|
||||
**Option B: Manual Download**
|
||||
|
||||
1. Visit https://code.visualstudio.com/
|
||||
2. Click "Download for Windows"
|
||||
3. Run the installer
|
||||
4. During installation, check these options:
|
||||
- ✅ Add "Open with Code" action to Windows Explorer file context menu
|
||||
- ✅ Add "Open with Code" action to Windows Explorer directory context menu
|
||||
- ✅ Register Code as an editor for supported file types
|
||||
- ✅ Add to PATH
|
||||
|
||||
**Verify Installation:**
|
||||
|
||||
```powershell
|
||||
code --version
|
||||
```
|
||||
|
||||
You should see version information.
|
||||
|
||||
**Recommended VS Code Extensions:**
|
||||
|
||||
Open VS Code and install these extensions for the best Git experience:
|
||||
|
||||
1. **GitLens** - Supercharge Git capabilities
|
||||
- Press `Ctrl+Shift+X` to open Extensions
|
||||
- Search for "GitLens"
|
||||
- Click Install
|
||||
|
||||
2. **Git Graph** - View Git history visually
|
||||
- Search for "Git Graph"
|
||||
- Click Install
|
||||
|
||||
3. **PowerShell** - Better PowerShell support
|
||||
- Search for "PowerShell"
|
||||
- Install the one from Microsoft
|
||||
|
||||
## Configure Git
|
||||
|
||||
Before making your first commit, tell Git who you are:
|
||||
|
||||
```powershell
|
||||
git config --global user.name "Your Name"
|
||||
git config --global user.email "your.email@example.com"
|
||||
```
|
||||
|
||||
**Verify your configuration:**
|
||||
|
||||
```powershell
|
||||
git config --global user.name
|
||||
git config --global user.email
|
||||
```
|
||||
|
||||
You should see your name and email printed.
|
||||
|
||||
**Optional: Set VS Code as Git's Default Editor**
|
||||
|
||||
If you installed Git before VS Code, configure Git to use VS Code:
|
||||
|
||||
```powershell
|
||||
git config --global core.editor "code --wait"
|
||||
```
|
||||
|
||||
## PowerShell Execution Policy
|
||||
|
||||
When running PowerShell scripts (`.ps1` files) in this workshop, you might encounter an error about execution policies.
|
||||
|
||||
**If you see an error like "script cannot be loaded because running scripts is disabled":**
|
||||
|
||||
Open **PowerShell 7 as Administrator** and run:
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
```
|
||||
|
||||
This allows you to run local scripts while maintaining security for downloaded scripts.
|
||||
|
||||
## Running Scripts in the Workshop
|
||||
|
||||
After installation, you can run workshop scripts using:
|
||||
|
||||
```powershell
|
||||
.\setup.ps1
|
||||
.\verify.ps1
|
||||
.\reset.ps1
|
||||
```
|
||||
|
||||
**Example workflow:**
|
||||
|
||||
```powershell
|
||||
# Navigate to a module
|
||||
cd 01-essentials\01-basics
|
||||
|
||||
# Run the setup script
|
||||
.\setup.ps1
|
||||
|
||||
# Complete the challenge using Git commands
|
||||
# ...
|
||||
|
||||
# Verify your solution
|
||||
.\verify.ps1
|
||||
```
|
||||
|
||||
## Optional: Python (for Module 08 only)
|
||||
|
||||
Module 08 (Multiplayer Git) uses Python for "The Great Print Project". You only need this for that specific module.
|
||||
|
||||
**Install Python 3.12:**
|
||||
|
||||
```powershell
|
||||
winget install --id Python.Python.3.12 --source winget
|
||||
```
|
||||
|
||||
**Verify installation:**
|
||||
|
||||
```powershell
|
||||
python --version
|
||||
```
|
||||
|
||||
You should see Python 3.12.x or higher.
|
||||
|
||||
## Optional: Windows Terminal (Highly Recommended)
|
||||
|
||||
Windows Terminal provides a modern terminal experience with tabs, better colors, and PowerShell 7 integration.
|
||||
|
||||
**Install:**
|
||||
|
||||
```powershell
|
||||
winget install --id Microsoft.WindowsTerminal --source winget
|
||||
```
|
||||
|
||||
Or install from the **Microsoft Store** (search for "Windows Terminal").
|
||||
|
||||
**After installation:**
|
||||
- Press `Win+X` and select "Windows Terminal"
|
||||
- Or search "Terminal" in the Start menu
|
||||
- PowerShell 7 should be the default profile
|
||||
|
||||
## Verify Complete Installation
|
||||
|
||||
Run these commands to verify everything is installed correctly:
|
||||
|
||||
```powershell
|
||||
# PowerShell version (should be 7.x.x)
|
||||
pwsh --version
|
||||
|
||||
# Git version (should be 2.23 or higher)
|
||||
git --version
|
||||
|
||||
# VS Code version
|
||||
code --version
|
||||
|
||||
# Git configuration
|
||||
git config --global user.name
|
||||
git config --global user.email
|
||||
|
||||
# Optional: Python (for Module 08)
|
||||
python --version
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Git command not found
|
||||
|
||||
If `git --version` doesn't work after installation:
|
||||
1. Close and reopen your terminal (Git needs a new terminal to update PATH)
|
||||
2. Restart your computer if the problem persists
|
||||
|
||||
### VS Code command not found
|
||||
|
||||
If `code --version` doesn't work:
|
||||
1. Ensure you checked "Add to PATH" during installation
|
||||
2. Close and reopen your terminal
|
||||
3. If still not working, reinstall VS Code with the PATH option enabled
|
||||
|
||||
### PowerShell execution policy errors
|
||||
|
||||
If you can't run `.ps1` scripts:
|
||||
1. Open PowerShell 7 **as Administrator**
|
||||
2. Run: `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser`
|
||||
3. Close admin PowerShell and try again in a regular PowerShell window
|
||||
|
||||
### winget command not found
|
||||
|
||||
If `winget` doesn't work:
|
||||
1. Update Windows 11 to the latest version (Settings → Windows Update)
|
||||
2. Install "App Installer" from the Microsoft Store
|
||||
3. Restart your computer
|
||||
|
||||
## You're Ready!
|
||||
|
||||
Once all verification commands work, you're ready to start the workshop!
|
||||
|
||||
```powershell
|
||||
# Clone or download the git-workshop repository
|
||||
# Navigate to it
|
||||
cd path\to\git-workshop
|
||||
|
||||
# Start with Module 01
|
||||
cd 01-essentials\01-basics
|
||||
|
||||
# Read the instructions
|
||||
code README.md
|
||||
|
||||
# Run setup and begin!
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Read the main [README.md](README.md) for workshop overview
|
||||
- Check [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) for Git command reference
|
||||
- Start with Module 01: `01-essentials\01-basics`
|
||||
|
||||
Happy learning!
|
||||
502
README.md
502
README.md
@@ -1,502 +0,0 @@
|
||||
# Git Workshop
|
||||
|
||||
A comprehensive, hands-on Git workshop with 15 progressive modules covering everything from basic commits to advanced debugging techniques and real-world collaboration. Each module presents a real-world scenario that you must solve using Git commands, with automated verification to confirm your solution.
|
||||
|
||||
Perfect for developers who want to move beyond basic Git usage and master professional workflows including rebasing, conflict resolution, collaboration, and advanced Git techniques.
|
||||
|
||||
## Workshop Structure
|
||||
|
||||
The workshop is organized into two tracks:
|
||||
|
||||
### 01 Essentials - Core Git Skills (8 modules)
|
||||
|
||||
Master fundamental Git concepts and collaborative workflows:
|
||||
|
||||
- **Module 01: Git Basics** - Initialize repositories, stage changes, make commits
|
||||
- **Module 02: Viewing History** - Use git log and git diff to explore project history
|
||||
- **Module 03: Branching and Merging** - Create branches, merge them, and resolve conflicts (checkpoint-based)
|
||||
- **Module 04: Cherry-Pick** - Apply specific commits from one branch to another
|
||||
- **Module 05: Git Revert** - Safe undoing - preserve history while reversing changes (includes merge commit reversion)
|
||||
- **Module 06: Git Reset** - Dangerous history rewriting - local cleanup only (NEVER on pushed commits!)
|
||||
- **Module 07: Stash** - Temporarily save work without committing
|
||||
- **Module 08: Multiplayer Git** - **The Great Print Project** - Real cloud-based collaboration with teammates
|
||||
|
||||
### 02 Advanced - Professional Techniques (6 modules)
|
||||
|
||||
Advanced Git workflows for power users:
|
||||
|
||||
- **Module 01: Rebasing** - Rebase branches to create linear history
|
||||
- **Module 02: Interactive Rebase** - Clean up commit history before submitting pull requests
|
||||
- **Module 03: Worktrees** - Work on multiple branches simultaneously
|
||||
- **Module 04: Bisect** - Use binary search to find bug-introducing commits
|
||||
- **Module 05: Blame** - Code archaeology - investigate who changed what and when
|
||||
- **Module 06: Merge Strategies** - Master fast-forward vs three-way merges and when to use each
|
||||
|
||||
## How to Use This Workshop
|
||||
|
||||
### For Local Modules (01-08 in Essentials, all Advanced modules)
|
||||
|
||||
1. Navigate to a module directory (e.g., `01-essentials/01-basics`)
|
||||
2. Read the `README.md` to understand the challenge
|
||||
3. Run `./setup.ps1` to create the challenge environment
|
||||
4. Complete the challenge using git commands
|
||||
5. Run `./verify.ps1` to check if you've solved it correctly
|
||||
6. Move to the next module
|
||||
|
||||
**Quick Reference**: See [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) for a comprehensive list of all Git commands covered in this workshop. Don't worry about memorizing everything - use this as a reference when you need to look up command syntax!
|
||||
|
||||
### For Module 08: Multiplayer Git
|
||||
|
||||
**This module is different!** It uses Azure DevOps for authentic cloud-based collaboration:
|
||||
|
||||
1. Navigate to `01-essentials/08-multiplayer`
|
||||
2. Read the `README.md` for complete instructions
|
||||
3. **No setup script** - you'll clone from Azure DevOps (URL provided by facilitator)
|
||||
4. Work with a partner on shared branches
|
||||
5. Experience real merge conflicts and pull requests
|
||||
6. Use SSH keys for secure authentication (best practice)
|
||||
7. **No verify script** - success is visual (your code appears in the final output)
|
||||
|
||||
**Facilitators**: See `01-essentials/08-multiplayer/FACILITATOR-SETUP.md` for server setup and workshop guidance.
|
||||
|
||||
## Running PowerShell Scripts
|
||||
|
||||
Most modules include setup, verification, and reset scripts.
|
||||
|
||||
If you encounter an "execution policy" error when running scripts, open PowerShell as Administrator and run:
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
```
|
||||
|
||||
Then run scripts using:
|
||||
```powershell
|
||||
.\setup.ps1
|
||||
.\verify.ps1
|
||||
.\reset.ps1
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Install these tools before starting:
|
||||
|
||||
**PowerShell 7+**
|
||||
```powershell
|
||||
winget install Microsoft.PowerShell
|
||||
```
|
||||
|
||||
**Git 2.23+**
|
||||
```powershell
|
||||
winget install Git.Git
|
||||
```
|
||||
|
||||
**Visual Studio Code**
|
||||
```powershell
|
||||
winget install Microsoft.VisualStudioCode
|
||||
```
|
||||
|
||||
### Quick Start
|
||||
|
||||
**Option 1: Oneshot Installation (Recommended)**
|
||||
Install everything and clone the repository in one command:
|
||||
|
||||
```powershell
|
||||
irm https://git.frod.dk/floppydiscen/git-workshop/raw/branch/main/install.ps1 | iex
|
||||
```
|
||||
|
||||
**Option 2: Manual Setup**
|
||||
1. Install the prerequisites above
|
||||
2. Clone this repository:
|
||||
```powershell
|
||||
git clone https://git.frod.dk/floppydiscen/git-workshop.git
|
||||
```
|
||||
3. Configure Git:
|
||||
```powershell
|
||||
git config --global user.name "Your Name"
|
||||
git config --global user.email "your.email@example.com"
|
||||
```
|
||||
|
||||
**Quick Check:**
|
||||
|
||||
You need the following software installed:
|
||||
|
||||
- **Git 2.23+** - Version control system
|
||||
```powershell
|
||||
git --version
|
||||
```
|
||||
|
||||
- **PowerShell 7+**
|
||||
```powershell
|
||||
pwsh --version
|
||||
```
|
||||
|
||||
- **Python 3.6+** (for Module 08 only)
|
||||
```powershell
|
||||
python --version
|
||||
```
|
||||
|
||||
**First-Time Git Configuration:**
|
||||
|
||||
Before making your first commit, configure Git with your identity:
|
||||
|
||||
```powershell
|
||||
git config --global user.name "Your Name"
|
||||
git config --global user.email "your.email@example.com"
|
||||
```
|
||||
|
||||
Verify your configuration:
|
||||
```powershell
|
||||
git config --global user.name
|
||||
git config --global user.email
|
||||
```
|
||||
|
||||
### Basic Command Line Knowledge
|
||||
|
||||
You should know how to:
|
||||
- Navigate directories (`cd`, `ls` or `dir`)
|
||||
- See your current location (`pwd`)
|
||||
- Read text files (`cat` or `type`)
|
||||
|
||||
Don't worry if you're not an expert - we'll guide you through each step!
|
||||
|
||||
## Optional: Install Glow for Pretty Markdown
|
||||
|
||||
This workshop includes many markdown files with instructions. You can install `glow` to render them beautifully in your terminal:
|
||||
|
||||
```powershell
|
||||
.\install-glow.ps1
|
||||
```
|
||||
|
||||
After installation, read markdown files with:
|
||||
|
||||
```powershell
|
||||
.\bin\glow.exe README.md
|
||||
```
|
||||
|
||||
**Pro tip**: Use `glow -p` for pager mode on longer files!
|
||||
|
||||
Without glow, you can still read markdown files with any text editor or `cat README.md`.
|
||||
|
||||
## Common Git Terms
|
||||
|
||||
New to Git? Here are the key terms you'll encounter:
|
||||
|
||||
- **Repository (or "repo")**: A project folder tracked by Git, containing your files and their complete history
|
||||
- **Commit**: A snapshot of your project at a specific point in time (like a save point in a video game)
|
||||
- **Staging Area (or "Index")**: A preparation area where you select which changes to include in your next commit
|
||||
- **Working Directory**: The actual files you see and edit on your computer
|
||||
- **Branch**: An independent line of development (like a parallel universe for your code)
|
||||
- **HEAD**: A pointer showing which commit you're currently working from
|
||||
- **main/master**: The primary branch in a repository (main is the modern convention)
|
||||
- **Merge**: Combining changes from different branches
|
||||
- **Remote**: A version of your repository hosted elsewhere (like GitHub, GitLab, or Gitea)
|
||||
- **Pull Request (PR)**: A request to merge your changes into another branch (used for code review)
|
||||
- **Conflict**: When Git can't automatically merge changes because both versions modified the same lines
|
||||
|
||||
Don't worry if these don't make sense yet - you'll learn them hands-on as you progress!
|
||||
|
||||
## Getting Started
|
||||
|
||||
**First time?** Make sure you have Git and PowerShell installed - see [INSTALLATION.md](INSTALLATION.md) for Windows 11 setup instructions.
|
||||
|
||||
Once installed, start with Essentials Module 01:
|
||||
|
||||
```powershell
|
||||
cd 01-essentials\01-basics
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
Follow the instructions in each module's README.md file.
|
||||
|
||||
## What Makes This Workshop Different
|
||||
|
||||
- **Hands-On Practice**: Each module creates a real Git scenario you must solve
|
||||
- **Automated Verification**: Scripts check your solution instantly (modules 01-08)
|
||||
- **Progressive Difficulty**: Builds from basics to advanced Git techniques
|
||||
- **Reset Anytime**: Each local module includes a reset script for a fresh start
|
||||
- **Self-Paced**: Learn at your own speed with detailed README guides
|
||||
- **Real Collaboration**: Module 08 uses an actual Git server for authentic teamwork
|
||||
- **Comprehensive Coverage**: From `git init` to advanced rebasing and bisecting
|
||||
|
||||
## Learning Path
|
||||
|
||||
The modules are designed to build on each other:
|
||||
|
||||
### Recommended Progression
|
||||
|
||||
**Phase 1: Core Fundamentals (Essentials 01-02)**
|
||||
- Git Basics, History
|
||||
- **Goal**: Understand commits and history
|
||||
|
||||
**Phase 2: Collaboration Basics (Essentials 03)**
|
||||
- Branching and Merging (checkpoint-based: branching, merging, conflicts)
|
||||
- **Goal**: Work with multiple branches and resolve conflicts
|
||||
|
||||
**Phase 3: Workflow Tools (Essentials 04-06)**
|
||||
- Cherry-Pick, Reset vs Revert, Stash
|
||||
- **Goal**: Manage your work effectively
|
||||
|
||||
**Phase 4: Real Collaboration (Essentials 07)**
|
||||
- **Multiplayer Git - The Great Print Project**
|
||||
- **Goal**: Apply all skills with real teammates on a cloud server
|
||||
- **Note**: This is a capstone module - bring everything together!
|
||||
|
||||
**Phase 5: Advanced Techniques (Advanced 01-06)**
|
||||
- Rebasing, Interactive Rebase, Worktrees, Bisect, Blame, Merge Strategies
|
||||
- **Goal**: Master professional Git workflows
|
||||
- **When**: After completing Essentials and feeling confident
|
||||
|
||||
### Alternative Paths
|
||||
|
||||
**Fast Track (1 day workshop):**
|
||||
- Essentials 01-03 + Essentials 07 (Multiplayer)
|
||||
|
||||
**Solo Learner:**
|
||||
- Complete Essentials 01-06, skip 07 (requires partners and server)
|
||||
- Or complete all Advanced modules for deep mastery
|
||||
|
||||
**Team Workshop:**
|
||||
- Essentials 01-03 then jump to 07 (Multiplayer) for collaborative practice
|
||||
|
||||
## Tips for Success
|
||||
|
||||
- **Don't skip modules** - each builds on previous concepts
|
||||
- **Read the README.md thoroughly** before starting each challenge
|
||||
- **Keep [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) open** as a quick reference
|
||||
- **Experiment freely** - you can always run `./reset.ps1` to start over
|
||||
- **Use `git log --oneline --graph --all`** frequently to visualize repository state
|
||||
- **If stuck**, check the Key Concepts section in the module's README
|
||||
- **Consider installing glow** for better markdown reading experience
|
||||
- **For Module 07**, work with a partner - collaboration is the point!
|
||||
|
||||
## Skills You'll Master
|
||||
|
||||
By completing this workshop, you'll be able to:
|
||||
|
||||
### From Essentials Track:
|
||||
- ✅ Create and manage Git repositories with confidence
|
||||
- ✅ Navigate project history and understand what changed when
|
||||
- ✅ Use branches effectively for parallel development
|
||||
- ✅ Merge branches and resolve conflicts like a pro
|
||||
- ✅ Apply specific commits with cherry-pick
|
||||
- ✅ Choose correctly between reset and revert
|
||||
- ✅ Use stash to manage work-in-progress without commits
|
||||
- ✅ **Collaborate with teammates on shared repositories**
|
||||
- ✅ **Resolve real merge conflicts in a team environment**
|
||||
- ✅ **Create and review pull requests**
|
||||
- ✅ **Use Git on a real cloud server (Azure DevOps)**
|
||||
- ✅ **Use SSH keys for secure Git authentication**
|
||||
|
||||
### From Advanced Track:
|
||||
- ✅ Rebase to maintain clean, linear history
|
||||
- ✅ Clean up messy commits before submitting pull requests
|
||||
- ✅ Work on multiple branches simultaneously with worktrees
|
||||
- ✅ Debug efficiently by finding bug-introducing commits with bisect
|
||||
- ✅ Investigate code history with git blame
|
||||
- ✅ Master different merge strategies and when to use each
|
||||
|
||||
These are professional-level Git skills used daily by developers at top tech companies.
|
||||
|
||||
## For Workshop Facilitators
|
||||
|
||||
This repository can be used for **self-paced learning** or as a **facilitated workshop**.
|
||||
|
||||
### Self-Paced Distribution
|
||||
|
||||
Before distributing this workshop to attendees for self-study:
|
||||
|
||||
1. **Delete the root `.git` directory**: This prevents confusion and ensures attendees practice git from scratch
|
||||
```powershell
|
||||
Remove-Item -Path .git -Recurse -Force
|
||||
```
|
||||
2. Each module's `challenge/` directory will become its own independent git repository when attendees run `setup.ps1`
|
||||
3. This isolation ensures each module provides a clean learning environment
|
||||
|
||||
**Note**: Module 08 (Multiplayer) requires you to set up a Git server - see facilitator guide below.
|
||||
|
||||
### Facilitated Workshop
|
||||
|
||||
For running this as a full-day instructor-led workshop:
|
||||
|
||||
1. **See [WORKSHOP-AGENDA.md](WORKSHOP-AGENDA.md)** - Complete agenda with timing, activities, and facilitation tips
|
||||
2. **See [PRESENTATION-OUTLINE.md](PRESENTATION-OUTLINE.md)** - Slide deck outline for presentations
|
||||
3. **Workshop covers:** Essentials 01-05 + Module 08 (Multiplayer collaboration exercise)
|
||||
4. **Duration:** 6-7 hours including breaks
|
||||
5. **Format:** Mix of presentation, live demos, and hands-on challenges
|
||||
|
||||
**Facilitator preparation:**
|
||||
- Review the workshop agenda thoroughly
|
||||
- Set up Git server for Module 08 (see below)
|
||||
- Ensure all participants have prerequisites installed (Git, PowerShell, Python)
|
||||
- Prepare slides using the presentation outline
|
||||
- Test all modules on a clean machine
|
||||
- Create student accounts on your Git server
|
||||
|
||||
The workshop format combines instructor-led sessions with self-paced hands-on modules for an engaging learning experience.
|
||||
|
||||
### Setting Up Module 08: Multiplayer Git
|
||||
|
||||
Module 08 requires a Git server for authentic collaboration using **Azure DevOps**.
|
||||
|
||||
**Azure DevOps Setup**
|
||||
|
||||
Use Azure DevOps as the cloud-based Git platform for this module:
|
||||
|
||||
**Benefits:**
|
||||
- 💰 Free tier supports up to 5 users with full access
|
||||
- 🌐 Cloud-hosted - no server maintenance required
|
||||
- 🔒 Enterprise-grade security and reliability
|
||||
- 🔑 Built-in SSH key support (industry best practice)
|
||||
- 👥 Perfect for workshops with any number of students (use Stakeholder licenses for >5 users)
|
||||
- 📊 Built-in pull request workflows and code review tools
|
||||
|
||||
**Setup Steps:**
|
||||
|
||||
1. **Create Azure DevOps Organization** (if you don't have one):
|
||||
- Sign up at [dev.azure.com](https://dev.azure.com) with a Microsoft account
|
||||
- Create a new organization for your workshop
|
||||
|
||||
2. **Set up SSH authentication** (recommended for all users):
|
||||
- See [AZURE-DEVOPS-SSH-SETUP.md](AZURE-DEVOPS-SSH-SETUP.md) for complete SSH key setup instructions
|
||||
- SSH provides secure, passwordless authentication (industry standard)
|
||||
|
||||
3. **Configure workshop repository and users**:
|
||||
- See `01-essentials/08-multiplayer/FACILITATOR-SETUP.md` for detailed workshop preparation:
|
||||
- Adding student accounts to Azure DevOps
|
||||
- Creating The Great Print Project repository
|
||||
- Configuring branch policies
|
||||
- Pairing students
|
||||
- Monitoring progress
|
||||
- Troubleshooting SSH and authentication issues
|
||||
|
||||
**Alternative: GitHub / GitLab / Bitbucket**
|
||||
|
||||
While this workshop uses Azure DevOps, the skills learned apply to any Git platform:
|
||||
- The workflow is identical across all platforms
|
||||
- SSH authentication works the same way everywhere
|
||||
- Pull request concepts transfer directly
|
||||
- Students can apply these skills to any Git hosting service
|
||||
|
||||
---
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
git-workshop/
|
||||
├── README.md # This file
|
||||
├── INSTALLATION.md # Windows 11 installation guide (PowerShell 7, Git, VS Code)
|
||||
├── install-prerequisites.ps1 # Automated installation script (one-shot setup)
|
||||
├── GIT-CHEATSHEET.md # Quick reference for all Git commands
|
||||
├── WORKSHOP-AGENDA.md # Facilitator guide for running workshops
|
||||
├── PRESENTATION-OUTLINE.md # Slide deck outline
|
||||
├── AZURE-DEVOPS-SSH-SETUP.md # SSH authentication best practices for Azure DevOps
|
||||
├── install-glow.ps1 # Install glow markdown renderer
|
||||
│
|
||||
├── 01-essentials/ # Core Git skills (8 modules)
|
||||
│ ├── 01-basics/ # Initialize, commit, status
|
||||
│ ├── 02-history/ # Log, diff, show
|
||||
│ ├── 03-branching-and-merging/ # Branches, merging, conflicts (checkpoint-based)
|
||||
│ ├── 04-cherry-pick/ # Apply specific commits
|
||||
│ ├── 05-revert/ # Safe undoing (includes merge commits)
|
||||
│ ├── 06-reset/ # Dangerous local cleanup
|
||||
│ ├── 07-stash/ # Save work-in-progress
|
||||
│ └── 08-multiplayer/ # Real collaboration (cloud-based)
|
||||
│ ├── README.md # Student guide
|
||||
│ └── FACILITATOR-SETUP.md # Server setup guide
|
||||
│
|
||||
└── 02-advanced/ # Professional techniques (6 modules)
|
||||
├── 01-rebasing/ # Linear history with rebase
|
||||
├── 02-interactive-rebase/ # Clean up commits
|
||||
├── 03-worktrees/ # Multiple branches simultaneously
|
||||
├── 04-bisect/ # Find bugs with binary search
|
||||
├── 05-blame/ # Code archaeology
|
||||
└── 06-merge-strategies/ # Master merge techniques
|
||||
```
|
||||
|
||||
## What's Unique About This Workshop
|
||||
|
||||
### The Great Print Project (Module 08)
|
||||
|
||||
Unlike any other Git tutorial, Module 08 provides **real collaborative experience**:
|
||||
|
||||
- **Real Git server**: Not simulated - actual Azure DevOps cloud repository
|
||||
- **Real teammates**: Work in pairs on shared branches
|
||||
- **Real conflicts**: Both partners edit the same code and must resolve conflicts together
|
||||
- **Real pull requests**: Create PRs, review code, merge to main
|
||||
- **Real success**: When all pairs merge, run `python main.py` and see everyone's contributions!
|
||||
- **Real security**: Use SSH keys for authentication (industry best practice)
|
||||
|
||||
**The challenge**: Each pair implements 3 Python functions (e.g., `print_b()`, `print_c()`, `print_d()`) in a shared repository. When complete, the program prints the alphabet A-Z and numbers 0-9.
|
||||
|
||||
**What students learn**:
|
||||
- Push/pull workflow with real teammates
|
||||
- Handling rejected pushes (partner pushed first!)
|
||||
- Resolving actual merge conflicts (not simulated)
|
||||
- Creating meaningful pull requests
|
||||
- Reviewing others' code
|
||||
- Staying synchronized with a team
|
||||
|
||||
This is how professional developers actually work - no simulation, no shortcuts.
|
||||
|
||||
---
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
**Q: Do I need to complete all modules?**
|
||||
A: No! Essentials 01-05 covers what most developers use daily. Complete 06-09 and Advanced modules to deepen your skills.
|
||||
|
||||
**Q: Can I do Module 08 (Multiplayer) without a partner?**
|
||||
A: Not recommended - collaboration is the point. If solo, skip to Advanced modules or wait until you can pair with someone.
|
||||
|
||||
**Q: How long does the workshop take?**
|
||||
A:
|
||||
- Essentials 01-05: 3-4 hours
|
||||
- Full Essentials (01-09): 6-7 hours
|
||||
- All modules: 12-15 hours
|
||||
- Self-paced over several days works great!
|
||||
|
||||
**Q: I'm stuck on a module. What should I do?**
|
||||
A:
|
||||
1. Re-read the module README.md
|
||||
2. Check [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md)
|
||||
3. Run `./reset.ps1` to start fresh
|
||||
4. Use `git status` and `git log --graph` to understand current state
|
||||
5. For Module 08, ask your partner or facilitator
|
||||
|
||||
**Q: Can I use this for a team workshop at my company?**
|
||||
A: Absolutely! See the "For Workshop Facilitators" section above. The materials are designed for both self-study and instructor-led workshops.
|
||||
|
||||
**Q: Do I need internet access?**
|
||||
A: Modules 01-07 work completely offline. Module 08 requires internet to access the Git server.
|
||||
|
||||
**Q: What if I prefer GitHub/GitLab instead of Azure DevOps?**
|
||||
A: The skills are identical across all Git platforms. Module 08 uses Azure DevOps but everything you learn applies directly to GitHub, GitLab, Bitbucket, and any other Git hosting service. The SSH authentication, pull request workflow, and collaboration patterns are the same everywhere.
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
Found a bug or have a suggestion? Please open an issue or submit a pull request!
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
This workshop is provided as-is for educational purposes.
|
||||
|
||||
---
|
||||
|
||||
**Ready to master Git?**
|
||||
|
||||
First-time setup (Windows 11): See [INSTALLATION.md](INSTALLATION.md)
|
||||
|
||||
Then start with Essentials Module 01 and begin your journey!
|
||||
|
||||
```powershell
|
||||
cd 01-essentials\01-basics
|
||||
.\setup.ps1
|
||||
```
|
||||
|
||||
Happy Learning! 🚀
|
||||
@@ -642,17 +642,21 @@ if ($userChoice -ne "CloneOnly") {
|
||||
|
||||
Write-Host " Setting the init.defaultBranch to be 'main'"
|
||||
git config --global init.defaultBranch main
|
||||
Write-Success " Set 'main' as default branch"
|
||||
|
||||
Write-Host " Setting the default editor to code, to handle merge messages"
|
||||
git config --global core.editor "code --wait"
|
||||
Write-Success " Visual Studio Code set as core.editor"
|
||||
|
||||
Write-Host " Setting vscode at the default code editor for merge conflicts"
|
||||
git config --global merge.tool vscode
|
||||
git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED'
|
||||
git config --global mergetool.vscode.cmd 'code --wait --merge $MERGED'
|
||||
Write-Success " Visual Studio Code set as mergetool"
|
||||
|
||||
Write-Host " Setting vscode as the default code editor for diffs"
|
||||
git config --global diff.tool vscode
|
||||
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
|
||||
Write-Success " Visual Studio Code set as difftool"
|
||||
|
||||
# Verify Git version specifically
|
||||
if ($results.Git) {
|
||||
|
||||
49
util.ps1
Normal file
49
util.ps1
Normal file
@@ -0,0 +1,49 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Utility functions for writing to stdout and for advanced git commands that are reused again and again
|
||||
#>
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
function Write-Error {
|
||||
param([string] $Message)
|
||||
Write-Host "[ERROR] $Message" -ForegroundColor Red
|
||||
}
|
||||
|
||||
|
||||
function Get-LocalBranches {
|
||||
return git for-each-ref --format='%(refname:short)' refs/heads
|
||||
}
|
||||
|
||||
function Get-MainBranch {
|
||||
$mainBranch = git branch --show-current 2>$null
|
||||
$allBranches = Get-LocalBranches
|
||||
if ($allBranches -contains "main") {
|
||||
$mainBranch = "main"
|
||||
} elseif ($allBranches -contains "master") {
|
||||
$mainBranch = "master"
|
||||
} else {
|
||||
$mainBranch = git config --get init.defaultBranch
|
||||
}
|
||||
|
||||
return $mainBranch
|
||||
}
|
||||
Reference in New Issue
Block a user