Compare commits

...

10 Commits

Author SHA1 Message Date
Bjarke Sporring
6b0e84934a feat: split out git blame 2026-01-07 21:12:31 +01:00
Bjarke Sporring
30b878fc67 feat: add git blame section 2026-01-07 20:22:53 +01:00
Bjarke Sporring
aefcfbe100 feat: add more challenges to the history module 2026-01-07 20:12:54 +01:00
Bjarke Sporring
5f8091d5b2 feat: add advanced node 2026-01-07 19:26:11 +01:00
Bjarke Sporring
cf073d569e refactor: move modules into levels 2026-01-07 17:59:02 +01:00
Bjarke Sporring
d7c146975d feat: add understanding for diffs 2026-01-05 13:34:59 +01:00
Bjarke Sporring
dc94520b2a feat: add guidance for beginners to get started 2026-01-05 12:47:33 +01:00
Bjarke Sporring
e29b9bca70 feat: use switch instead of checkout 2026-01-05 12:38:35 +01:00
Bjarke Sporring
a7b511c8cb feat: add git cheatsheet 2026-01-05 12:34:40 +01:00
Bjarke Sporring
a8eb66d3c9 feat: update readme 2026-01-05 12:22:01 +01:00
59 changed files with 1770 additions and 181 deletions

View File

