Compare commits
11 Commits
a898030a9f
...
3a4fe8ce9e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a4fe8ce9e | ||
|
|
13dd2317f9 | ||
|
|
cac03b69e3 | ||
|
|
19cf66e23d | ||
|
|
a6b33a441e | ||
|
|
690b83cead | ||
|
|
c69b463f84 | ||
|
|
39d8ace75c | ||
|
|
4b9d2449c8 | ||
|
|
5582b9fcbd | ||
|
|
3a6eb0646b |
@@ -11,35 +11,35 @@
|
|||||||
- Committed both required files (welcome.txt and instructions.txt)
|
- Committed both required files (welcome.txt and instructions.txt)
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\..\util.ps1"
|
||||||
|
|
||||||
Write-Host "Verifying Module 01: Git Basics Challenge..." -ForegroundColor Cyan
|
Write-Host "Verifying Module 01: Git Basics Challenge..." -ForegroundColor Cyan
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
$allChecksPassed = $true
|
$allChecksPassed = $true
|
||||||
|
$challengeRoot = "$PSScriptRoot\challenge"
|
||||||
|
|
||||||
# Check if challenge directory exists
|
# Check if challenge directory exists
|
||||||
if (-not (Test-Path "challenge")) {
|
if (-not (Test-Path $challengeRoot)) {
|
||||||
Write-Host "[FAIL] Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
Write-Fail "Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Location "challenge"
|
|
||||||
|
|
||||||
# Check if git repository exists
|
# Check if git repository exists
|
||||||
if (-not (Test-Path ".git")) {
|
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||||
Write-Host "[FAIL] No git repository found. Did you run 'git init'?" -ForegroundColor Red
|
Write-Fail "No git repository found. Did you run 'git init'?" -ForegroundColor Red
|
||||||
Set-Location ".."
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "[PASS] Git repository initialized" -ForegroundColor Green
|
Write-Pass "Git repository initialized" -ForegroundColor Green
|
||||||
|
|
||||||
# Check if there are any commits
|
# Check if there are any commits
|
||||||
$commitCount = (git rev-list --all --count 2>$null)
|
$commitCount = (git rev-list --all --count 2>$null)
|
||||||
if ($null -eq $commitCount -or $commitCount -eq 0) {
|
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
|
$allChecksPassed = $false
|
||||||
} else {
|
} 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
|
# 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
|
$trackedFiles = git ls-tree -r HEAD --name-only 2>$null
|
||||||
|
|
||||||
if ($trackedFiles -match "welcome.txt") {
|
if ($trackedFiles -match "welcome.txt") {
|
||||||
Write-Host "[PASS] welcome.txt is committed" -ForegroundColor Green
|
Write-Pass "welcome.txt is committed" -ForegroundColor Green
|
||||||
} else {
|
} 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
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($trackedFiles -match "instructions.txt") {
|
if ($trackedFiles -match "instructions.txt") {
|
||||||
Write-Host "[PASS] instructions.txt is committed" -ForegroundColor Green
|
Write-Pass "instructions.txt is committed" -ForegroundColor Green
|
||||||
} else {
|
} 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
|
$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
|
Write-Host "[INFO] You have uncommitted changes. This is OK, but make sure all required files are committed." -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Location ".."
|
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
if ($allChecksPassed) {
|
if ($allChecksPassed) {
|
||||||
Write-Host "========================================" -ForegroundColor Green
|
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>`
|
7. View specific commits: `git show <commit-hash>`
|
||||||
8. Compare specific commits: `git diff <commit1> <commit2> <file>`
|
8. Compare specific commits: `git diff <commit1> <commit2> <file>`
|
||||||
9. Fill in your answers in `answers.md`
|
9. Fill in your answers in `answers.md`
|
||||||
|
10. Remember to save `answers.md`
|
||||||
|
|
||||||
> **Important Notes:**
|
> **Important Notes:**
|
||||||
> - You can use any Git commands you like to explore the repository
|
> - 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
|
- answers.txt exists with correct information about commit history
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\..\util.ps1"
|
||||||
|
|
||||||
Write-Host "`n=== Verifying Module 02 Solution ===" -ForegroundColor Cyan
|
Write-Host "`n=== Verifying Module 02 Solution ===" -ForegroundColor Cyan
|
||||||
|
|
||||||
$allChecksPassed = $true
|
$allChecksPassed = $true
|
||||||
|
$challengeRoot = "$PSScriptRoot\challenge"
|
||||||
|
|
||||||
|
|
||||||
# Check if challenge directory exists
|
# Check if challenge directory exists
|
||||||
if (-not (Test-Path "challenge")) {
|
if (-not (Test-Path $challengeRoot)) {
|
||||||
Write-Host "[FAIL] Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red
|
Write-Fail "Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Location "challenge"
|
|
||||||
|
|
||||||
# Check if git repository exists
|
# Check if git repository exists
|
||||||
if (-not (Test-Path ".git")) {
|
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||||
Write-Host "[FAIL] Not a git repository. Did you run setup.ps1?" -ForegroundColor Red
|
Write-Fail "Not a git repository. Did you run setup.ps1?" -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if answers.md exists
|
# Check if answers.md exists
|
||||||
if (-not (Test-Path "answers.md")) {
|
if (-not (Test-Path "$challengeRoot\answers.md")) {
|
||||||
Write-Host "[FAIL] answers.md not found. Did you run setup.ps1?" -ForegroundColor Red
|
Write-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
|
Write-Hint "The setup script should have created answers.md for you" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[PASS] answers.md exists" -ForegroundColor Green
|
Write-Pass "answers.md exists" -ForegroundColor Green
|
||||||
|
|
||||||
# Read the answers file
|
# Read the answers file
|
||||||
$answers = Get-Content "answers.md" -Raw
|
$answers = Get-Content "$challengeRoot\answers.md" -Raw
|
||||||
$answersLower = $answers.ToLower()
|
$answersLower = $answers.ToLower()
|
||||||
|
|
||||||
# Check 1: Contains "5" or "five" for commit count
|
# Check 1: Contains "5" or "five" for commit count
|
||||||
if ($answersLower -match "5|five|fem") {
|
if ($answersLower -match "5|five|fem") {
|
||||||
Write-Host "[PASS] Correct commit count found" -ForegroundColor Green
|
Write-Pass "Correct commit count found" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] Commit count not found or incorrect" -ForegroundColor Red
|
Write-Fail "Commit count not found or incorrect" -ForegroundColor Red
|
||||||
Write-Host "[HINT] Use 'git log --oneline' to count commits easily" -ForegroundColor Yellow
|
Write-Hint "Use 'git log --oneline' to count commits easily" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check 2: Contains "database" keyword for third commit
|
# Check 2: Contains "database" keyword for third commit
|
||||||
if ($answersLower -match "database") {
|
if ($answersLower -match "database") {
|
||||||
Write-Host "[PASS] Third commit message identified" -ForegroundColor Green
|
Write-Pass "Third commit message identified" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] Third commit message not found" -ForegroundColor Red
|
Write-Fail "Third commit message not found" -ForegroundColor Red
|
||||||
Write-Host "[HINT] Use 'git log' to see commit messages in order" -ForegroundColor Yellow
|
Write-Hint "Use 'git log' to see commit messages in order" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,38 +65,37 @@ if (-not (Test-Path "answers.md")) {
|
|||||||
$hasDatabase = $answersLower -match "database"
|
$hasDatabase = $answersLower -match "database"
|
||||||
|
|
||||||
if ($hasAuth -and $hasDatabase) {
|
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) {
|
} elseif ($hasAuth -or $hasDatabase) {
|
||||||
Write-Host "[PARTIAL] Only one file found - there are TWO files modified in this commit" -ForegroundColor Yellow
|
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
|
$allChecksPassed = $false
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] Files modified in bug fix commit not found" -ForegroundColor Red
|
Write-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-Hint "Use 'git log --stat' to see which files were changed in each commit" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check 4: Contains "config" keyword for staged file
|
# Check 4: Contains "config" keyword for staged file
|
||||||
if ($answersLower -match "config.py") {
|
if ($answersLower -match "config.py") {
|
||||||
Write-Host "[PASS] Staged file identified" -ForegroundColor Green
|
Write-Pass "Staged file identified" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] Staged file not identified" -ForegroundColor Red
|
Write-Fail "Staged file not identified" -ForegroundColor Red
|
||||||
Write-Host "[HINT] Use 'git status' or 'git diff --staged' to see staged changes" -ForegroundColor Yellow
|
Write-Hint "Use 'git status' or 'git diff --staged' to see staged changes" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check 5: Contains "unicorn" for the secret code
|
# Check 5: Contains "unicorn" for the secret code
|
||||||
if ($answersLower -match "unicorn") {
|
if ($answersLower -match "unicorn") {
|
||||||
Write-Host "[PASS] Secret code found!" -ForegroundColor Green
|
Write-Pass "Secret code found!" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] Secret code not found" -ForegroundColor Red
|
Write-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-Hint "Use 'git diff <commit3> <commit4> database.py' to find the secret code" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Location ..
|
|
||||||
|
|
||||||
# Final summary
|
# Final summary
|
||||||
if ($allChecksPassed) {
|
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!
|
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`)
|
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.
|
- 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`
|
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!
|
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`
|
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
|
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`
|
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!
|
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.
|
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
|
- 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!
|
You should see your feature branch merged into main!
|
||||||
|
|
||||||
@@ -139,7 +142,7 @@ git merge another-feature
|
|||||||
|
|
||||||
### What is a Branch?
|
### 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
|
main: A---B---C
|
||||||
@@ -154,7 +157,7 @@ my-feature: D---E
|
|||||||
|
|
||||||
### What is HEAD?
|
### 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
|
```pwsh
|
||||||
# HEAD points to main
|
# HEAD points to main
|
||||||
@@ -181,7 +184,7 @@ main: A---B---C---M
|
|||||||
feature: D---E
|
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**:
|
**Fast-forward merge**:
|
||||||
```
|
```
|
||||||
@@ -194,7 +197,7 @@ After merge:
|
|||||||
main: A---B---C---D
|
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
|
## Key Commands
|
||||||
|
|
||||||
@@ -340,7 +343,7 @@ After completing this module, you understand:
|
|||||||
|
|
||||||
## Next Steps
|
## 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:
|
To start over:
|
||||||
```pwsh
|
```pwsh
|
||||||
@@ -348,4 +351,4 @@ To start over:
|
|||||||
.\setup.ps1
|
.\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
|
$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
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Check challenge directory exists
|
# 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 "[ERROR] Challenge directory not found." -ForegroundColor Red
|
||||||
Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Push-Location "challenge"
|
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||||
|
|
||||||
if (-not (Test-Path ".git")) {
|
|
||||||
Write-Host "[ERROR] Not a git repository." -ForegroundColor Red
|
Write-Host "[ERROR] Not a git repository." -ForegroundColor Red
|
||||||
Write-Host "Run ..\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
Write-Host "Run ..\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
||||||
Pop-Location
|
|
||||||
exit 1
|
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.)
|
# Detect the main branch name (could be main, master, etc.)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Try to get the default branch from remote origin first
|
# Try to get the default branch from remote origin first
|
||||||
$mainBranch = git symbolic-ref refs/remotes/origin/HEAD 2>$null | Split-Path -Leaf
|
$mainBranch = Get-MainBranch
|
||||||
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" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
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
|
## 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?**
|
**When do conflicts happen?**
|
||||||
- ✅ Two branches modify the same lines in a file
|
- ✅ Two branches modify the same lines in a file
|
||||||
- ✅ One branch deletes a file that another branch modifies
|
- ✅ 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 files are changed (no conflict!)
|
||||||
- ❌ Different parts of the same file 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
|
## Your Task
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ For this challenge, we want **both settings**, so:
|
|||||||
|
|
||||||
### Part 9: Mark the Conflict as Resolved
|
### Part 9: Mark the Conflict as Resolved
|
||||||
|
|
||||||
Tell Git you've resolved the conflict:
|
Tell git you've resolved the conflict:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Stage the resolved file
|
# Stage the resolved file
|
||||||
@@ -267,7 +267,7 @@ All conflicts fixed but you are still merging.
|
|||||||
(use "git commit" to conclude merge)
|
(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
|
### Part 10: Complete the Merge
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ Commit the merge:
|
|||||||
git commit
|
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!
|
**Done!** Your merge is complete!
|
||||||
|
|
||||||
@@ -436,7 +436,7 @@ git diff main..feature-branch
|
|||||||
|
|
||||||
## Merge Tools
|
## Merge Tools
|
||||||
|
|
||||||
Git supports visual merge tools that make resolving conflicts easier:
|
git supports visual merge tools that make resolving conflicts easier:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Configure a merge tool (one-time setup)
|
# Configure a merge tool (one-time setup)
|
||||||
@@ -484,4 +484,4 @@ To start over:
|
|||||||
.\setup.ps1
|
.\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
|
- Ensuring valid JSON syntax
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\..\util.ps1"
|
||||||
|
|
||||||
$script:allChecksPassed = $true
|
$script:allChecksPassed = $true
|
||||||
|
$challengeRoot = "$PSScriptRoot\challenge"
|
||||||
|
|
||||||
# ============================================================================
|
Write-Host $PSScriptRoot
|
||||||
# Helper Functions
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
function Write-Pass {
|
|
||||||
param([string]$Message)
|
|
||||||
Write-Host "[PASS] $Message" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
|
|
||||||
function Write-Fail {
|
|
||||||
param([string]$Message)
|
|
||||||
Write-Host "[FAIL] $Message" -ForegroundColor Red
|
|
||||||
$script:allChecksPassed = $false
|
|
||||||
}
|
|
||||||
|
|
||||||
function Write-Hint {
|
|
||||||
param([string]$Message)
|
|
||||||
Write-Host "[HINT] $Message" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
function Write-Info {
|
|
||||||
param([string]$Message)
|
|
||||||
Write-Host "[INFO] $Message" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Check challenge directory exists
|
# Check challenge directory exists
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
if (-not (Test-Path "challenge")) {
|
if (-not (Test-Path $challengeRoot)) {
|
||||||
Write-Host "[ERROR] Challenge directory not found." -ForegroundColor Red
|
Write-Error "Challenge directory not found." -ForegroundColor Red
|
||||||
Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Push-Location "challenge"
|
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||||
|
Write-Error "Not a git repository." -ForegroundColor Red
|
||||||
if (-not (Test-Path ".git")) {
|
Write-Host "Run .\setup.ps1 first to create the challenge environment." -ForegroundColor Yellow
|
||||||
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
|
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.)
|
# Detect the main branch name (could be main, master, etc.)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Try to get the default branch from remote origin first
|
# Try to get the default branch from remote origin first
|
||||||
$mainBranch = git symbolic-ref refs/remotes/origin/HEAD 2>$null | Split-Path -Leaf
|
$mainBranch = Get-MainBranch
|
||||||
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" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -97,22 +57,20 @@ if ($currentBranch -eq $mainBranch) {
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Check that merge is not in progress
|
# 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-Fail "Merge is still in progress (conflicts not resolved)"
|
||||||
Write-Hint "Resolve conflicts in config.json, then: git add config.json && git commit"
|
Write-Hint "Resolve conflicts in config.json, then: git add config.json && git commit"
|
||||||
Pop-Location
|
|
||||||
exit 1
|
exit 1
|
||||||
} else {
|
} else {
|
||||||
Write-Pass "No merge in progress (conflicts resolved)"
|
Write-Pass "No merge in progress (conflicts resolved)"
|
||||||
}
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Check if config.json exists
|
# 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-Fail "File 'config.json' not found"
|
||||||
Write-Hint "The config.json file should exist"
|
Write-Hint "The config.json file should exist"
|
||||||
Pop-Location
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,14 +78,13 @@ if (-not (Test-Path "config.json")) {
|
|||||||
# Verify config.json is valid JSON
|
# Verify config.json is valid JSON
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
try {
|
try {
|
||||||
$configContent = Get-Content "config.json" -Raw
|
$configContent = Get-Content "$challengeRoot\config.json" -Raw
|
||||||
$config = $configContent | ConvertFrom-Json -ErrorAction Stop
|
$config = $configContent | ConvertFrom-Json -ErrorAction Stop
|
||||||
Write-Pass "File 'config.json' is valid JSON"
|
Write-Pass "File 'config.json' is valid JSON"
|
||||||
} catch {
|
} catch {
|
||||||
Write-Fail "File 'config.json' is not valid JSON"
|
Write-Fail "File 'config.json' is not valid JSON"
|
||||||
Write-Hint "Make sure you removed all conflict markers (<<<<<<<, =======, >>>>>>>)"
|
Write-Hint "Make sure you removed all conflict markers (<<<<<<<, =======, >>>>>>>)"
|
||||||
Write-Hint "Check for missing commas or brackets"
|
Write-Hint "Check for missing commas or brackets"
|
||||||
Pop-Location
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +94,6 @@ try {
|
|||||||
if ($configContent -match '<<<<<<<|=======|>>>>>>>') {
|
if ($configContent -match '<<<<<<<|=======|>>>>>>>') {
|
||||||
Write-Fail "Conflict markers still present in config.json"
|
Write-Fail "Conflict markers still present in config.json"
|
||||||
Write-Hint "Remove all conflict markers (<<<<<<<, =======, >>>>>>>)"
|
Write-Hint "Remove all conflict markers (<<<<<<<, =======, >>>>>>>)"
|
||||||
Pop-Location
|
|
||||||
exit 1
|
exit 1
|
||||||
} else {
|
} else {
|
||||||
Write-Pass "No conflict markers in config.json"
|
Write-Pass "No conflict markers in config.json"
|
||||||
@@ -163,8 +119,11 @@ if ($config.app.debug -eq $true) {
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Verify both branches were merged
|
# Verify both branches were merged
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
$addTimeoutMerged = git log --oneline --grep="add-timeout" 2>$null | Select-String "Merge"
|
git merge-base --is-ancestor add-timeout main
|
||||||
$addDebugMerged = git log --oneline --grep="add-debug" 2>$null | Select-String "Merge"
|
$addTimeoutMerged = $LASTEXITCODE -eq 0
|
||||||
|
|
||||||
|
git merge-base --is-ancestor add-debug main
|
||||||
|
$addDebugMerged = $LASTEXITCODE -eq 0
|
||||||
|
|
||||||
if ($addTimeoutMerged) {
|
if ($addTimeoutMerged) {
|
||||||
Write-Pass "add-timeout branch has been merged"
|
Write-Pass "add-timeout branch has been merged"
|
||||||
@@ -197,7 +156,6 @@ if ($totalCommits -ge 5) {
|
|||||||
Write-Hint "Make sure both branches are merged"
|
Write-Hint "Make sure both branches are merged"
|
||||||
}
|
}
|
||||||
|
|
||||||
Pop-Location
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Final summary
|
# Final summary
|
||||||
|
|||||||
@@ -110,24 +110,26 @@ Now copy the bug fix commits from development to main:
|
|||||||
- Look for a commit message like "Fix security vulnerability in input validation"
|
- Look for a commit message like "Fix security vulnerability in input validation"
|
||||||
- Note its hash (first 7 characters)
|
- Note its hash (first 7 characters)
|
||||||
|
|
||||||
2. Cherry-pick the security fix:
|
2. First let's just check whether or not we have the `security.py` and `cache.py` file available by running `ls` in the challenge directory or check the file explorer in your VSCode
|
||||||
|
|
||||||
|
3. Cherry-pick the security fix:
|
||||||
```pwsh
|
```pwsh
|
||||||
git cherry-pick <security-fix-hash>
|
git cherry-pick <security-fix-hash>
|
||||||
|
|
||||||
# Example if the hash is abc1234:
|
# Example if the hash is abc1234:
|
||||||
# git cherry-pick abc1234
|
# git cherry-pick abc1234
|
||||||
```
|
```
|
||||||
3. Verify it worked: Check that security.py, with `ls` or check your file explorer in VSCode, now exists and check that the commit has been added to the main branch with `git log --oneline --graph --all`
|
4. Verify it worked: Check that security.py, with `ls` or check your file explorer in VSCode, now exists and check that the commit has been added to the main branch with `git log --oneline --graph --all`
|
||||||
4. Find the performance fix commit hash
|
5. Find the performance fix commit hash
|
||||||
- Look for "Fix performance issue with data caching"
|
- Look for "Fix performance issue with data caching"
|
||||||
- Note its hash
|
- Note its hash
|
||||||
|
|
||||||
5. Cherry-pick the performance fix:
|
6. Cherry-pick the performance fix:
|
||||||
```pwsh
|
```pwsh
|
||||||
git cherry-pick <performance-fix-hash>
|
git cherry-pick <performance-fix-hash>
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Verify both fixes are now on main:
|
7. Verify both fixes are now on main:
|
||||||
```pwsh
|
```pwsh
|
||||||
# You should see both security.py and cache.py
|
# You should see both security.py and cache.py
|
||||||
ls
|
ls
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
the bug fixes to the main branch.
|
the bug fixes to the main branch.
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\..\util.ps1"
|
||||||
|
|
||||||
# Remove existing challenge directory if present
|
# Remove existing challenge directory if present
|
||||||
if (Test-Path "challenge") {
|
if (Test-Path "challenge") {
|
||||||
Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow
|
Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow
|
||||||
@@ -42,11 +44,7 @@ git add app.py
|
|||||||
git commit -m "Initial app implementation" | Out-Null
|
git commit -m "Initial app implementation" | Out-Null
|
||||||
|
|
||||||
# Detect the main branch name after first commit
|
# Detect the main branch name after first commit
|
||||||
$mainBranch = git branch --show-current
|
$mainBranch = Get-MainBranch
|
||||||
if (-not $mainBranch) {
|
|
||||||
$mainBranch = git config --get init.defaultBranch
|
|
||||||
if (-not $mainBranch) { $mainBranch = "main" }
|
|
||||||
}
|
|
||||||
Write-Host "Default branch detected: $mainBranch" -ForegroundColor Yellow
|
Write-Host "Default branch detected: $mainBranch" -ForegroundColor Yellow
|
||||||
|
|
||||||
$readme = @"
|
$readme = @"
|
||||||
|
|||||||
@@ -9,168 +9,136 @@
|
|||||||
to the main branch without merging the experimental features.
|
to the main branch without merging the experimental features.
|
||||||
#>
|
#>
|
||||||
|
|
||||||
Set-Location "challenge" -ErrorAction SilentlyContinue
|
. "$PSScriptRoot\..\..\util.ps1"
|
||||||
|
|
||||||
# Check if challenge directory exists
|
$challengeRoot = "$PSScriptRoot\challenge"
|
||||||
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 ".")) {
|
if (-not (Test-Path $challengeRoot)) {
|
||||||
Write-Host "Error: Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
Write-Host "Error: Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Verifying your solution..." -ForegroundColor Cyan
|
Write-Host "Verifying your solution..." -ForegroundColor Cyan
|
||||||
|
|
||||||
# Check if git repository exists
|
# Check if git repository exists
|
||||||
if (-not (Test-Path ".git")) {
|
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||||
Write-Host "[FAIL] No git repository found." -ForegroundColor Red
|
Write-Fail "No git repository found." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Detect the main branch name
|
$mainBranch = Get-MainBranch
|
||||||
$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" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
||||||
|
|
||||||
# Check current branch
|
# Check current branch
|
||||||
$currentBranch = git branch --show-current 2>$null
|
$currentBranch = git branch --show-current 2>$null
|
||||||
if ($currentBranch -ne $mainBranch) {
|
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 "Current branch: $currentBranch" -ForegroundColor Yellow
|
||||||
Write-Host "Hint: Use 'git checkout $mainBranch' to switch to $mainBranch branch" -ForegroundColor Yellow
|
Write-Hint "Use 'git checkout $mainBranch' to switch to $mainBranch branch" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if there's an ongoing cherry-pick
|
# Check if there's an ongoing cherry-pick
|
||||||
if (Test-Path ".git/CHERRY_PICK_HEAD") {
|
if (Test-Path "$challengeRoot\.git\CHERRY_PICK_HEAD") {
|
||||||
Write-Host "[FAIL] Cherry-pick is not complete. There may be unresolved conflicts." -ForegroundColor Red
|
Write-Fail "Cherry-pick is not complete. There may be unresolved conflicts." -ForegroundColor Red
|
||||||
Write-Host "Hint: Resolve any conflicts, then use:" -ForegroundColor Yellow
|
Write-Hint "Resolve any conflicts, then use:" -ForegroundColor Yellow
|
||||||
Write-Host " git add <file>" -ForegroundColor White
|
Write-Host " git add <file>" -ForegroundColor White
|
||||||
Write-Host " git cherry-pick --continue" -ForegroundColor White
|
Write-Host " git cherry-pick --continue" -ForegroundColor White
|
||||||
Write-Host "Or abort with: git cherry-pick --abort" -ForegroundColor White
|
Write-Host "Or abort with: git cherry-pick --abort" -ForegroundColor White
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check commit count on main (should be 4: 2 initial + 2 cherry-picked)
|
# Check commit count on main (should be 4: 2 initial + 2 cherry-picked)
|
||||||
$mainCommitCount = (git rev-list --count $mainBranch 2>$null)
|
$mainCommitCount = (git rev-list --count $mainBranch 2>$null)
|
||||||
if ($mainCommitCount -ne 4) {
|
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) {
|
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 {
|
} 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 "`nExpected commits on ${mainBranch}:" -ForegroundColor Yellow
|
||||||
Write-Host " 1. Initial app implementation" -ForegroundColor White
|
Write-Host " 1. Initial app implementation" -ForegroundColor White
|
||||||
Write-Host " 2. Add README" -ForegroundColor White
|
Write-Host " 2. Add README" -ForegroundColor White
|
||||||
Write-Host " 3. Fix security vulnerability in input validation (cherry-picked)" -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
|
Write-Host " 4. Fix performance issue with data caching (cherry-picked)" -ForegroundColor White
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check for merge commits (should be none - cherry-pick doesn't create merge commits)
|
# Check for merge commits (should be none - cherry-pick doesn't create merge commits)
|
||||||
$mergeCommits = git log --merges --oneline $mainBranch 2>$null
|
$mergeCommits = git log --merges --oneline $mainBranch 2>$null
|
||||||
if ($mergeCommits) {
|
if ($mergeCommits) {
|
||||||
Write-Host "[FAIL] Found merge commits on $mainBranch. You should use cherry-pick, not merge." -ForegroundColor Red
|
Write-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
|
Write-Hint "Use 'git cherry-pick <commit-hash>' instead of 'git merge'" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that security.py exists (from the security fix commit)
|
# Check that security.py exists (from the security fix commit)
|
||||||
if (-not (Test-Path "security.py")) {
|
if (-not (Test-Path "$challengeRoot\security.py")) {
|
||||||
Write-Host "[FAIL] security.py not found on $mainBranch branch." -ForegroundColor Red
|
Write-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
|
Write-Hint "You need to cherry-pick the 'Fix security vulnerability' commit" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that security.py has the security fix
|
# 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") {
|
if ($securityContent -notmatch "sanitize_input") {
|
||||||
Write-Host "[FAIL] security.py is missing the sanitize_input function." -ForegroundColor Red
|
Write-Fail "security.py is missing the sanitize_input function." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($securityContent -notmatch "validate_token") {
|
if ($securityContent -notmatch "validate_token") {
|
||||||
Write-Host "[FAIL] security.py is missing the validate_token function." -ForegroundColor Red
|
Write-Fail "security.py is missing the validate_token function." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that app.py exists
|
# Check that app.py exists
|
||||||
if (-not (Test-Path "app.py")) {
|
if (-not (Test-Path "$challengeRoot\app.py")) {
|
||||||
Write-Host "[FAIL] app.py not found." -ForegroundColor Red
|
Write-Fail "app.py not found." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that cache.py exists (from performance fix)
|
# Check that cache.py exists (from performance fix)
|
||||||
if (-not (Test-Path "cache.py")) {
|
if (-not (Test-Path "$challengeRoot\cache.py")) {
|
||||||
Write-Host "[FAIL] cache.py not found on $mainBranch branch." -ForegroundColor Red
|
Write-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
|
Write-Hint "You need to cherry-pick the 'Fix performance issue' commit" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that cache.py has the DataCache class
|
# 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") {
|
if ($cacheContent -notmatch "DataCache") {
|
||||||
Write-Host "[FAIL] cache.py is missing the DataCache class." -ForegroundColor Red
|
Write-Fail "cache.py is missing the DataCache class." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cacheContent -notmatch "def get\(") {
|
if ($cacheContent -notmatch "def get\(") {
|
||||||
Write-Host "[FAIL] cache.py is missing the get method." -ForegroundColor Red
|
Write-Fail "cache.py is missing the get method." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that app.py does NOT have experimental features
|
# 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
|
# Should NOT have experimental features
|
||||||
if ($appContent -match "experimental_mode") {
|
if ($appContent -match "experimental_mode") {
|
||||||
Write-Host "[FAIL] app.py contains experimental features (experimental_mode)." -ForegroundColor Red
|
Write-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-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
|
Write-Host " The experimental feature commits should stay on development branch only" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($appContent -match "beta_features") {
|
if ($appContent -match "beta_features") {
|
||||||
Write-Host "[FAIL] app.py contains experimental features (beta_features)." -ForegroundColor Red
|
Write-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
|
Write-Hint "You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($appContent -match "enable_experimental_features") {
|
if ($appContent -match "enable_experimental_features") {
|
||||||
Write-Host "[FAIL] app.py contains experimental features (enable_experimental_features)." -ForegroundColor Red
|
Write-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
|
Write-Hint "You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,25 +159,22 @@ foreach ($commit in $commitArray) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (-not $hasSecurityFix) {
|
if (-not $hasSecurityFix) {
|
||||||
Write-Host "[FAIL] Security fix commit not found on $mainBranch branch." -ForegroundColor Red
|
Write-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
|
Write-Hint "Cherry-pick the 'Fix security vulnerability' commit from development" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $hasPerformanceFix) {
|
if (-not $hasPerformanceFix) {
|
||||||
Write-Host "[FAIL] Performance fix commit not found on $mainBranch branch." -ForegroundColor Red
|
Write-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
|
Write-Hint "Cherry-pick the 'Fix performance issue' commit from development" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Verify development branch still has all commits
|
# Verify development branch still has all commits
|
||||||
$devCommitCount = (git rev-list --count development 2>$null)
|
$devCommitCount = (git rev-list --count development 2>$null)
|
||||||
if ($devCommitCount -ne 6) {
|
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
|
Write-Host "Found: $devCommitCount commits" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
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 "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
|
Write-Host "Try 'git log --oneline --graph --all' to see both branches." -ForegroundColor Cyan
|
||||||
|
|
||||||
Set-Location ..
|
|
||||||
exit 0
|
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:**
|
1. **Navigate to the challenge directory:**
|
||||||
```pwsh
|
```pwsh
|
||||||
cd challenge
|
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`):
|
2. **Check which branch you're on** (you should be on `regular-revert`):
|
||||||
|
|||||||
@@ -9,23 +9,23 @@
|
|||||||
- multi-revert: Multiple commits reverted
|
- multi-revert: Multiple commits reverted
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\..\util.ps1"
|
||||||
|
|
||||||
Write-Host "`n=== Verifying Module 06: Git Revert Solutions ===" -ForegroundColor Cyan
|
Write-Host "`n=== Verifying Module 06: Git Revert Solutions ===" -ForegroundColor Cyan
|
||||||
|
|
||||||
$allChecksPassed = $true
|
$allChecksPassed = $true
|
||||||
$originalDir = Get-Location
|
|
||||||
|
$challengeRoot = "$PSScriptRoot\challenge"
|
||||||
|
|
||||||
# Check if challenge directory exists
|
# Check if challenge directory exists
|
||||||
if (-not (Test-Path "challenge")) {
|
if (-not (Test-Path "$challengeRoot")) {
|
||||||
Write-Host "[FAIL] Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
Write-Fail "Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Location "challenge"
|
|
||||||
|
|
||||||
# Check if git repository exists
|
# Check if git repository exists
|
||||||
if (-not (Test-Path ".git")) {
|
if (-not (Test-Path "$challengeRoot\.git")) {
|
||||||
Write-Host "[FAIL] Not a git repository. Run setup.ps1 first." -ForegroundColor Red
|
Write-Fail "Not a git repository. Run setup.ps1 first." -ForegroundColor Red
|
||||||
Set-Location $originalDir
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,50 +37,50 @@ Write-Host "`n=== Scenario 1: Regular Revert ===" -ForegroundColor Cyan
|
|||||||
git switch regular-revert 2>&1 | Out-Null
|
git switch regular-revert 2>&1 | Out-Null
|
||||||
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
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
|
$allChecksPassed = $false
|
||||||
} else {
|
} else {
|
||||||
# Check that a revert commit exists
|
# Check that a revert commit exists
|
||||||
$revertCommit = git log --oneline --grep="Revert" 2>$null
|
$revertCommit = git log --oneline --grep="Revert" 2>$null
|
||||||
if ($revertCommit) {
|
if ($revertCommit) {
|
||||||
Write-Host "[PASS] Revert commit found" -ForegroundColor Green
|
Write-Pass "Revert commit found" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] No revert commit found" -ForegroundColor Red
|
Write-Fail "No revert commit found" -ForegroundColor Red
|
||||||
Write-Host "[HINT] Use: git revert <commit-hash>" -ForegroundColor Yellow
|
Write-Hint "Use: git revert <commit-hash>" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that divide.py is removed (was reverted)
|
# Check that divide.py is removed (was reverted)
|
||||||
if (-not (Test-Path "divide.py")) {
|
if (-not (Test-Path "$challengeRoot\divide.py")) {
|
||||||
Write-Host "[PASS] Broken divide.py successfully reverted (file removed)" -ForegroundColor Green
|
Write-Pass "Broken divide.py successfully reverted (file removed)" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] divide.py still exists (should be reverted)" -ForegroundColor Red
|
Write-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-Hint "The bad commit should be reverted, removing divide.py" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that calculator.py exists and has correct content
|
# Check that calculator.py exists and has correct content
|
||||||
if (Test-Path "calculator.py") {
|
if (Test-Path "$challengeRoot\calculator.py") {
|
||||||
$calcContent = Get-Content "calculator.py" -Raw
|
$calcContent = Get-Content "$challengeRoot\calculator.py" -Raw
|
||||||
|
|
||||||
# Check that modulo function still exists (should be preserved)
|
# Check that modulo function still exists (should be preserved)
|
||||||
if ($calcContent -match "def modulo") {
|
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 {
|
} else {
|
||||||
Write-Host "[FAIL] modulo function missing (should still exist)" -ForegroundColor Red
|
Write-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-Hint "Only revert the bad commit, not the good ones after it" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that multiply function exists (should be preserved)
|
# Check that multiply function exists (should be preserved)
|
||||||
if ($calcContent -match "def multiply") {
|
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 {
|
} else {
|
||||||
Write-Host "[FAIL] multiply function missing" -ForegroundColor Red
|
Write-Fail "multiply function missing" -ForegroundColor Red
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] calculator.py not found" -ForegroundColor Red
|
Write-Fail "calculator.py not found" -ForegroundColor Red
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ Write-Host "`n=== Scenario 2: Multi Revert ===" -ForegroundColor Cyan
|
|||||||
git switch multi-revert 2>&1 | Out-Null
|
git switch multi-revert 2>&1 | Out-Null
|
||||||
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
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
|
$allChecksPassed = $false
|
||||||
} else {
|
} else {
|
||||||
# Count revert commits
|
# Count revert commits
|
||||||
@@ -101,56 +101,54 @@ if ($LASTEXITCODE -ne 0) {
|
|||||||
$revertCount = ($revertCommits | Measure-Object).Count
|
$revertCount = ($revertCommits | Measure-Object).Count
|
||||||
|
|
||||||
if ($revertCount -ge 2) {
|
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 {
|
} else {
|
||||||
Write-Host "[FAIL] Found only $revertCount revert commit(s), need at least 2" -ForegroundColor Red
|
Write-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-Hint "Revert both bad commits: git revert <commit1> <commit2>" -ForegroundColor Yellow
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that sqrt.py is removed (reverted)
|
# Check that sqrt.py is removed (reverted)
|
||||||
if (-not (Test-Path "sqrt.py")) {
|
if (-not (Test-Path "$challengeRoot\sqrt.py")) {
|
||||||
Write-Host "[PASS] Broken sqrt.py successfully reverted (file removed)" -ForegroundColor Green
|
Write-Pass "Broken sqrt.py successfully reverted (file removed)" -ForegroundColor Green
|
||||||
} else {
|
} 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
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that logarithm.py is removed (reverted)
|
# Check that logarithm.py is removed (reverted)
|
||||||
if (-not (Test-Path "logarithm.py")) {
|
if (-not (Test-Path "$challengeRoot\logarithm.py")) {
|
||||||
Write-Host "[PASS] Broken logarithm.py successfully reverted (file removed)" -ForegroundColor Green
|
Write-Pass "Broken logarithm.py successfully reverted (file removed)" -ForegroundColor Green
|
||||||
} else {
|
} 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
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check calculator.py content
|
# Check calculator.py content
|
||||||
if (Test-Path "calculator.py") {
|
if (Test-Path "$challengeRoot\calculator.py") {
|
||||||
$calcContent = Get-Content "calculator.py" -Raw
|
$calcContent = Get-Content "$challengeRoot\calculator.py" -Raw
|
||||||
|
|
||||||
# Check that power function still exists (good commit before bad ones)
|
# Check that power function still exists (good commit before bad ones)
|
||||||
if ($calcContent -match "def power") {
|
if ($calcContent -match "def power") {
|
||||||
Write-Host "[PASS] power function preserved" -ForegroundColor Green
|
Write-Pass "power function preserved" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] power function missing (should still exist)" -ForegroundColor Red
|
Write-Fail "power function missing (should still exist)" -ForegroundColor Red
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that absolute function still exists (good commit after bad ones)
|
# Check that absolute function still exists (good commit after bad ones)
|
||||||
if ($calcContent -match "def absolute") {
|
if ($calcContent -match "def absolute") {
|
||||||
Write-Host "[PASS] absolute function preserved" -ForegroundColor Green
|
Write-Pass "absolute function preserved" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] absolute function missing (should still exist)" -ForegroundColor Red
|
Write-Fail "absolute function missing (should still exist)" -ForegroundColor Red
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] calculator.py not found" -ForegroundColor Red
|
Write-Fail "calculator.py not found" -ForegroundColor Red
|
||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Location $originalDir
|
|
||||||
|
|
||||||
# Final summary
|
# Final summary
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
if ($allChecksPassed) {
|
if ($allChecksPassed) {
|
||||||
|
|||||||
@@ -9,48 +9,28 @@
|
|||||||
and completed the feature on the feature branch.
|
and completed the feature on the feature branch.
|
||||||
#>
|
#>
|
||||||
|
|
||||||
Set-Location "challenge" -ErrorAction SilentlyContinue
|
$root = $PSScriptRoot
|
||||||
|
|
||||||
# Check if challenge directory exists
|
if (-not (Test-Path "$root/challenge")) {
|
||||||
if (-not (Test-Path "../verify.ps1")) {
|
Write-Error "Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
||||||
Write-Host "Error: Please run this script from the module directory" -ForegroundColor Red
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not (Test-Path ".")) {
|
|
||||||
Write-Host "Error: Challenge directory not found. Run setup.ps1 first." -ForegroundColor Red
|
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Verifying your solution..." -ForegroundColor Cyan
|
Write-Host "Verifying your solution..." -ForegroundColor Cyan
|
||||||
|
|
||||||
# Check if git repository exists
|
# Check if git repository exists
|
||||||
if (-not (Test-Path ".git")) {
|
if (-not (Test-Path "$root/challenge/.git")) {
|
||||||
Write-Host "[FAIL] No git repository found." -ForegroundColor Red
|
Write-Fail "No git repository found." -ForegroundColor Red
|
||||||
Set-Location ..
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Detect the main branch name
|
$mainBranch = Get-MainBranch
|
||||||
$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" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
Write-Host "Detected main branch: $mainBranch" -ForegroundColor Cyan
|
||||||
|
|
||||||
# Check current branch
|
# Check current branch
|
||||||
$currentBranch = git branch --show-current 2>$null
|
$currentBranch = git branch --show-current 2>$null
|
||||||
if ($currentBranch -ne "feature-login") {
|
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 "Current branch: $currentBranch" -ForegroundColor Yellow
|
||||||
Write-Host "Hint: Switch back to feature-login after completing the challenge" -ForegroundColor Yellow
|
Write-Host "Hint: Switch back to feature-login after completing the challenge" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
@@ -60,8 +40,8 @@ if ($currentBranch -ne "feature-login") {
|
|||||||
# Check for uncommitted changes on feature-login
|
# Check for uncommitted changes on feature-login
|
||||||
$status = git status --porcelain 2>$null
|
$status = git status --porcelain 2>$null
|
||||||
if ($status) {
|
if ($status) {
|
||||||
Write-Host "[FAIL] You have uncommitted changes on feature-login." -ForegroundColor Red
|
Write-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-Hint "After restoring from stash, you should complete and commit the feature" -ForegroundColor Yellow
|
||||||
git status --short
|
git status --short
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
@@ -69,7 +49,7 @@ if ($status) {
|
|||||||
|
|
||||||
# Verify main branch has the security fix
|
# Verify main branch has the security fix
|
||||||
Write-Host "`nChecking $mainBranch branch for bug fix..." -ForegroundColor Cyan
|
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
|
# Check for bug fix commit
|
||||||
$mainCommits = git log --pretty=format:"%s" $mainBranch 2>$null
|
$mainCommits = git log --pretty=format:"%s" $mainBranch 2>$null
|
||||||
@@ -82,17 +62,17 @@ foreach ($commit in $mainCommits) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (-not $hasSecurityFix) {
|
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
|
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 ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that app.py has been fixed
|
# Check that app.py has been fixed
|
||||||
if (-not (Test-Path "app.py")) {
|
if (-not (Test-Path "app.py")) {
|
||||||
Write-Host "[FAIL] app.py not found on $mainBranch branch." -ForegroundColor Red
|
Write-Fail "app.py not found on $mainBranch branch." -ForegroundColor Red
|
||||||
git checkout feature-login 2>$null | Out-Null
|
git switch feature-login 2>$null | Out-Null
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -102,9 +82,9 @@ $appContent = Get-Content "app.py" -Raw
|
|||||||
# The bug was "return true" in authenticate - it should be fixed now
|
# 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
|
# We'll check that the buggy comment is gone or the implementation is improved
|
||||||
if ($appContent -match "allows unauthenticated access") {
|
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
|
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 ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -113,14 +93,14 @@ Write-Host "[PASS] Security bug fixed on main!" -ForegroundColor Green
|
|||||||
|
|
||||||
# Switch back to feature-login
|
# Switch back to feature-login
|
||||||
Write-Host "`nChecking feature-login branch..." -ForegroundColor Cyan
|
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
|
# Check for completed feature commit
|
||||||
$featureCommits = git log --pretty=format:"%s" feature-login 2>$null
|
$featureCommits = git log --pretty=format:"%s" feature-login 2>$null
|
||||||
$commitCount = ($featureCommits -split "`n").Count
|
$commitCount = ($featureCommits -split "`n").Count
|
||||||
|
|
||||||
if ($commitCount -lt 3) {
|
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
|
Write-Host "Hint: You should have the initial commits plus your completed feature commit" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
@@ -128,7 +108,7 @@ if ($commitCount -lt 3) {
|
|||||||
|
|
||||||
# Check that login.py exists
|
# Check that login.py exists
|
||||||
if (-not (Test-Path "login.py")) {
|
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 ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -137,22 +117,22 @@ $loginContent = Get-Content "login.py" -Raw
|
|||||||
|
|
||||||
# Check that login method exists and is implemented
|
# Check that login method exists and is implemented
|
||||||
if ($loginContent -notmatch "def login") {
|
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 ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that TODOs are completed (no TODO comments should remain)
|
# Check that TODOs are completed (no TODO comments should remain)
|
||||||
if ($loginContent -match "TODO") {
|
if ($loginContent -match "TODO") {
|
||||||
Write-Host "[FAIL] login.py still contains TODO comments." -ForegroundColor Red
|
Write-Fail "login.py still contains TODO comments." -ForegroundColor Red
|
||||||
Write-Host "Hint: Complete all the TODOs in login.py before committing" -ForegroundColor Yellow
|
Write-Hint "Complete all the TODOs in login.py before committing" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that password verification is implemented
|
# Check that password verification is implemented
|
||||||
if ($loginContent -notmatch "password") {
|
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 ..
|
Set-Location ..
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -160,7 +140,7 @@ if ($loginContent -notmatch "password") {
|
|||||||
# Check that the feature has been committed (not just in working directory)
|
# Check that the feature has been committed (not just in working directory)
|
||||||
$lastCommit = git log -1 --pretty=format:"%s" 2>$null
|
$lastCommit = git log -1 --pretty=format:"%s" 2>$null
|
||||||
if ($lastCommit -notmatch "login|feature|complete|implement") {
|
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 "Last commit: $lastCommit" -ForegroundColor Yellow
|
||||||
Write-Host "Hint: After popping the stash and completing the TODOs, commit the feature" -ForegroundColor Yellow
|
Write-Host "Hint: After popping the stash and completing the TODOs, commit the feature" -ForegroundColor Yellow
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ This creates a new branch and switches to it.
|
|||||||
```powershell
|
```powershell
|
||||||
git add .
|
git add .
|
||||||
git commit -m "fix: move 7 to correct position"
|
git commit -m "fix: move 7 to correct position"
|
||||||
git push feature-2
|
git push
|
||||||
```
|
```
|
||||||
|
|
||||||
Your branch is now on Azure DevOps.
|
Your branch is now on Azure DevOps.
|
||||||
|
|||||||
@@ -19,8 +19,52 @@ Master fundamental Git concepts and collaborative workflows:
|
|||||||
- **Module 07: Stash** - Temporarily save work without committing
|
- **Module 07: Stash** - Temporarily save work without committing
|
||||||
- **Module 08: Multiplayer Git** - **The Great Print Project** - Real cloud-based collaboration with teammates
|
- **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
|
## How to Use This Workshop
|
||||||
|
|
||||||
|
|
||||||
### For Local Modules (01-07)
|
### For Local Modules (01-07)
|
||||||
|
|
||||||
1. Navigate to a module directory (e.g., `01-essentials/01-basics`)
|
1. Navigate to a module directory (e.g., `01-essentials/01-basics`)
|
||||||
@@ -28,6 +72,7 @@ Master fundamental Git concepts and collaborative workflows:
|
|||||||
3. Run `./setup.ps1` to create the challenge environment
|
3. Run `./setup.ps1` to create the challenge environment
|
||||||
4. Complete the challenge using git commands
|
4. Complete the challenge using git commands
|
||||||
5. Run `./verify.ps1` to check if you've solved it correctly
|
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
|
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!
|
**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!
|
||||||
@@ -56,6 +101,12 @@ If you encounter an "execution policy" error when running scripts, open PowerShe
|
|||||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
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:
|
Then run scripts using:
|
||||||
```pwsh
|
```pwsh
|
||||||
.\setup.ps1
|
.\setup.ps1
|
||||||
@@ -63,49 +114,6 @@ Then run scripts using:
|
|||||||
.\reset.ps1
|
.\reset.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
Install these tools before starting:
|
|
||||||
|
|
||||||
**PowerShell 7+**
|
|
||||||
```pwsh
|
|
||||||
winget install Microsoft.PowerShell
|
|
||||||
```
|
|
||||||
|
|
||||||
**Git 2.23+**
|
|
||||||
```pwsh
|
|
||||||
winget install Git.Git
|
|
||||||
```
|
|
||||||
|
|
||||||
**Visual Studio Code**
|
|
||||||
```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
|
|
||||||
```
|
|
||||||
|
|
||||||
### Quick Start
|
|
||||||
|
|
||||||
1. **Install the prerequisites above**
|
|
||||||
2. **Clone this repository**
|
|
||||||
3. **Configure Git** (see below for recommended settings)
|
|
||||||
|
|
||||||
## Git Configuration
|
## Git Configuration
|
||||||
|
|
||||||
Before starting the workshop, configure Git with your identity and recommended settings:
|
Before starting the workshop, configure Git with your identity and recommended settings:
|
||||||
@@ -269,31 +277,3 @@ By completing this workshop, you'll be able to:
|
|||||||
- **Use SSH keys for secure Git authentication**
|
- **Use SSH keys for secure Git authentication**
|
||||||
|
|
||||||
These are professional-level Git skills used daily by developers at tech companies.
|
These are professional-level Git skills used daily by developers at tech companies.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Repository Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
git-workshop/
|
|
||||||
├── README.md # This file
|
|
||||||
├── INSTALLATION.md # Installation guide
|
|
||||||
├── install.ps1 # Automated installation script
|
|
||||||
├── GIT-CHEATSHEET.md # Quick reference for all Git commands
|
|
||||||
├── BEST-PRACTICES.md # Git best practices
|
|
||||||
├── COMMIT-MESSAGES.md # Guide to writing good commit messages
|
|
||||||
├── WHAT-IS-GIT.md # Introduction to Git concepts
|
|
||||||
│
|
|
||||||
└── 01-essentials/ # Core Git skills (8 modules)
|
|
||||||
├── 01-basics/ # Initialize, commit, status
|
|
||||||
├── 02-history/ # Log, diff, show
|
|
||||||
├── 03-branching-and-merging/ # Branches and merging
|
|
||||||
├── 04-merge-conflict/ # Resolve merge conflicts
|
|
||||||
├── 05-cherry-pick/ # Apply specific commits
|
|
||||||
├── 06-revert/ # Safe undoing
|
|
||||||
├── 07-stash/ # Save work-in-progress
|
|
||||||
└── 08-multiplayer/ # Real collaboration (cloud-based)
|
|
||||||
├── README.md # Student guide
|
|
||||||
├── 01_FACILITATOR.md # Facilitator setup guide
|
|
||||||
└── 02_AZURE-DEVOPS-SSH-SETUP.md # SSH authentication guide
|
|
||||||
```
|
|
||||||
@@ -110,7 +110,7 @@ Nothing creates unnecessary conflicts like two people reformatting the same file
|
|||||||
|
|
||||||
**Do this:**
|
**Do this:**
|
||||||
- Agree on code formatting standards as a team
|
- 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
|
- Configure your editor to format on save
|
||||||
- Run formatters before committing
|
- Run formatters before committing
|
||||||
|
|
||||||
@@ -122,16 +122,22 @@ Renaming a widely-used function or moving files around will conflict with almost
|
|||||||
|
|
||||||
**Do this:**
|
**Do this:**
|
||||||
- Announce refactors to the team before starting
|
- 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
|
- Do them quickly and push immediately
|
||||||
- Consider doing them when others aren't actively working
|
- Consider doing them when others aren't actively working
|
||||||
- Keep refactoring commits separate from feature work
|
- 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
|
## The Golden Rules
|
||||||
|
|
||||||
1. **Sync frequently** - Pull before you start, pull before you push
|
1. **Sync frequently** - Pull before you start, pull before you push
|
||||||
2. **Commit small** - Many small commits beat one large commit
|
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
|
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
|
5. **Push promptly** - Don't sit on finished work
|
||||||
|
|
||||||
## When Conflicts Do Happen
|
## 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
|
1. **Don't panic** - Conflicts are normal, not failures
|
||||||
2. **Read carefully** - Understand both sides before choosing
|
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
|
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.
|
Remember: merge conflicts are a communication problem as much as a technical one. The best tool for reducing conflicts is talking to your team.
|
||||||
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