Compare commits
10 Commits
f11f5a4646
...
6b0e84934a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b0e84934a | ||
|
|
30b878fc67 | ||
|
|
aefcfbe100 | ||
|
|
5f8091d5b2 | ||
|
|
cf073d569e | ||
|
|
d7c146975d | ||
|
|
dc94520b2a | ||
|
|
e29b9bca70 | ||
|
|
a7b511c8cb | ||
|
|
a8eb66d3c9 |
@@ -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:
|
||||
225
01_essentials/02-history/README.md
Normal file
225
01_essentials/02-history/README.md
Normal 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.
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
@@ -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`
|
||||
@@ -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>
|
||||
```
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -86,7 +86,7 @@ git rebase --abort
|
||||
git branch
|
||||
|
||||
# Switch to a branch
|
||||
git checkout <branch-name>
|
||||
git switch <branch-name>
|
||||
```
|
||||
|
||||
## Verification
|
||||
169
03_advanced/05-blame/README.md
Normal file
169
03_advanced/05-blame/README.md
Normal 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.
|
||||
24
03_advanced/05-blame/reset.ps1
Normal file
24
03_advanced/05-blame/reset.ps1
Normal 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"
|
||||
323
03_advanced/05-blame/setup.ps1
Normal file
323
03_advanced/05-blame/setup.ps1
Normal 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 ""
|
||||
114
03_advanced/05-blame/verify.ps1
Normal file
114
03_advanced/05-blame/verify.ps1
Normal 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
493
GIT-CHEATSHEET.md
Normal 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
186
README.md
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user