@@ -53,20 +53,53 @@ git status # Show the working tree status
git add <file> # Stage a specific file for commit
git add . # Stage all files in current directory
git commit -m "<message>" # Create a commit with a message
git ls-tree -r HEAD --name-only # List all files in the latest commit
git ls-tree -r HEAD --name-only # ADVANCED: List all files in the latest commit
git log # View commit history
```
### Verification
Once you think you've completed the challenge, run:
Once you think you've completed the challenge, run the verification script.
**Important:** Run this from the **module directory**, not the challenge directory.
```powershell
# If you're in the challenge directory, go back up:
cd ..
# Then verify:
.\verify.ps1
```
This will check if you've successfully completed all the steps.
### Troubleshooting
**Error: "fatal: unable to auto-detect email address"**
This means Git doesn't know who you are yet. You need to configure your name and email:
```powershell
git config user.name "Your Name"
git config user.email "your.email@example.com"
```
Then try your commit again. For more details, see the "Requirements" section in the main README.md.
**Error: "Not a git repository"**
Make sure you ran `git init` in the challenge directory. This creates a hidden `.git` folder that tracks your project.
**Can't find the challenge directory?**
Make sure you ran `.\setup.ps1` first from the module directory. This creates the `challenge/` folder.
**Where am I?**
Use `pwd` (Print Working Directory) to see your current location:
- If you're in something like `.../module-01-basics/challenge`, you're in the challenge directory
- If you're in something like `.../module-01-basics`, you're in the module directory
### Need to Start Over?
If you want to reset the challenge and start fresh, run:

View File

@@ -0,0 +1,225 @@
# Module 02: Viewing History
## Learning Objectives
In this module, you will:
- Understand commit history and how to navigate it
- Use `git log` to view commit history with various formats
- Use `git show` to view specific commit details
- Use `git diff` to compare changes between commits
- Use `git diff --staged` to view changes ready to be committed
- Understand commit hashes and references
- Discover how `git diff` reveals changes not visible in current files
## Challenge
### Setup
Run the setup script to create your challenge environment:
```powershell
.\setup.ps1
```
This will create a `challenge/` directory with a Git repository that already has some commit history.
### Your Task
You'll explore an existing Git repository that contains multiple commits. Your goal is to use Git commands to discover information about the repository's history, including:
- Viewing commit history
- Examining changes between specific commits
- Understanding staged changes
- **Finding a secret code hidden in the commit history!** (Only discoverable by using `git diff`)
The setup script will create an `answers.md` file in the challenge directory with questions for you to answer. Fill in your answers directly in that file.
**Suggested Approach:**
1. Navigate to the challenge directory: `cd challenge`
2. Open `answers.md` to see the questions
3. View the commit history: `git log` or `git log --oneline`
4. Check repository status: `git status`
5. View staged changes: `git diff --staged`
6. Try different log formats: `git log --stat`, `git log --graph`
7. View specific commits: `git show <commit-hash>`
8. Compare specific commits: `git diff <commit1> <commit2> <file>`
9. Fill in your answers in `answers.md`
> **Important Notes:**
> - You can use any Git commands you like to explore the repository
> - Fill in your answers directly in the `answers.md` file (there are placeholder sections for each answer)
> - Commit hashes can be referenced by their full hash or just the first 7 characters
> - Notice that one file is already staged - use `git diff --staged` to see what it contains
## Key Concepts
- **Commit Hash**: A unique identifier (SHA-1 hash) for each commit. You can use the full hash or just the first few characters.
- **Commit Message**: A description of what changed in that commit, written by the author.
- **Commit History**: The chronological record of all changes made to a repository.
- **HEAD**: A pointer to the current commit you're working from.
- **Diff**: A view showing the differences between two versions of files.
- **Staging Area**: Where changes wait before being committed. Use `git diff --staged` to see what's ready to commit.
- **Working Directory vs Staged vs Committed**:
- Working Directory: Files you're currently editing
- Staged (Index): Changes marked for the next commit (via `git add`)
- Committed: Changes permanently saved in history
## Understanding Diff Output
When you run `git diff` between commits, the output can look confusing at first. Here's how to read it:
### Example Diff Output
```diff
diff --git a/app.py b/app.py
index 1a2b3c4..5d6e7f8 100644
--- a/app.py
+++ b/app.py
@@ -1,5 +1,7 @@
# app.py - Main application file
+from auth import login, logout
def main():
print("Welcome to My App!")
- # Application initialization code here
+ login("user", "password")
pass
```
### Breaking It Down
**1. File Header**
```diff
diff --git a/app.py b/app.py
```
- Shows which file is being compared
- `a/app.py` = old version (before)
- `b/app.py` = new version (after)
**2. Metadata**
```diff
index 1a2b3c4..5d6e7f8 100644
--- a/app.py
+++ b/app.py
```
- `---` indicates the old version
- `+++` indicates the new version
- The hashes (1a2b3c4, 5d6e7f8) are internal Git identifiers
**3. Change Location (Hunk Header)**
```diff
@@ -1,5 +1,7 @@
```
- `@@ -1,5 +1,7 @@` tells you where changes occurred
- `-1,5` = in the old file, starting at line 1, showing 5 lines
- `+1,7` = in the new file, starting at line 1, showing 7 lines
- The file grew by 2 lines (from 5 to 7)
**4. The Actual Changes**
Lines are prefixed with symbols:
- ` ` (space) = unchanged line (context)
- `-` (minus) = line removed from old version (shown in red in terminal)
- `+` (plus) = line added in new version (shown in green in terminal)
In our example:
```diff
# app.py - Main application file ← unchanged
+from auth import login, logout ← added (new)
def main(): ← unchanged
print("Welcome to My App!") ← unchanged
- # Application initialization code here ← removed (old)
+ login("user", "password") ← added (new)
pass ← unchanged
```
### Reading Multiple Files
If multiple files changed, you'll see multiple diff sections:
```diff
diff --git a/app.py b/app.py
[changes to app.py]
diff --git a/auth.py b/auth.py
[changes to auth.py]
```
### Pro Tips
- **Context lines**: Unchanged lines around changes help you understand where the change happened
- **Color coding**: In your terminal, deletions are usually red, additions are green
- **No newline warning**: If you see `\ No newline at end of file`, it means the file doesn't end with a newline character (usually not important for beginners)
- **Binary files**: For images or other binary files, Git just says "Binary files differ"
### Try It Yourself
In this module's challenge, you'll use:
```bash
# See what's staged for the next commit
git diff --staged
# Compare changes between specific commits
git diff <commit2> <commit4> app.py
```
Pay attention to:
- Which lines were added (green, with `+`)
- Which lines were removed (red, with `-`)
- The surrounding context (white, with space)
- How `git diff --staged` shows only changes ready to commit
## Useful Commands
### Viewing History
```bash
git log # View commit history
git log --oneline # Compact one-line format
git log --stat # Show files changed in each commit
git log --graph # Show branch graph (more useful with branches)
git show <commit> # View specific commit details
git show <commit>:<file> # View a file from a specific commit
```
### Comparing Changes with git diff
```bash
# Compare commits
git diff <commit1> <commit2> # Compare two commits
git diff <commit1> <commit2> <file> # Compare specific file between commits
git diff <commit> # Compare commit with current working directory
# Compare staged changes
git diff --staged # Show changes in staging area (ready to commit)
git diff --cached # Same as --staged (alternative syntax)
git diff # Show unstaged changes in working directory
git diff HEAD # Show all changes (staged + unstaged) vs last commit
```
**When to use each `git diff` variant:**
- `git diff` - See what you've changed but haven't staged yet
- `git diff --staged` - Review what you're about to commit
- `git diff HEAD` - See all your changes since the last commit
- `git diff <commit1> <commit2>` - Compare any two points in history
## Verification
Once you've filled in your answers in `answers.md`, verify your solution:
```powershell
.\verify.ps1
```
The verification script will check that your answers contain the expected information.
## Need to Start Over?
If you want to reset the challenge and start fresh:
```powershell
.\reset.ps1
```
This will remove the challenge directory and run the setup script again, giving you a clean slate.

View File

@@ -87,6 +87,7 @@ git commit -m "Add user authentication" | Out-Null
Write-Host "Adding database connection..." -ForegroundColor Green
$databaseContent = @"
# database.py - Database connection module
# SECRET_CODE: UNICORN
def connect():
# Connect to database
@@ -140,6 +141,22 @@ def logout(username):
"@
Set-Content -Path "auth.py" -Value $authContent
# Remove the secret code from database.py
$databaseContent = @"
# database.py - Database connection module
def connect():
# Connect to database
print("Connecting to database...")
return True
def disconnect():
# Disconnect from database
print("Disconnecting from database...")
return True
"@
Set-Content -Path "database.py" -Value $databaseContent
git add .
git commit -m "Fix authentication bug" | Out-Null
@@ -183,52 +200,155 @@ Set-Content -Path "app.py" -Value $appContent
git add .
git commit -m "Add user profile feature" | Out-Null
# Create a staged change scenario
Write-Host "Creating staged changes for exploration..." -ForegroundColor Green
$configContent = @"
# config.py - Configuration settings
DEBUG_MODE = False
DATABASE_URL = "sqlite:///app.db"
"@
Set-Content -Path "config.py" -Value $configContent
git add config.py
# Create answers.md template
Write-Host "Creating answers.md template..." -ForegroundColor Green
$answersTemplate = @"
# Git History Exploration - Answers
Answer the following questions by exploring the Git repository history.
## Question 1: How many commits are in the repository?
**Your Answer:**
<!-- Write your answer here -->
## Question 2: What was the commit message for the third commit?
(Counting from the first/oldest commit)
**Your Answer:**
<!-- Write your answer here -->
## Question 3: Which file was modified in the "Fix authentication bug" commit?
**Your Answer:**
<!-- Write your answer here -->
## Question 4: What changes were made to app.py between the first and last commits?
Briefly describe the main changes you observe.
**Your Answer:**
<!-- Write your answer here -->
Welcome! Answer the following questions by exploring the Git repository history using Git commands.
**Instructions:**
- Replace the "Write your answer here" comments with your actual answers
- You can use any Git commands to explore the repository
- The hints section at the bottom provides helpful commands
---
**Hints:**
- Use `git log` or `git log --oneline` to view commit history
- Use `git log --stat` to see which files were changed in each commit
- Use `git show <commit-hash>` to view details of a specific commit
- Use `git diff <commit1> <commit2> <file>` to compare changes between commits
## Question 1: How many commits are in the repository?
**Suggested commands:**
``````bash
git log --oneline
# Or count them with:
git rev-list --count HEAD
``````
**Your Answer:**
<!-- Write your answer here -->
---
## Question 2: What was the commit message for the third commit?
**Note:** Count from the first/oldest commit (the one at the bottom of `git log`)
**Suggested commands:**
``````bash
git log --oneline --reverse # Shows oldest first
git log # Shows newest first
``````
**Your Answer:**
<!-- Write your answer here -->
---
## Question 3: Which files were modified in the "Fix authentication bug" commit?
**Note:** There are multiple files - list all of them!
**Suggested commands:**
``````bash
git log --stat # Shows files changed in each commit
git show <commit-hash> --name-only # Shows only filenames for a commit
``````
**Your Answer:**
<!-- Write your answer here (list all files) -->
---
## Question 4: What new file is currently staged (ready to be committed)?
**Suggested commands:**
``````bash
git status # Shows staged, unstaged, and untracked files
git diff --staged # Shows content of staged changes
``````
**Your Answer:**
<!-- Write your answer here -->
---
## Question 5: Find the secret code hidden in the commit history! 🔍
**The Challenge:**
A secret code was added in one commit and then removed in a later commit. It doesn't exist in the current files - you can ONLY find it by comparing commits with `git diff`.
**Hint:** The secret code is in `database.py` and exists in the third commit but was removed in the fourth commit.
**Suggested commands:**
``````bash
# First, get the commit hashes
git log --oneline
# Then compare the third and fourth commits
git diff <commit3-hash> <commit4-hash> database.py
# Look for lines that were removed (marked with - in red)
``````
**Your Answer (what is the secret code?):**
<!-- Write your answer here -->
---
---
## Quick Reference - Useful Commands
**Viewing History:**
``````bash
git log # View commit history (newest first)
git log --oneline # Compact one-line format
git log --reverse # Show oldest commits first
git log --stat # Show files changed in each commit
git log --graph --all # Visual branch graph
``````
**Viewing Specific Commits:**
``````bash
git show <commit-hash> # View commit details
git show <commit-hash> --stat # Show files changed
git show <commit-hash>:file.txt # View file from specific commit
``````
**Comparing Changes:**
``````bash
git diff <commit1> <commit2> # Compare two commits
git diff <commit1> <commit2> file # Compare specific file
git diff --staged # Show staged changes
git diff # Show unstaged changes
git diff HEAD # Show all changes since last commit
``````
**Repository Status:**
``````bash
git status # Show working tree status
git ls-files # List all tracked files
``````
**Pro Tip:** You can use just the first 7 characters of a commit hash (e.g., `a1b2c3d` instead of the full hash)
---
When you're done, run ``..\verify.ps1`` to check your answers!
"@
Set-Content -Path "answers.md" -Value $answersTemplate

View File

@@ -59,23 +59,40 @@ if (-not (Test-Path "answers.md")) {
$allChecksPassed = $false
}
# Check 3: Contains "auth" keyword for file modified in bug fix
if ($answersLower -match "auth") {
Write-Host "[PASS] Correct file identified for bug fix commit" -ForegroundColor Green
# Check 3: Contains both "auth" and "database" keywords for files modified in bug fix
$hasAuth = $answersLower -match "auth"
$hasDatabase = $answersLower -match "database"
if ($hasAuth -and $hasDatabase) {
Write-Host "[PASS] Both files identified for bug fix commit" -ForegroundColor Green
} elseif ($hasAuth -or $hasDatabase) {
Write-Host "[PARTIAL] Only one file found - there are TWO files modified in this commit" -ForegroundColor Yellow
Write-Host "[HINT] Use 'git log --stat' or 'git show <commit-hash> --name-only' to see ALL files changed" -ForegroundColor Yellow
$allChecksPassed = $false
} else {
Write-Host "[FAIL] File modified in bug fix commit not found" -ForegroundColor Red
Write-Host "[FAIL] Files modified in bug fix commit not found" -ForegroundColor Red
Write-Host "[HINT] Use 'git log --stat' to see which files were changed in each commit" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check 4: Some mention of changes (flexible check)
if ($answersLower -match "import|profile|function|added|login|connect") {
Write-Host "[PASS] Changes to app.py described" -ForegroundColor Green
# Check 4: Contains "config" keyword for staged file
if ($answersLower -match "config") {
Write-Host "[PASS] Staged file identified" -ForegroundColor Green
} else {
Write-Host "[FAIL] Changes to app.py not described" -ForegroundColor Red
Write-Host "[HINT] Use 'git diff <first-commit> <last-commit> app.py' to see changes" -ForegroundColor Yellow
Write-Host "[FAIL] Staged file not identified" -ForegroundColor Red
Write-Host "[HINT] Use 'git status' or 'git diff --staged' to see staged changes" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check 5: Contains "unicorn" for the secret code
if ($answersLower -match "unicorn") {
Write-Host "[PASS] Secret code found!" -ForegroundColor Green
} else {
Write-Host "[FAIL] Secret code not found" -ForegroundColor Red
Write-Host "[HINT] Use 'git diff <commit3> <commit4> database.py' to find the secret code" -ForegroundColor Yellow
$allChecksPassed = $false
}
}
Set-Location ..
@@ -91,7 +108,8 @@ if ($allChecksPassed) {
Write-Host " - View commit history with git log" -ForegroundColor White
Write-Host " - Find specific commits and their messages" -ForegroundColor White
Write-Host " - See which files changed in commits" -ForegroundColor White
Write-Host " - Compare changes between commits with git diff" -ForegroundColor White
Write-Host " - Check staged changes with git diff --staged" -ForegroundColor White
Write-Host " - Compare changes between specific commits with git diff" -ForegroundColor White
Write-Host "`nReady for the next module!" -ForegroundColor Green
Write-Host ""
} else {

View File

@@ -4,8 +4,8 @@
In this module, you will:
- Understand what a branch is in Git
- Create new branches using `git branch` or `git checkout -b`
- Switch between branches using `git checkout` or `git switch`
- Create new branches using `git branch` or `git switch -c`
- Switch between branches using `git switch`
- View all branches with `git branch`
- Understand that branches allow parallel development
@@ -38,19 +38,18 @@ Your goal is to create a feature branch, make commits on it, and understand how
1. Navigate to the challenge directory: `cd challenge`
2. View existing branches: `git branch`
3. Create and switch to new branch: `git checkout -b feature-login`
3. Create and switch to new branch: `git switch -c feature-login`
4. Create `login.py` with any content you like
5. Stage and commit: `git add login.py` and `git commit -m "Add login functionality"`
6. Modify `login.py`, then commit again
7. Switch back to main: `git checkout main`
7. Switch back to main: `git switch main`
8. Run `ls` and notice that `login.py` doesn't exist on main!
9. Switch back to feature-login: `git checkout feature-login`
9. Switch back to feature-login: `git switch feature-login`
10. Run `ls` again and see that `login.py` is back!
> **Important Notes:**
> - You can use either `git checkout` or `git switch` to change branches
> - `git checkout -b <name>` creates and switches in one command
> - `git switch -c <name>` is the newer equivalent
> - Use `git switch` to change branches (modern Git command)
> - `git switch -c <name>` creates and switches in one command
> - Branches are independent - files in one branch don't affect another until you merge
> - You can switch between branches as many times as you want
@@ -66,10 +65,9 @@ Your goal is to create a feature branch, make commits on it, and understand how
```bash
git branch # List all branches (* shows current)
git branch <name> # Create a new branch
git checkout <branch> # Switch to an existing branch
git checkout -b <name> # Create and switch to new branch
git switch <branch> # Switch to a branch (newer syntax)
git switch -c <name> # Create and switch (newer syntax)
git switch <branch> # Switch to an existing branch
git switch -c <name> # Create and switch to new branch
git switch - # Switch back to previous branch
git branch -d <name> # Delete a branch (we won't use this yet)
```

View File

@@ -43,10 +43,10 @@ This challenge has two parts that teach you about the two types of merges in Git
3. View existing branches: `git branch -a`
4. Merge feature-api: `git merge feature-api`
5. View the log: `git log --oneline --graph`
6. Create feature-ui branch: `git checkout -b feature-ui`
6. Create feature-ui branch: `git switch -c feature-ui`
7. Create a new file `ui.py` and commit it
8. Make another commit on feature-ui (modify ui.py)
9. Switch back to main: `git checkout main`
9. Switch back to main: `git switch main`
10. Make a change on main (modify api.py) and commit it
11. Merge feature-ui: `git merge feature-ui`
12. View the merge history: `git log --oneline --graph --all`

View File

@@ -112,7 +112,7 @@ The verification will check that:
2. You're currently on the development branch
3. View the commits: `git log --oneline`
4. You'll see several commits - identify the bug fixes
5. Switch to main branch: `git checkout main`
5. Switch to main branch: `git switch main`
6. Cherry-pick the bug fix commits (you'll need their commit hashes)
7. Verify the result with `git log --oneline`
8. Run the verification script
@@ -131,7 +131,7 @@ The verification will check that:
### Hotfix to Production
You have a critical bug fix on a development branch that needs to go to production immediately:
```bash
git checkout production
git switch production
git cherry-pick <bugfix-commit-hash>
```
@@ -141,17 +141,17 @@ You accidentally committed on the wrong branch:
# On wrong branch, note the commit hash
git log --oneline
# Switch to correct branch
git checkout correct-branch
git switch correct-branch
git cherry-pick <commit-hash>
# Go back and remove from wrong branch
git checkout wrong-branch
git switch wrong-branch
git reset --hard HEAD~1
```
### Backporting
You need to apply a fix to an older release branch:
```bash
git checkout release-2.0
git switch release-2.0
git cherry-pick <fix-from-main>
```

View File

@@ -135,7 +135,7 @@ The verification will check that:
2. You're on the local-feature branch with a bad commit
3. View commits: `git log --oneline`
4. Use `git reset --hard HEAD~1` to remove the bad commit
5. Switch to shared-feature: `git checkout shared-feature`
5. Switch to shared-feature: `git switch shared-feature`
6. View commits: `git log --oneline`
7. Find the hash of the "Add broken feature" commit
8. Use `git revert <commit-hash>` to undo it safely

View File

@@ -121,10 +121,10 @@ The verification will check that:
3. Check status: `git status` (you'll see modified files)
4. Stash your changes: `git stash save "WIP: login feature"`
5. Verify working directory is clean: `git status`
6. Switch to main: `git checkout main`
6. Switch to main: `git switch main`
7. View the bug in app.js and fix it (remove the incorrect line)
8. Commit the fix: `git add app.js && git commit -m "Fix critical security bug"`
9. Switch back to feature: `git checkout feature-login`
9. Switch back to feature: `git switch feature-login`
10. Restore your work: `git stash pop`
11. Complete the feature (the TODOs in login.js)
12. Commit your completed feature
@@ -147,9 +147,9 @@ The verification will check that:
```bash
# Working on feature, need to switch to main
git stash
git checkout main
git switch main
# Do work on main
git checkout feature
git switch feature
git stash pop
```
@@ -176,10 +176,10 @@ git stash pop # Restore original work
```bash
# Same fix needed on multiple branches
git stash
git checkout branch1
git switch branch1
git stash apply
git commit -am "Apply fix"
git checkout branch2
git switch branch2
git stash apply
git commit -am "Apply fix"
git stash drop # Clean up when done

View File

@@ -134,7 +134,7 @@ The verification will check that:
2. You'll find a simulated "remote" repository
3. Clone it: `git clone remote-repo local-repo`
4. Navigate into your clone: `cd local-repo`
5. Create and switch to a feature branch: `git checkout -b add-feature`
5. Create and switch to a feature branch: `git switch -c add-feature`
6. Make changes to the project (add a new feature to app.js)
7. Commit your changes
8. Push to remote: `git push -u origin add-feature`
@@ -185,20 +185,20 @@ Safer than pull because it doesn't automatically merge
### Daily Work Flow
```bash
# Start of day: get latest changes
git checkout main
git switch main
git pull origin main
# Create feature branch
git checkout -b my-feature
git switch -c my-feature
# Do work, make commits
git add .
git commit -m "Add feature"
# Before pushing, update with latest main
git checkout main
git switch main
git pull origin main
git checkout my-feature
git switch my-feature
git merge main
# Push your feature
@@ -223,7 +223,7 @@ git remote add upstream <original-repo-url>
# Get latest from upstream
git fetch upstream
git checkout main
git switch main
git merge upstream/main
# Push to your fork

View File

@@ -86,7 +86,7 @@ git rebase --abort
git branch
# Switch to a branch
git checkout <branch-name>
git switch <branch-name>
```
## Verification

View File

@@ -0,0 +1,169 @@
# Module 05: Git Blame - Code Archaeology
## Learning Objectives
In this module, you will:
- Use `git blame` to find who made specific changes
- Understand blame output format and information
- Track down problematic code changes
- Learn when and why to use `git blame`
- Investigate code history to understand context
## Challenge
### Setup
Run the setup script to create your challenge environment:
```powershell
.\setup.ps1
```
This will create a `challenge/` directory with a Git repository that has a security issue - someone committed hardcoded credentials!
### Your Task
Your team has discovered a security vulnerability: hardcoded credentials were added to the codebase. Your job is to investigate who made this change and document your findings.
The setup script will create an `investigation.md` file in the challenge directory with questions for you to answer. Use `git blame` and other Git commands to track down the responsible developer.
**Scenario:**
- Someone added hardcoded login credentials (`username: "admin"`, `password: "admin123"`) to `app.py`
- This is a critical security issue
- You need to identify who made this change so the team can discuss it with them
**Suggested Approach:**
1. Navigate to the challenge directory: `cd challenge`
2. Open `investigation.md` to see the questions
3. Examine `app.py` to find the suspicious line
4. Use `git blame` to find who wrote that line
5. Use `git blame -e` to see email addresses
6. Use `git show` to see the full commit details
7. Document your findings in `investigation.md`
> **Important Notes:**
> - `git blame` shows who last modified each line
> - Each line shows: commit hash, author, date, line number, and content
> - Use `-e` flag to show email addresses
> - Use `-L` to focus on specific line ranges
## Key Concepts
- **Git Blame**: Shows the revision and author who last modified each line of a file
- **Code Archaeology**: Using Git history to understand when and why code changed
- **Author Attribution**: Identifying who wrote specific code for context, not punishment
- **Commit Context**: Understanding the full story behind a change
## Understanding Git Blame Output
When you run `git blame app.py`, you'll see output like this:
```
a1b2c3d4 (John Doe 2024-01-15 10:30:45 +0000 1) # app.py - Main application
a1b2c3d4 (John Doe 2024-01-15 10:30:45 +0000 2)
e5f6g7h8 (Jane Smith 2024-01-16 14:20:10 +0000 3) from auth import login
e5f6g7h8 (Jane Smith 2024-01-16 14:20:10 +0000 4)
i9j0k1l2 (Bob Wilson 2024-01-17 09:15:30 +0000 5) def main():
i9j0k1l2 (Bob Wilson 2024-01-17 09:15:30 +0000 6) login("admin", "admin123")
```
### Breaking It Down
Each line shows:
1. **Commit Hash** (`a1b2c3d4`) - The commit that last changed this line
2. **Author Name** (`John Doe`) - Who made the change
3. **Date/Time** (`2024-01-15 10:30:45 +0000`) - When it was changed
4. **Line Number** (`1`) - The line number in the current file
5. **Line Content** (`# app.py - Main application`) - The actual code
### Useful Git Blame Options
```bash
git blame <file> # Basic blame output
git blame -e <file> # Show email addresses instead of names
git blame -L 10,20 <file> # Only show lines 10-20
git blame -L 10,+5 <file> # Show 5 lines starting from line 10
git blame -w <file> # Ignore whitespace changes
git blame <commit> <file> # Blame as of specific commit
```
### Following Up After Blame
Once you find the commit hash:
```bash
git show <commit-hash> # See the full commit details
git log -p <commit-hash> # See commit with diff
git show <commit-hash> --stat # See which files were changed
```
## When to Use Git Blame
**Good reasons to use `git blame`:**
- 🔍 Understanding why code was written a certain way
- 📚 Finding context for a piece of code
- 🐛 Identifying when a bug was introduced
- 💡 Discovering the thought process behind a decision
- 👥 Finding who to ask about specific code
**Not for blaming:**
- ❌ Finding someone to blame for mistakes
- ❌ Tracking "productivity" or code ownership
- ❌ Punishing developers for old code
**Remember:** Code archaeology is about understanding, not blaming!
## Useful Commands
### Investigation Commands
```bash
# Find who changed each line
git blame <file>
git blame -e <file> # With email addresses
# Focus on specific lines
git blame -L 10,20 <file> # Lines 10-20
git blame -L :function_name <file> # Specific function (Git 2.20+)
# See historical blame
git blame <commit>^ <file> # Blame before a specific commit
# Combine with grep
git blame <file> | grep "pattern" # Find who wrote lines matching pattern
```
### Context Commands
```bash
# See full commit details
git show <commit-hash>
git log -1 <commit-hash> # Just the commit message
# See all commits by author
git log --author="name"
# See what else changed in that commit
git show <commit-hash> --stat
```
## Verification
Once you've completed your investigation in `investigation.md`, verify your solution:
```powershell
.\verify.ps1
```
The verification script will check that you've identified the correct developer.
## Need to Start Over?
If you want to reset the challenge and start fresh:
```powershell
.\reset.ps1
```
This will remove the challenge directory and run the setup script again, giving you a clean slate.

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Resets the Module 05 challenge environment.
.DESCRIPTION
This script removes the challenge directory and re-runs the setup script
to give you a fresh start.
#>
Write-Host "`n=== Resetting Module 05 Challenge ===" -ForegroundColor Cyan
# Remove challenge directory if it exists
if (Test-Path "challenge") {
Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow
Remove-Item -Recurse -Force "challenge"
Write-Host "Challenge directory removed." -ForegroundColor Green
} else {
Write-Host "No challenge directory found to remove." -ForegroundColor Yellow
}
# Run setup script
Write-Host "`nRunning setup script..." -ForegroundColor Cyan
& "./setup.ps1"

View File

@@ -0,0 +1,323 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Sets up the Module 05 challenge environment for git blame investigation.
.DESCRIPTION
This script creates a challenge directory with a Git repository that
contains a security vulnerability (hardcoded credentials) for students
to investigate using git blame.
#>
Write-Host "`n=== Setting up Module 05 Challenge ===" -ForegroundColor Cyan
# Remove existing challenge directory if it exists
if (Test-Path "challenge") {
Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow
Remove-Item -Recurse -Force "challenge"
}
# Create fresh challenge directory
Write-Host "Creating challenge directory..." -ForegroundColor Green
New-Item -ItemType Directory -Path "challenge" | Out-Null
Set-Location "challenge"
# Initialize Git repository
Write-Host "Initializing Git repository..." -ForegroundColor Green
git init | Out-Null
# Commit 1: Initial project structure (by Alice)
Write-Host "Creating initial project structure..." -ForegroundColor Green
git config user.name "Alice Johnson"
git config user.email "alice@example.com"
$appContent = @"
# app.py - Main application file
def main():
print("Welcome to My App!")
# Application initialization code here
pass
if __name__ == "__main__":
main()
"@
Set-Content -Path "app.py" -Value $appContent
git add .
git commit -m "Initial project structure" | Out-Null
# Commit 2: Add authentication module (by Bob)
Write-Host "Adding authentication module..." -ForegroundColor Green
git config user.name "Bob Chen"
git config user.email "bob@example.com"
$authContent = @"
# auth.py - Authentication module
def login(username, password):
# Authenticate user
print(f"Logging in user: {username}")
return True
def logout(username):
# Log out user
print(f"Logging out user: {username}")
return True
"@
Set-Content -Path "auth.py" -Value $authContent
$appContent = @"
# app.py - Main application file
from auth import login, logout
def main():
print("Welcome to My App!")
# Application initialization code here
pass
if __name__ == "__main__":
main()
"@
Set-Content -Path "app.py" -Value $appContent
git add .
git commit -m "Add authentication module" | Out-Null
# Commit 3: Add database connection (by Carol)
Write-Host "Adding database connection..." -ForegroundColor Green
git config user.name "Carol Martinez"
git config user.email "carol@example.com"
$databaseContent = @"
# database.py - Database connection module
def connect():
# Connect to database
print("Connecting to database...")
return True
def disconnect():
# Disconnect from database
print("Disconnecting from database...")
return True
"@
Set-Content -Path "database.py" -Value $databaseContent
$appContent = @"
# app.py - Main application file
from auth import login, logout
from database import connect, disconnect
def main():
print("Welcome to My App!")
connect()
# Application initialization code here
pass
if __name__ == "__main__":
main()
"@
Set-Content -Path "app.py" -Value $appContent
git add .
git commit -m "Add database connection" | Out-Null
# Commit 4: Add hardcoded credentials (THE SECURITY ISSUE - by Suspicious Developer)
Write-Host "Adding suspicious change..." -ForegroundColor Green
git config user.name "Suspicious Developer"
git config user.email "guilty@email.com"
$appContent = @"
# app.py - Main application file
from auth import login, logout
from database import connect, disconnect
def main():
print("Welcome to My App!")
connect()
# Quick fix for testing - TODO: Remove before production!
if login("admin", "admin123"):
print("Admin logged in successfully")
pass
if __name__ == "__main__":
main()
"@
Set-Content -Path "app.py" -Value $appContent
git add .
git commit -m "Add quick test login for debugging" | Out-Null
# Commit 5: Add logging (by David - innocent commit after the security issue)
Write-Host "Adding logging module..." -ForegroundColor Green
git config user.name "David Lee"
git config user.email "david@example.com"
$loggingContent = @"
# logging_config.py - Logging configuration
import logging
def setup_logging():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
return logging.getLogger(__name__)
"@
Set-Content -Path "logging_config.py" -Value $loggingContent
git add .
git commit -m "Add logging configuration" | Out-Null
# Reset git config
git config user.name "Workshop Student"
git config user.email "student@example.com"
# Create investigation.md template
Write-Host "Creating investigation template..." -ForegroundColor Green
$investigationTemplate = @"
# Security Investigation Report
## Incident Overview
A security vulnerability has been discovered in the codebase: hardcoded credentials in `app.py`.
**Your task:** Use git blame and related Git commands to investigate this security issue and document your findings.
---
## Question 1: What line number contains the hardcoded password?
Look at `app.py` and find the line with `"admin123"`.
**Your Answer:**
<!-- Write the line number here -->
---
## Question 2: Who added the hardcoded credentials?
Use `git blame` to find the email address of the developer who wrote the line with the hardcoded credentials.
**Suggested commands:**
``````bash
# View blame with email addresses
git blame -e app.py
# Or focus on specific lines (if you know the line range)
git blame -L 8,10 app.py
# Look for the line containing login("admin", "admin123")
``````
**Your Answer (provide the email address):**
<!-- Write the email address here -->
---
## Question 3: What was the commit message for the change that introduced the hardcoded credentials?
Once you've found the commit hash from git blame, use `git show` or `git log` to see the full commit message.
**Suggested commands:**
``````bash
# After finding the commit hash from git blame
git show <commit-hash>
git log -1 <commit-hash>
``````
**Your Answer:**
<!-- Write the commit message here -->
---
## Question 4: How many files were modified in the commit that added the hardcoded credentials?
Use `git show` with the `--stat` flag to see which files were changed.
**Suggested commands:**
``````bash
git show <commit-hash> --stat
git show <commit-hash> --name-only
``````
**Your Answer:**
<!-- Write the number or list the files here -->
---
## Question 5: When was this security vulnerability introduced?
Use the timestamp from git blame to determine when the vulnerable code was committed.
**Your Answer (date and time):**
<!-- Write the date/time here -->
---
## Recommendations
Based on your investigation, what actions should the team take?
**Your Recommendations:**
<!-- Write your recommendations here, for example:
- Remove hardcoded credentials
- Implement proper environment variables
- Add pre-commit hooks to prevent secrets
- Review with the developer who made the change
-->
---
## Quick Reference - Investigation Commands
**Finding Who Changed What:**
``````bash
git blame <file> # Show who last modified each line
git blame -e <file> # Show with email addresses
git blame -L 10,20 <file> # Blame specific line range
``````
**Getting Commit Details:**
``````bash
git show <commit-hash> # See full commit details
git show <commit-hash> --stat # See files changed
git log -1 <commit-hash> # See commit message only
git log -p <commit-hash> # See commit with diff
``````
**Searching History:**
``````bash
git log --all --grep="keyword" # Search commit messages
git log --author="name" # See commits by author
git log --since="2 weeks ago" # Recent commits
``````
---
When you're done with your investigation, run ``..\verify.ps1`` to check your answers!
"@
Set-Content -Path "investigation.md" -Value $investigationTemplate
# Return to module directory
Set-Location ..
Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green
Write-Host "`nYour investigation environment is ready in the 'challenge/' directory." -ForegroundColor Cyan
Write-Host "`nScenario: Someone committed hardcoded credentials to app.py!" -ForegroundColor Yellow
Write-Host "`nNext steps:" -ForegroundColor Cyan
Write-Host " 1. cd challenge" -ForegroundColor White
Write-Host " 2. Open 'investigation.md' to see the investigation questions" -ForegroundColor White
Write-Host " 3. Use 'git blame -e app.py' to start your investigation" -ForegroundColor White
Write-Host " 4. Fill in your findings in 'investigation.md'" -ForegroundColor White
Write-Host " 5. Run '..\verify.ps1' to check your investigation" -ForegroundColor White
Write-Host ""

View File

@@ -0,0 +1,114 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Verifies the Module 05 challenge solution.
.DESCRIPTION
This script checks that:
- The challenge directory exists
- A Git repository exists
- investigation.md exists with correct findings about the security issue
#>
Write-Host "`n=== Verifying Module 05 Solution ===" -ForegroundColor Cyan
$allChecksPassed = $true
# Check if challenge directory exists
if (-not (Test-Path "challenge")) {
Write-Host "[FAIL] Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red
exit 1
}
Set-Location "challenge"
# Check if git repository exists
if (-not (Test-Path ".git")) {
Write-Host "[FAIL] Not a git repository. Did you run setup.ps1?" -ForegroundColor Red
Set-Location ..
exit 1
}
# Check if investigation.md exists
if (-not (Test-Path "investigation.md")) {
Write-Host "[FAIL] investigation.md not found. Did you run setup.ps1?" -ForegroundColor Red
Write-Host "[HINT] The setup script should have created investigation.md for you" -ForegroundColor Yellow
$allChecksPassed = $false
} else {
Write-Host "[PASS] investigation.md exists" -ForegroundColor Green
# Read the investigation file
$investigation = Get-Content "investigation.md" -Raw
$investigationLower = $investigation.ToLower()
# Check 1: Line number (line 8 contains the hardcoded password)
if ($investigationLower -match "8") {
Write-Host "[PASS] Correct line number identified" -ForegroundColor Green
} else {
Write-Host "[FAIL] Line number not found or incorrect" -ForegroundColor Red
Write-Host "[HINT] Look at app.py to find which line contains 'admin123'" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check 2: Email address (guilty@email.com)
if ($investigationLower -match "guilty@email\.com") {
Write-Host "[PASS] Correct email address found using git blame!" -ForegroundColor Green
} else {
Write-Host "[FAIL] Developer's email address not found" -ForegroundColor Red
Write-Host "[HINT] Use 'git blame -e app.py' to see who changed each line with email addresses" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check 3: Commit message (contains "test" or "debug" or "quick")
if ($investigationLower -match "test|debug|quick") {
Write-Host "[PASS] Commit message identified" -ForegroundColor Green
} else {
Write-Host "[FAIL] Commit message not found" -ForegroundColor Red
Write-Host "[HINT] Use 'git show <commit-hash>' to see the commit message" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check 4: Number of files (1 file - only app.py)
if ($investigationLower -match "1|one|app\.py") {
Write-Host "[PASS] Number of files modified identified" -ForegroundColor Green
} else {
Write-Host "[FAIL] Number of files modified not found" -ForegroundColor Red
Write-Host "[HINT] Use 'git show <commit-hash> --stat' to see which files were changed" -ForegroundColor Yellow
$allChecksPassed = $false
}
# Check 5: Some mention of timestamp/date (flexible check)
# We're just checking they attempted to answer this
if ($investigationLower -match "202|date|time|\d{4}-\d{2}-\d{2}") {
Write-Host "[PASS] Timestamp/date documented" -ForegroundColor Green
} else {
Write-Host "[FAIL] Timestamp/date not documented" -ForegroundColor Red
Write-Host "[HINT] The git blame output shows the date and time of each change" -ForegroundColor Yellow
$allChecksPassed = $false
}
}
Set-Location ..
# Final summary
if ($allChecksPassed) {
Write-Host "`n" -NoNewline
Write-Host "=====================================" -ForegroundColor Green
Write-Host " INVESTIGATION COMPLETE!" -ForegroundColor Green
Write-Host "=====================================" -ForegroundColor Green
Write-Host "`nExcellent detective work! You've successfully used git blame to track down the security issue." -ForegroundColor Cyan
Write-Host "`nYou now know how to:" -ForegroundColor Cyan
Write-Host " - Use git blame to find who modified each line" -ForegroundColor White
Write-Host " - Read and interpret git blame output" -ForegroundColor White
Write-Host " - Use git blame with -e flag to show email addresses" -ForegroundColor White
Write-Host " - Find commit details after identifying changes with blame" -ForegroundColor White
Write-Host " - Conduct code archaeology to understand code history" -ForegroundColor White
Write-Host "`nRemember: git blame is for understanding, not blaming!" -ForegroundColor Yellow
Write-Host "`nReady for the next module!" -ForegroundColor Green
Write-Host ""
} else {
Write-Host "`n[SUMMARY] Some checks failed. Review the hints above and try again." -ForegroundColor Red
Write-Host "[INFO] You can run this verification script as many times as needed." -ForegroundColor Yellow
Write-Host ""
exit 1
}

493
GIT-CHEATSHEET.md Normal file
View File

@@ -0,0 +1,493 @@
# Git Command Cheatsheet
A comprehensive reference for all Git commands covered in this workshop.
---
## Essentials
### Repository Initialization
```bash
git init
```
Initialize a new Git repository in the current directory.
### Staging & Committing
```bash
git status
```
Show the current state of your working directory and staging area.
```bash
git add <file>
```
Add a file to the staging area (prepare it for commit).
```bash
git add .
```
Add all changed files in the current directory to the staging area.
```bash
git commit -m "message"
```
Create a new commit with the staged changes and a descriptive message.
```bash
git commit -am "message"
```
Stage all modified tracked files and commit in one step (doesn't include new files).
### Viewing History
```bash
git log
```
Show the commit history for the current branch.
```bash
git log --oneline
```
Show commit history in compact one-line format.
```bash
git log --oneline --graph --all
```
Show commit history as a graph with all branches.
```bash
git log --stat
```
Show commit history with statistics about which files changed.
```bash
git show <commit>
```
Display detailed information about a specific commit.
```bash
git show <commit>:<file>
```
View the contents of a file from a specific commit.
### Comparing Changes
```bash
git diff
```
Show unstaged changes in your working directory.
```bash
git diff --staged
```
Show staged changes (what will be committed).
```bash
git diff <commit1> <commit2>
```
Compare two commits.
```bash
git diff <commit1> <commit2> <file>
```
Compare changes to a specific file between two commits.
**Understanding diff output:**
- Lines with `+` (green) = added
- Lines with `-` (red) = removed
- Lines with ` ` (space) = unchanged (context)
- `@@ -1,5 +1,7 @@` = location of changes (old line/count, new line/count)
For a detailed guide on reading diff output, see Module 02 README.md.
### Branching
```bash
git branch
```
List all local branches (current branch marked with *).
```bash
git branch <branch-name>
```
Create a new branch.
```bash
git branch -d <branch-name>
```
Delete a branch (only if it's been merged).
```bash
git branch -D <branch-name>
```
Force delete a branch (even if not merged).
```bash
git switch <branch-name>
```
Switch to a different branch.
```bash
git switch -c <branch-name>
```
Create a new branch and switch to it in one command.
```bash
git switch -
```
Switch back to the previous branch.
### Merging
```bash
git merge <branch-name>
```
Merge the specified branch into your current branch.
```bash
git merge --abort
```
Abort a merge in progress and return to the pre-merge state.
### Merge Conflict Resolution
```bash
git status
```
During a merge conflict, shows which files have conflicts.
```bash
# After resolving conflicts manually:
git add <resolved-file>
git commit
```
Stage resolved files and complete the merge.
### Restoring Files
```bash
git restore <file>
```
Discard changes in working directory (restore from last commit).
```bash
git restore --staged <file>
```
Unstage a file (remove from staging area but keep changes).
```bash
git restore --source=<commit> <file>
```
Restore a file to its state in a specific commit.
---
## Advanced
### Rebasing
```bash
git rebase <branch>
```
Reapply your commits on top of another branch (creates linear history).
```bash
git rebase -i <commit>
```
Interactive rebase - edit, reorder, squash, or drop commits.
```bash
git rebase --continue
```
Continue rebasing after resolving conflicts.
```bash
git rebase --abort
```
Abort a rebase and return to the original state.
### Reset (History Manipulation)
```bash
git reset --soft HEAD~<n>
```
Undo last n commits but keep changes staged.
```bash
git reset --mixed HEAD~<n>
```
Undo last n commits and unstage changes (default mode).
```bash
git reset --hard HEAD~<n>
```
Undo last n commits and discard all changes (DESTRUCTIVE).
```bash
git reset --hard <commit>
```
Reset your branch to a specific commit, discarding all changes.
### Revert (Safe Undo)
```bash
git revert <commit>
```
Create a new commit that undoes changes from a specific commit (safe for shared branches).
```bash
git revert --no-commit <commit>
```
Revert changes but don't create the commit yet (allows editing).
```bash
git revert --abort
```
Abort a revert in progress.
### Cherry-Pick
```bash
git cherry-pick <commit>
```
Apply the changes from a specific commit to your current branch.
```bash
git cherry-pick <commit1> <commit2> <commit3>
```
Cherry-pick multiple commits.
```bash
git cherry-pick --continue
```
Continue cherry-picking after resolving conflicts.
```bash
git cherry-pick --abort
```
Abort a cherry-pick in progress.
### Stash (Temporary Storage)
```bash
git stash
```
Save your uncommitted changes temporarily and revert to a clean working directory.
```bash
git stash save "description"
```
Stash changes with a descriptive message.
```bash
git stash list
```
Show all stashed changes.
```bash
git stash pop
```
Apply the most recent stash and remove it from the stash list.
```bash
git stash apply
```
Apply the most recent stash but keep it in the stash list.
```bash
git stash apply stash@{n}
```
Apply a specific stash by index.
```bash
git stash drop
```
Delete the most recent stash.
```bash
git stash drop stash@{n}
```
Delete a specific stash.
```bash
git stash clear
```
Delete all stashes.
### Working with Remotes
```bash
git clone <url>
```
Create a local copy of a remote repository.
```bash
git remote
```
List all remote repositories.
```bash
git remote -v
```
List all remote repositories with their URLs.
```bash
git remote add <name> <url>
```
Add a new remote repository.
```bash
git remote remove <name>
```
Remove a remote repository.
```bash
git fetch <remote>
```
Download changes from remote but don't merge them.
```bash
git pull <remote> <branch>
```
Fetch and merge changes from remote branch to current branch.
```bash
git pull
```
Fetch and merge from the tracked remote branch.
```bash
git push <remote> <branch>
```
Upload your commits to a remote branch.
```bash
git push -u <remote> <branch>
```
Push and set up tracking relationship (use -u first time pushing a branch).
```bash
git push
```
Push to the tracked remote branch.
### Worktrees (Multiple Working Directories)
```bash
git worktree add <path> <branch>
```
Create a new working directory linked to your repository for a specific branch.
```bash
git worktree add <path> -b <new-branch>
```
Create a new branch and working directory for it.
```bash
git worktree list
```
Show all worktrees associated with the repository.
```bash
git worktree remove <path>
```
Remove a worktree.
```bash
git worktree prune
```
Clean up stale worktree administrative data.
### Bisect (Binary Search for Bugs)
```bash
git bisect start
```
Start a bisect session to find which commit introduced a bug.
```bash
git bisect bad
```
Mark the current commit as bad (contains the bug).
```bash
git bisect good <commit>
```
Mark a commit as good (doesn't contain the bug).
```bash
git bisect reset
```
End the bisect session and return to the original branch.
```bash
git bisect run <script>
```
Automatically test commits using a script to find the bad commit.
---
## Useful Tips
### Viewing Changes
- Use `git log --oneline --graph --all` to visualize branch structure
- Use `git log -p` to show the actual changes (patch) in each commit
- Use `git log --author="name"` to filter commits by author
- Use `git log --since="2 weeks ago"` to filter commits by date
### Undoing Changes
- **Haven't committed yet?** Use `git restore <file>` to discard changes
- **Staged but want to unstage?** Use `git restore --staged <file>`
- **Committed to wrong branch?** Use `git cherry-pick` to copy the commit to the right branch
- **Want to change last commit message?** Use `git commit --amend`
- **Pushed to remote already?** Use `git revert` (not reset) to safely undo
### Best Practices
- Commit often with clear, descriptive messages
- Pull before you push to avoid conflicts
- Use branches for new features or experiments
- Don't rebase or reset commits that have been pushed to shared branches
- Use `git stash` when you need to switch contexts quickly
- Test your changes before committing
### Getting Help
```bash
git help <command>
```
Show detailed help for any Git command.
```bash
git <command> --help
```
Alternative way to show help.
```bash
git <command> -h
```
Show brief usage summary.
---
## Module Reference
Each workshop module focuses on specific commands:
- **Module 01**: init, add, commit, status
- **Module 02**: log, show, diff
- **Module 03**: branch, switch
- **Module 04**: merge (fast-forward and three-way)
- **Module 05**: merge (conflict resolution)
- **Module 06**: rebase
- **Module 07**: reset (interactive rebase alternative)
- **Module 08**: cherry-pick
- **Module 09**: reset vs revert
- **Module 10**: stash
- **Module 11**: clone, remote, push, pull, fetch
- **Module 12**: worktree
- **Module 13**: bisect

186
README.md
View File

@@ -1,22 +1,31 @@
# Git Workshop
A hands-on, progressive git workshop with practical challenges ranging from basic to advanced concepts.
A comprehensive, hands-on Git workshop with 13 progressive modules covering everything from basic commits to advanced debugging techniques. Each module presents a real-world scenario that you must solve using Git commands, with automated verification to confirm your solution.
Perfect for developers who want to move beyond basic Git usage and master professional workflows including rebasing, conflict resolution, bisecting, worktrees, and more.
## Workshop Structure
Each module is a self-contained challenge that teaches specific git concepts:
- **Module 01**: Git Basics (init, add, commit, status)
- **Module 02**: Viewing History (log, diff)
- **Module 03**: Branching Basics
- **Module 04**: Merging
- **Module 05**: Merge Conflicts
- **Module 06**: Rebasing
- **Module 07**: Interactive Rebase
- **Module 08**: Cherry-pick
- **Module 09**: Reset vs Revert
- **Module 10**: Stash
- **Module 11**: Working with Remotes
### Beginner Level
- **Module 01**: Git Basics - Initialize repositories, stage changes, make commits
- **Module 02**: Viewing History - Use git log and git diff to explore project history
- **Module 03**: Branching Basics - Create, switch, and manage branches
### Intermediate Level
- **Module 04**: Merging - Combine branches with fast-forward and three-way merges
- **Module 05**: Merge Conflicts - Identify, understand, and resolve merge conflicts
- **Module 06**: Rebasing - Rebase branches to create linear history
- **Module 07**: Interactive Rebase - Clean up commit history with reset and recommit
- **Module 08**: Cherry-Pick - Apply specific commits from one branch to another
### Advanced Level
- **Module 09**: Reset vs Revert - Understand when to rewrite history vs create new commits
- **Module 10**: Stash - Temporarily save work without committing
- **Module 11**: Working with Remotes - Clone, push, pull, and fetch from remote repositories
- **Module 12**: Worktrees - Work on multiple branches simultaneously
- **Module 13**: Bisect - Use binary search to find bugs in commit history
## How to Use This Workshop
@@ -27,11 +36,94 @@ Each module is a self-contained challenge that teaches specific git concepts:
5. Run `./verify.ps1` to check if you've solved it correctly
6. Move to the next module
**Quick Reference**: See [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) for a comprehensive list of all Git commands covered in this workshop. Don't worry about memorizing everything - use this as a reference when you need to look up command syntax!
## Running PowerShell Scripts
Each module includes setup, verification, and reset scripts. Here's how to run them:
### Windows
If you encounter an "execution policy" error when running scripts, open PowerShell as Administrator and run:
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
Then run scripts using:
```powershell
.\setup.ps1
```
### macOS/Linux
First, make sure scripts are executable (only needed once):
```bash
chmod +x module-*/setup.ps1 module-*/verify.ps1 module-*/reset.ps1
```
Then run scripts using:
```bash
./setup.ps1
```
Or explicitly with PowerShell:
```bash
pwsh setup.ps1
```
**Note:** All examples in this workshop use Windows syntax (`.\script.ps1`). macOS/Linux users should use `./script.ps1` instead.
## Requirements
- Git installed and configured
- PowerShell (Windows PowerShell 5.1+ or PowerShell Core 7+)
- Basic command line knowledge
### Git
You need Git version 2.23 or later (for `git switch` and `git restore` commands).
**Check if Git is installed:**
```powershell
git --version
```
If you see a version number (e.g., "git version 2.34.1"), you're all set!
If not, download and install from: https://git-scm.com/downloads
**Configure Git (Required - First Time Only):**
Before making your first commit, tell Git who you are:
```powershell
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
```
**Verify your configuration:**
```powershell
git config --global user.name
git config --global user.email
```
You should see your name and email printed. This is required to make commits in Git.
### PowerShell
- **Windows**: PowerShell 5.1+ (already included in Windows 10/11)
- **macOS/Linux**: Install PowerShell Core 7+ from https://github.com/PowerShell/PowerShell
**Check PowerShell version:**
```powershell
$PSVersionTable.PSVersion
```
### Basic Command Line Knowledge
You should know how to:
- Navigate directories (`cd`, `ls` or `dir`)
- See your current location (`pwd`)
- Read text files (`cat` or `type`)
Don't worry if you're not an expert - we'll guide you through each step!
## Optional: Install Glow for Pretty Markdown
@@ -55,6 +147,22 @@ After installation, read markdown files with:
Without glow, you can still read markdown files with any text editor or `cat README.md`.
## Common Git Terms
New to Git? Here are the key terms you'll encounter:
- **Repository (or "repo")**: A project folder tracked by Git, containing your files and their complete history
- **Commit**: A snapshot of your project at a specific point in time (like a save point in a video game)
- **Staging Area (or "Index")**: A preparation area where you select which changes to include in your next commit
- **Working Directory**: The actual files you see and edit on your computer
- **Branch**: An independent line of development (like a parallel universe for your code)
- **HEAD**: A pointer showing which commit you're currently working from
- **main/master**: The primary branch in a repository (main is the modern convention)
- **Merge**: Combining changes from different branches
- **Remote**: A version of your repository hosted elsewhere (like GitHub)
Don't worry if these don't make sense yet - you'll learn them hands-on as you progress!
## Getting Started
Start with Module 01:
@@ -66,6 +174,54 @@ cd module-01-basics
Follow the instructions in each module's README.md file.
## What Makes This Workshop Different
- **Hands-On Practice**: Each module creates a real Git scenario you must solve
- **Automated Verification**: Scripts check your solution instantly
- **Progressive Difficulty**: Builds from basics to advanced Git techniques
- **Reset Anytime**: Each module includes a reset script for a fresh start
- **Self-Paced**: Learn at your own speed with detailed README guides
- **No Internet Required**: All modules work offline with local repositories
## Learning Path
The modules are designed to build on each other:
1. **Start Here** (Modules 1-3): Core Git fundamentals everyone needs
2. **Collaboration** (Modules 4-5): Working with branches and resolving conflicts
3. **History Management** (Modules 6-8): Rewriting and organizing commits
4. **Advanced Workflows** (Modules 9-11): Professional Git techniques
5. **Power User** (Modules 12-13): Advanced tools for productivity and debugging
## Tips for Success
- Don't skip modules - each builds on previous concepts
- Read the README.md thoroughly before starting each challenge
- Keep [GIT-CHEATSHEET.md](GIT-CHEATSHEET.md) open as a quick reference
- Experiment freely - you can always run `./reset.ps1` to start over
- Use `git log --oneline --graph --all` frequently to visualize repository state
- If stuck, check the Key Concepts section in the module's README
- Consider installing glow for better markdown reading experience
## Skills You'll Master
By completing this workshop, you'll be able to:
- ✅ Create and manage Git repositories with confidence
- ✅ Navigate project history and understand what changed when
- ✅ Use branches effectively for parallel development
- ✅ Merge branches and resolve conflicts like a pro
- ✅ Rebase to maintain clean, linear history
- ✅ Clean up messy commits before submitting pull requests
- ✅ Cherry-pick specific commits across branches
- ✅ Choose correctly between reset and revert
- ✅ Use stash to manage work-in-progress without commits
- ✅ Collaborate effectively with remote repositories
- ✅ Work on multiple branches simultaneously with worktrees
- ✅ Debug efficiently by finding bug-introducing commits with bisect
These are professional-level Git skills used daily by developers at top tech companies.
## For Workshop Facilitators
Before distributing this workshop to attendees:

View File

@@ -1,84 +0,0 @@
# Module 02: Viewing History
## Learning Objectives
In this module, you will:
- Understand commit history and how to navigate it
- Use `git log` to view commit history with various formats
- Use `git show` to view specific commit details
- Use `git diff` to compare changes between commits
- Understand commit hashes and references
## Challenge
### Setup
Run the setup script to create your challenge environment:
```powershell
.\setup.ps1
```
This will create a `challenge/` directory with a Git repository that already has some commit history.
### Your Task
You'll explore an existing Git repository that contains multiple commits. Your goal is to use Git commands to discover information about the repository's history.
The setup script will create an `answers.md` file in the challenge directory with questions for you to answer. Fill in your answers directly in that file.
**Suggested Approach:**
1. Navigate to the challenge directory: `cd challenge`
2. Open `answers.md` to see the questions
3. View the commit history: `git log`
4. Try different log formats: `git log --oneline`, `git log --stat`
5. View specific commits: `git show <commit-hash>`
6. Compare commits: `git diff <commit1> <commit2>`
7. Fill in your answers in `answers.md`
> **Important Notes:**
> - You can use any Git commands you like to explore the repository
> - Fill in your answers directly in the `answers.md` file (there are placeholder sections for each answer)
> - Try different `git log` options to see which format you prefer
> - Commit hashes can be referenced by their full hash or just the first 7 characters
## Key Concepts
- **Commit Hash**: A unique identifier (SHA-1 hash) for each commit. You can use the full hash or just the first few characters.
- **Commit Message**: A description of what changed in that commit, written by the author.
- **Commit History**: The chronological record of all changes made to a repository.
- **HEAD**: A pointer to the current commit you're working from.
## Useful Commands
```bash
git log # View commit history
git log --oneline # Compact one-line format
git log --stat # Show files changed in each commit
git log --graph # Show branch graph (more useful with branches)
git show <commit> # View specific commit details
git show <commit>:<file> # View a file from a specific commit
git diff <commit1> <commit2> # Compare two commits
git diff <commit> # Compare commit with current working directory
```
## Verification
Once you've filled in your answers in `answers.md`, verify your solution:
```powershell
.\verify.ps1
```
The verification script will check that your answers contain the expected information.
## Need to Start Over?
If you want to reset the challenge and start fresh:
```powershell
.\reset.ps1
```
This will remove the challenge directory and run the setup script again, giving you a clean slate.