Home
Git EscapeRoom Labs
🔀 Git Escape Room
Learn Git from Zero to Hero through 50 Interactive Puzzle Rooms

Decryption Tip
If the content doesn’t appear after entering the password in the selected room, please refresh the page (F5 or Ctrl+R).
Usage
- There are several ways to run the Git-EscapeRoom Labs.
- Choose the method that works best for you.
Using Docker is the easiest way to get started locally with the labs:
# GitHub Container Registry
docker run -it --pull=always -p 3000:3000 ghcr.io/nirgeier/git-escaperoom
Prerequisites:
- Docker and Docker Compose installed on your system
- No additional setup required
- The easiest way to get started with the labs
- Learn in your browser without any local installation
Benefits:
- No installation required
- Pre-configured environment
- Works on any device with a web browser
- All tools pre-installed
For those who prefer to run it directly on their machine:
# Clone the repository
git clone https://github.com/nirgeier/Git-EscapeRoom
# Change to the Labs directory
cd Git-EscapeRoom/Labs
# Start with the setup lab
cd assets
# Follow the instructions in the README of each lab
cat README.md
Prerequisites:
- A Unix-like operating system (Linux, macOS, or Windows with WSL)
- Basic command-line tools
- Google Cloud Shell provides a free, browser-based environment with all necessary tools pre-installed.
- Click on the
Open in Google Cloud Shellbutton below:
- The repository will automatically be cloned into a free Cloud instance.
- Use CTRL + click to open it in a new window.
- Follow the instructions in the README of each lab.
Benefits:
- No local installation required
- Pre-configured environment
- Works on any device with a web browser
- All tools pre-installed
- Free tier available
Intro
- This tutorial teaches Git through puzzles designed as escape rooms.
- Each room covers a different Git concept - from basic installation to plumbing commands and internals.
- Every room folder includes a
READMEthat describes the room’s objectives, hints, rules, and how to verify the solution. - The Git Escape Room is a series of Git puzzles (Escape-rooms, similar to the real-life attractions).
- The puzzles are designed to teach players Git skills & features from beginner to expert level.
Pre-Requirements
- This tutorial will test your
GitandLinuxskills. - You should be familiar with the following topics:
- Basic Linux commands and shell navigation
- Basic knowledge of a text editor (vim, nano, etc.)
- Basic knowledge of
Docker(if you choose to run it with Docker)
Room Links
| # | Room | Summary |
|---|---|---|
| 01 | Install & Verify Git | Check if Git is installed, explore its binary location and sub-commands |
| 02 | Git Configuration | Configure Git identity, editor, and preferences with git config |
| 03 | Git Init | Initialize a repository and explore the .git directory structure |
| 04 | The Three States of Git | Understand Git’s three areas: Working Directory, Staging Area, and Repository |
| 05 | Git Add: Staging Deep Dive | Master git add with patterns, patches, and interactive staging |
| 06 | Git Status & Restore | Read git status output and use git restore to manage file states |
| 07 | Git Commit: Saving Snapshots | Create commits, write good messages, and use git commit options |
| 08 | Git Log: Exploring History | Navigate commit history with git log formats, filters, and search |
| 09 | Git Diff: Comparing Changes | Compare changes with git diff between working dir, staging, and commits |
| 10 | Git Branch: Parallel Universes | Create, switch, list, and manage branches with git branch and git switch |
| 11 | Git Merge: Bringing Branches Together | Combine branches with git merge, fast-forward and three-way merges |
| 12 | Merge Conflicts | Resolve merge conflicts by editing conflict markers and completing the merge |
| 13 | Git Rebase: Linear History | Rewrite history with git rebase and interactive rebase for clean timelines |
| 14 | Git Stash: Emergency Shelf | Save and restore work-in-progress with git stash |
| 15 | Git Remote: Connecting to the World | Manage remote repositories with git remote - add, rename, remove |
| 16 | Git Clone: Copying Repositories | Clone repositories with depth, branch, and bare options |
| 17 | Git Fetch: Download Without Merging | Download remote changes without merging using git fetch |
| 18 | Git Pull: Fetch + Merge | Fetch and integrate remote changes with git pull and pull strategies |
| 19 | Git Push: Sharing Your Work | Share commits with git push, set upstream, and manage remote branches |
| 20 | Git Tag: Marking Milestones | Mark releases and milestones with lightweight and annotated tags |
| 21 | Git Cherry-Pick: Selective Commits | Pick specific commits from other branches and apply them |
| 22 | Git Reset: Rewinding History | Rewind history with git reset - soft, mixed, and hard modes |
| 23 | Git Revert: Safe Undo | Safely undo commits by creating a new reverting commit |
| 24 | Git Commit –Amend: Fixing Mistakes | Fix the last commit - change message, add files, or update content |
| 25 | Git Blame: Line-by-Line Detective | Track down who changed what and when - line-by-line attribution |
| 26 | Git Bisect: Bug Hunting | Binary search through history to find the commit that introduced a bug |
| 27 | Git Reflog: Your Safety Net | Recover lost commits, branches, and undone work from the reflog |
| 28 | Git Alias: Custom Shortcuts | Create shortcuts for your most-used Git commands |
| 29 | Gitignore: Hiding Files from Git | Keep unwanted files out of your repo with .gitignore patterns |
| 30 | Gitattributes: File-Level Rules | Control line endings, diff behavior, and merge strategies |
| 31 | Git Hooks: Automation Triggers | Automate workflows with scripts that run at key Git lifecycle points |
| 32 | Git Submodule: Repos Within Repos | Embed external repositories inside your project as submodules |
| 33 | Git Worktree: Parallel Branches | Work on multiple branches simultaneously without stashing |
| 34 | Git Sparse-Checkout: Partial Repos | Clone only the parts of a repo you need |
| 35 | Git Assume-Unchanged: Hiding Local Edits | Tell Git to ignore local changes to tracked files |
| 36 | Git Clean: Remove Untracked Files | Remove untracked files and directories from your working tree |
| 37 | Git Archive: Export Without .git | Export a snapshot of your repository without the .git directory |
| 38 | Git Bundle: Offline Transfer | Transfer repositories offline using Git bundles |
| 39 | Git Format-Patch & Am: Email Patches | Create and apply patches for email-based collaboration |
| 40 | Git Grep: Search Tracked Files | Search through tracked files and commit history |
| 41 | Git Shortlog: Contributor Stats | Summarize commit activity by contributor |
| 42 | Git Describe: Human-Readable Names | Get human-readable names for commits based on nearby tags |
| 43 | Git Notes: Commit Metadata | Attach extra metadata to commits without changing their hashes |
| 44 | Git Replace: Transparent Object Swap | Transparently swap Git objects to rewrite history |
| 45 | Git Filter-Branch & Filter-Repo | Rewrite entire repository history - the nuclear option |
| 46 | Git Rerere: Reuse Recorded Resolution | Let Git remember and reuse conflict resolutions |
| 47 | Git Fsck: Filesystem Check | Check the integrity of your Git repository |
| 48 | Git GC: Garbage Collection | Optimize your repository by cleaning up and compressing objects |
| 49 | Git Plumbing Commands: Internals | Peek under the hood with Git’s low-level plumbing commands |
| 50 | Git Object Model: The Four Objects | Understand the four fundamental Git objects that power everything |
| 99 | The Final Exam | The grand escape - prove your Git mastery! |
Room 01 - Install & Verify Git
INSTALL & VERIFY GIT
Room 01 - Installing Git
- Git is a distributed version control system created by Linus Torvalds in 2005.
- Before you can use Git, you need to make sure it’s installed and working.
📜 Your mission
Your first mission: Confirm Git is installed and discover its secrets.
-
Run:
git --versionVerify that git is installed -
Run:
which gitThis shows you where git in called from. -
Find the password:
- Look inside the “room01” git repository in this room.
- The password is hidden in the commit history.
- Hint: use
git logto reveal it.
Decrypt the next room:
next <PASSWORD>
Key Commands
| Command | Purpose |
|---|---|
git --version |
Show installed Git version |
which git |
Show path to git binary |
git --exec-path |
Show Git’s libexec directory |
git help |
List common Git commands |
git help -a |
List ALL available Git commands |
git help <command> |
Show help for specific command |
man git |
Manual page for Git |
Installing Git on Different Systems
# macOS (Homebrew)
brew install git
# Ubuntu/Debian
sudo apt-get update && sudo apt-get install git
# Fedora/RHEL
sudo dnf install git
# Arch
sudo pacman -S git
# Alpine (this container)
apk add git
# Windows
# Download from https://git-scm.com/downloads
# Or use: winget install Git.Git
# Verify installation
git --version
How Git Differs From Other VCS
mermaid
flowchart TB
subgraph Centralized["Centralized VCS - SVN"]
S["🖥️ Server"] --> D1["Dev1\n(working copy)"]
S --> D2["Dev2\n(working copy)"]
S --> D3["Dev3\n(working copy)"]
end
subgraph Distributed["Distributed VCS - Git"]
R["🌐 Remote A"] <--> G1["Dev1\n(full repo)"]
R <--> G2["Dev2\n(full repo)"]
R <--> G3["Dev3\n(full repo)"]
G1 <--> G2
G2 <--> G3
end
Tasks
01. Verify Git Is Installed
The very first thing to check on any machine - is Git actually available?
Hint: git --version
Solution
02. Locate the Git Binary
Find where the git executable lives on this system.
Hint: which git, type git
Solution
03. Explore Git’s Built-in Help
Git ships with built-in documentation. List the most common Git commands.
Hint: git help, git help -a
Solution
04. Find the Git Libexec Directory
Git stores helper programs in a special libexec directory. Find its path.
Hint: git --exec-path
Solution
05. Explore the room01 Repo
This room contains a room01 git repository. Enter it and look around.
Hint: cd room01, ls -la, git status
Solution
06. Read the Commit History
The password is hidden in the commit messages of the room01 repo. Use the log to find it.
Hint: git log, git log --oneline
Solution
07. Show a Specific Commit’s Details
Once you spot an interesting commit, inspect its full details.
Hint: git show <hash>
Solution
[Protected] Room 02 - Git Configuration
GIT CONFIGURATION
Room 02 - git config: Your Identity
- Git needs to know who you are before you can make commits.
- Configuration exists at three levels: system, global, and local.
- Your identity is everything in Git.
- Every commit you make is stamped with your name and email.
- Without configuring these, Git will complain or use defaults that won’t represent you properly.
📜 Your mission
- Set your name:
- Set your email:
- List all configuration:
-
Add a custom list alias:
-
Find the password:
- This room is a git repository.
- The password is hidden in the local git configuration (
.git/config).
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git config --global user.name "Name" |
Set your name |
git config --global user.email "email" |
Set your email |
git config --list |
List all settings |
git config --list --show-origin |
Show where each setting comes from |
git config --global core.editor vim |
Set default editor |
git config --global init.defaultBranch main |
Set default branch name |
git config --unset user.name |
Remove a setting |
The Three Config Levels
- Git configuration lives at three levels (each overrides the one above):
| Scope | Location | Description |
|---|---|---|
--system |
/etc/gitconfig |
Applies to ALL users on this machine |
--global |
~/.gitconfig |
Applies to YOUR user across all repos |
--local |
.git/config |
Applies only to the CURRENT repository |
- Priority: System -> Global -> Local
- Local is the default if no scope is defined
- System config is stored in a central location for all users
- Global config is stored in the user’s home directory
- Local config is stored in the
.gitfolder of the repository
# View each level separately
git config --system --list
git config --global --list
git config --local --list
# Common useful settings
git config --global color.ui auto # Colored output
git config --global pull.rebase true # Rebase on pull
git config --global core.autocrlf input # Line endings (macOS/Linux)
git config --global alias.st status # Create shortcuts
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
Tasks
01. Set Your Name
Every commit is stamped with the author’s name. Configure yours.
Hint: git config --global user.name
Solution
02. Set Your Email
The email is required for commit attribution and is public in most repos.
Hint: git config --global user.email
Solution
03. List All Configuration
See every setting Git is currently using - from all three levels combined.
Hint: git config --list
Solution
04. View Each Config Level Separately
Understand which settings live at system, global, and local scope.
Hint: git config --system --list, git config --global --list, git config --local --list
Solution
05. Set a Default Editor
Configure which editor opens when Git needs input (commit messages, rebase, etc.).
Hint: git config --global core.editor
Solution
06. Create Useful Aliases
Aliases let you create shortcuts for frequently used commands.
Hint: git config --global alias.<name> "<command>"
Solution
07. Remove a Configuration Setting
Clean up a setting you no longer need.
Hint: git config --unset
Solution
08. Find the Password in Local Config
This room folder is itself a git repo. The password is hiding in its local configuration.
Hint: git config --local --list
Solution
[Protected] Room 03 - Git Init
GIT INIT
Room 03 - Creating Your First Repository
git inittransforms a regular directory into a Git repository.- It creates a hidden
.git/directory that stores ALL version control data.
📜 Your mission
Every journey starts with git init.
-
Create a new directory called
my-project:mkdir my-project && cd my-project
-
Initialize it as a git repository:
git init
-
Explore what git created:
ls -la .git/
-
Look inside the .git directory structure:
tree .git/(orfind .git/ -type f)
-
Read the HEAD file:
cat .git/HEAD
-
What does HEAD point to? It references
refs/heads/<default-branch>, which is the default branch name (oftenmainormaster). This is the CURRENT branch pointer. -
The CURRENT branch is the password for the next room. Use it to unlock the next challenge:
next <HEAD content>
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git init |
Initialize new repository |
git init --bare |
Initialize bare repository (no working dir) |
git init --initial-branch=main |
Init with custom branch name |
ls -la .git/ |
Explore repository internals |
cat .git/HEAD |
See what HEAD points to |
cat .git/config |
View repo-local configuration |
The .git Directory Structure
.git/
├── HEAD ← Points to current branch (refs/heads/main)
├── config ← Repository-local configuration
├── description ← Used by GitWeb (rarely modified)
├── hooks/ ← Client-side and server-side hooks
│ ├── pre-commit.sample
│ ├── commit-msg.sample
│ └── ...
├── info/
│ └── exclude ← Local gitignore (not committed)
├── objects/ ← ALL content stored here (blobs, trees, commits)
│ ├── info/
│ └── pack/
└── refs/ ← Pointers to commit objects
├── heads/ ← Branch tips
└── tags/ ← Tag pointers
init vs clone
# git init: create NEW empty repository
git init my-project
cd my-project
# git clone: copy EXISTING repository
git clone https://github.com/user/repo.git
cd repo
# (Already has .git/, history, remote configured)
Tasks
01. Create a New Directory
Every project starts in its own folder.
Hint: mkdir, cd
02. Initialize a Git Repository
Transform the empty directory into a Git-tracked repository.
Hint: git init
Solution
03. Explore the .git Directory
After git init, a hidden .git/ directory holds everything Git knows.
Hint: ls -la .git/, tree .git/
Solution
04. Read the HEAD File
HEAD tells Git which branch you are currently on.
Hint: cat .git/HEAD
Solution
05. Inspect the Config File
Each repo has its own local config inside .git/config.
Hint: cat .git/config
Solution
06. Try Initializing with a Custom Branch Name
By default, git init uses main (or master). You can choose your own.
Hint: git init --initial-branch=<name>
Solution
07. Create a Bare Repository
Bare repos have no working directory - used as central “server” repos.
Hint: git init --bare
Solution
08. Find the Password
The default branch name that Git created is the password for the next room.
Hint: cat .git/HEAD - the branch name after refs/heads/ is the password
[Protected] Room 04 - The Three States of Git
THE THREE STATES OF GIT
Room 04 - Working Directory → Staging → Repository
- Git has three main areas where your files live.
- Understanding this is THE KEY to mastering Git.
```mermaid flowchart LR %% Stash first (leftmost) ST[“📂 Stash\n(Temporary)”] ST -. “git stash pop” .-> WD
%% Main forward flow
WD["📂 Working Directory\n(modified)"]
SA["📋 Staging Area\n(Index)"]
RP["🗄️ Local Repository\n(.git)"]
RM["🗄️ Remote Repository\n(Git Server)"]
WD -. "git stash" .-> ST
WD -- "git add / git rm" --> SA
SA -- "git commit" --> RP
RP -- "git push" --> RM
%% Reverse operations
SA -. "git restore --staged" .-> WD
RP -. "git checkout" .-> WD
RM -. "git fetch" .-> RP
RM -. "git pull" .-> WD
RM -. "git clone" .-> WD
```
📜 Your mission
-
This room has a git repo already initialized with files.
Run:
git status -
Notice some files are “modified”, some are “staged”, some are “untracked”.
-
Identify the files in different states:
File State working.txtModified but NOT staged staged.txtAdded to the staging area committed.txtAlready committed -
View the content of each file to understand the three states:
Command What it shows cat working.txtSee “WORKING” git diffWorking dir changes git diff --stagedStaging area changes -
Find the password:
- Run
git status- and find out what is the command whichto discard changes in working directory.
- Run
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git status |
Show file states |
git diff |
Working dir vs Staging |
git diff --staged |
Staging vs Last Commit |
git diff HEAD |
Working dir vs Last Commit |
git status -s |
Short format status |
Try It Yourself: Explore This Room’s Repo
This room already has a git repo set up. Follow these steps to explore each state:
You should see output like this:
On branch main
Changes to be committed:
new file: staged.txt ← STAGED
Changes not staged for commit:
modified: committed.txt ← MODIFIED (unstaged)
Untracked files:
working.txt ← UNTRACKED
# Step 2 - Read the files
cat committed.txt # committed + has an unstaged change
cat staged.txt # staged, waiting to be committed
cat working.txt # untracked, git doesn't know about it
# Step 3 - See what changed in the working directory
git diff # shows the unstaged change to committed.txt
# Step 4 - See what's in the staging area
git diff --staged # shows staged.txt ready to commit
Moving files between states
# Unstage staged.txt (Staged → Untracked)
git restore --staged staged.txt
git status # staged.txt is now untracked
# Re-stage it
git add staged.txt
# Discard the unstaged change to committed.txt (Modified → Committed)
git restore committed.txt
git status # committed.txt is no longer modified
cat committed.txt # the extra line is gone!
# Track working.txt by staging it (Untracked → Staged)
git add working.txt
git status # working.txt is now staged
# Commit everything (Staged → Committed)
git commit -m "All files committed"
git status # working tree clean - all states resolved
The Three States Explained
```mermaid flowchart LR WD(“Working Directory\n\nYour actual files on disk\nmodified files”) WD – “git add” –> SA(“Staging Area\n(Index)\n\nContent\nfor next commit”) SA – “git commit” –> REPO(“Repository\n(.git)\n\nPermanent\nsnapshots”) SA – “← git restore –staged” –> WD REPO – “← git restore” –> SA
style WD fill:#334292,stroke:#448aff,stroke-width:1px,height:150px
style SA fill:#334292,stroke:#448aff,stroke-width:1px,height:150px
style REPO fill:#334292,stroke:#448aff,stroke-width:1px,height:150px
```
File Lifecycle
```mermaid flowchart LR U(“Untracked”) – “git add” –> S(“Staged”) S – “git commit” –> C(“Committed”) S – “git restore –staged” –> U C – “modify file” –> M(“Modified\n(unstaged)”) M – “git add” –> S
style U fill:#2b2e35,stroke:#9e9e9e,stroke-width:1px,width:125px
style S fill:#2b2e35,stroke:#9e9e9e,stroke-width:1px,width:125px
style C fill:#2b2e35,stroke:#9e9e9e,stroke-width:1px,width:125px
style M fill:#2b2e35,stroke:#9e9e9e,stroke-width:1px,width:125px
```
Tasks
01. Check the Current State
Always start by understanding what Git sees right now.
Hint: git status
Solution
02. Use Short Status Format
The short format gives a compact one-line-per-file overview using two-column codes.
Hint: git status -s
Solution
03. Read Each File to Understand the Three States
Inspect the actual file contents to see what’s in each state.
Hint: cat <filename>
Solution
04. See Unstaged Changes (git diff)
git diff (no flags) compares Working Directory vs Staging Area.
Hint: git diff
Solution
05. See Staged Changes (git diff --staged)
git diff --staged compares the Staging Area vs the Last Commit.
Hint: git diff --staged, git diff --cached
Solution
06. Unstage a File
Remove staged.txt from the staging area without deleting the file.
Hint: git restore --staged <file>
Solution
07. Discard Working Directory Changes
Throw away the extra line in committed.txt and restore it to the last committed version.
Hint: git restore <file>
Solution
08. Move a File Through All Three States
Track working.txt by staging it, then commit everything to reach a clean state.
Hint: git add, git commit
Solution
09. Find the Password
Run git status and read the output carefully. Git tells you which command to use “to discard changes in working directory”. That command name is the password.
Hint: look at the git status output for the suggested command
Solution
[Protected] Room 05 - Git Add: Staging Deep Dive
GIT ADD: STAGING DEEP DIVE
Room 05 - The Staging Area
📜 Your mission
- The staging area (also called the index) is Git’s superpower.
- Unlike most VCS tools, Git lets you choose exactly what enters each commit - file by file, or even hunk by hunk.
- Work through the tasks below to master every flavour of
git add. At the end, a hidden puzzle lets you discover the password by staging Python files.
How to find the password - step by step:
-
Enter the room directory and inspect the repo:
-
You will find 8 untracked Python files, each named with a step number followed by a word - for example
1_scanner.py,2_tracker.py, and so on up to8_1nterface.py. -
Stage all Python files at once:
-
List the staged files in order:
- The files appear sorted numerically (1 → 8) because of their
N_prefix.
- The files appear sorted numerically (1 → 8) because of their
-
For each filename, skip the step number and the underscore, then take the very first character of what remains:
-
Use the password to unlock the next room:
Quick Reference
| Command | Purpose |
|---|---|
git add <file> |
Stage a specific file |
git add <dir>/ |
Stage all changes inside a directory |
git add *.txt |
Stage by glob pattern |
git add . |
Stage everything in the current directory (recursive) |
git add -A |
Stage ALL changes - new, modified and deleted |
git add -u |
Stage modifications & deletions of already-tracked files only |
git add -p |
Interactive patch mode - stage individual hunks |
git add -i |
Full interactive staging menu |
git add -N <file> |
Mark an untracked file with intent-to-add |
git add -f <file> |
Force-add a file that matches .gitignore |
git add -n |
Dry-run - show what would be staged without doing it |
git restore --staged <file> |
Unstage a file (keep working-copy changes) |
git diff --staged |
Show what is currently staged vs last commit |
git diff |
Show unstaged working-copy changes |
Tasks
01. Inspect the Starting State
Before touching git add, understand what you are working with.
- You just entered
room_05and need a clear picture of the working tree. - Knowing which files are tracked, untracked, or modified is the first step before staging anything.
Hint: git status, git status -s
Solution
02. Stage a Single Specific File
- You want to add only
1_hello.txtto the next commit. - Passing the exact filename is the most precise form of staging.
Hint: git add <filename>
Solution
03. Stage Multiple Named Files at Once
- You want to stage both
2_notes.txtand3_todo.txtin a single command. git addaccepts multiple filenames separated by spaces.
Hint: git add file1 file2 ...
Solution
04. Stage Files Matching a Glob Pattern
- The room contains log files named
4_log_2026_03_15.txtand5_log_2026_03_16.txt. - You want to stage all log files without listing each one individually.
Hint: git add ?_log_*.txt
Solution
05. Stage All Files by Extension
- The repo contains 8 Python files named
1_scanner.pythrough8_1nterface.py. - Stage every
.pyfile with a single pattern.
Hint: git add *.py
Solution
06. Stage Everything at Once (git add .)
- You want to stage every untracked and modified file in one shot.
git add .stages all changes rooted at the current directory (recursively).
Hint: git add .
Solution
07. The Difference Between git add . and git add -A
git add .stages new files and modifications, but misses deletions outside the current directory in older Git versions.git add -A(or--all) always stages new + modified + deleted files regardless of where you run it.
Hint: git add -A, git rm
Solution
# Simulate a deleted file
rm 3_todo.txt
# git add . stages everything including this deletion (Git 2.x)
git add .
git status -s
# D 3_todo.txt ← deletion is staged
# Reset and try -A explicitly
git restore --staged 3_todo.txt
git restore 3_todo.txt # bring the file back
rm 3_todo.txt
git add -A
git status -s
# D 3_todo.txt ← same result - -A is unambiguous across all Git versions
08. Stage Only Already-Tracked Files (git add -u)
changes.txtis already tracked (it has a commit). You modified it.- Several other files are untracked - you do NOT want to touch them yet.
git add -u(update) stages modifications and deletions of tracked files only.
Hint: git add -u, git add --update
Solution
09. Preview What Would Be Staged (Dry Run)
- Before actually staging anything, you want to see which files a
git addcommand would affect. - Use
--dry-run(or-n) to preview without making changes.
Hint: git add -n, git add --dry-run
Solution
10. Stage Part of a File - Interactive Patch Mode
changes.txthas two independent changes: a production database hostname and a newapi_keyline.- You want to stage the hostname change but not the api_key (it should not be committed yet).
git add -plets you review and selectively stage individual hunks.
Hint: git add -p changes.txt
Solution
git add -p changes.txt
# Git shows each hunk and asks: Stage this hunk [y,n,q,a,d,s,e,?]?
#
# Hunk options:
# y - yes, stage this hunk
# n - no, skip this hunk
# s - split into smaller hunks
# e - manually edit the hunk
# q - quit, don't stage remaining hunks
# ? - show help
# After answering each hunk:
git diff --staged # shows only what you chose to stage
git diff # shows what remains unstaged
11. Split a Large Hunk (s in patch mode)
- Sometimes
git add -pshows a single hunk that contains multiple logical changes. - The
skey splits the hunk into smaller pieces so you can stage them independently.
Hint: git add -p, press s at the hunk prompt
Solution
12. Manually Edit a Hunk (e in patch mode)
- The hunk boundaries don’t split exactly where you need.
- Typing
ein patch mode opens the hunk in$EDITORso you can remove individual lines.
Hint: git add -p, press e; lines starting with + that you delete won’t be staged
Solution
git add -p changes.txt
# At the hunk prompt, type: e
# Your editor opens with the hunk diff.
#
# To EXCLUDE a + line from staging:
# change +api_key = SUPER_SECRET_KEY_12345
# to api_key = SUPER_SECRET_KEY_12345 (remove the leading +)
#
# Save and quit the editor.
# Git stages only the lines you kept.
git diff --staged # api_key line should NOT appear here
git diff # api_key line IS still in the working copy
13. Full Interactive Staging Menu (git add -i)
- You want a menu-driven interface to see the entire staging area at once, add/reset files, and diff them.
Hint: git add -i, git add --interactive
Solution
git add -i
# Menu:
# 1: status 2: update 3: revert
# 4: add untracked 5: patch 6: diff
# 7: quit 8: help
# Workflow:
# Choose 4 (add untracked) → select files by number → press Enter twice to confirm
# Choose 5 (patch) → select file → stage hunks interactively
# Choose 1 (status) → review what is staged
# Choose 7 (quit)
14. Mark a File with Intent-to-Add (-N)
- You want
git diff(without--staged) to show a new file’s content, but you are not ready to stage it. git add -N(or--intent-to-add) registers the path in the index as an empty blob.
Hint: git add -N <file>
Solution
15. Force-Add an Ignored File (git add -f)
- Create a
.gitignorethat ignores*.logfiles. - Then force-add one of the log files anyway.
Hint: git add -f, git add --force
Solution
# Create a .gitignore
echo "*.log" > .gitignore
echo "debug output" > debug.log
# Normal add is blocked
git add debug.log
# The following paths are ignored by one of your .gitignore files: debug.log
# Force it
git add -f debug.log
git status -s
# A .gitignore
# A debug.log ← staged despite the ignore rule
# Clean up
git restore --staged debug.log
rm debug.log .gitignore
16. Unstage a File (git restore --staged)
- You accidentally staged
7_budget.txtbut want to remove it from the index while keeping your local changes.
Hint: git restore --staged <file>
Solution
17. Unstage Everything at Once
- You ran
git add .and staged everything, but you want to start over.
Hint: git restore --staged .
Solution
18. Review Staged Changes Before Committing
- Before you commit you want to see exactly what diff will land in the commit.
git diff --staged(alias:git diff --cached) shows index vs last commit.
Hint: git diff --staged, git diff --cached
Solution
19. Stage Files in a Specific Sub-directory
- Imagine your repo has a
src/subdirectory. You want to stage only files inside it. - Passing a directory path to
git addstages everything within it recursively.
Hint: git add <directory>/
Solution
20. Combine Patterns - Add All Config Files
- You have
8_config_dev.txtand9_config_prod.txt. - Stage only the config files without listing them individually.
Hint: git add ?_config_*.txt
21. Use git add with Verbose Output
- You want to see every file path as Git stages it, useful when staging large trees.
Hint: git add -v .
Solution
22. Find the Password
- The password is hidden in the filenames of the 7 Python files in this repo.
- Each filename follows the pattern
N_word.py- a step number, then a word. - Stage all Python files, then list what you staged in order.
- Take the first letter of the word part (after
N_) from each filename in sequence - they spell the password.
Hint: git add *.py → git diff --staged --name-only
Solution
# Stage every Python file
git add *.py
# List staged files in alphabetical (step) order
git diff --staged --name-only
# Output:
# 1_scanner.py ← s
# 2_tracker.py ← t
# 3_adapter.py ← a
# 4_gateway.py ← g
# 5_encoder.py ← e
# 6_deployer.py ← d
# 7_0ps.py ← 0
# 8_1nterface.py ← 1
#
# First characters in order: s t a g e d 0 1 → staged01
Key Concepts Summary
mermaid
flowchart LR
WD["Working Directory"] -- "git add" --> SA["Staging Area (Index)"]
SA -- "git commit" --> R["Repository"]
SA -- "git restore --staged" --> WD
git add .- stage everything (new + modified, current dir downward)git add -A- stage everything including deletions, everywheregit add -u- stage only changes to already-tracked filesgit add -p- the most powerful form - stage individual hunksgit add -N- register intent; makes new files visible togit diffgit add -f- override.gitignorerulesgit add -n- preview without staging (dry-run)
[Protected] Room 06 - Git Status & Restore
GIT STATUS: READING THE CRIME SCENE
Room 06 - Deleted, Renamed, and Gone
📜 Your mission
- Someone has been busy.
- Files have been deleted and renamed - all already staged and ready to commit.
- Your job is to use
git status(and its friends) to figure out exactly what happened. - The password for the next room is hidden in plain sight: it is the filename of the longest deleted file.
Step-by-step:
-
Enter the room and run a full status:
Look at the “Changes to be committed” section - that is where staged deletions and renames appear.
-
Switch to the short format for a quicker overview:
Status codes to watch for:
Code Meaning DDeleted (staged) RRenamed (staged) MModified (not staged) ??Untracked -
Filter for only deleted staged files:
-
List the deleted filenames, find the longest one - that is your password.
-
Unlock the next room:
Quick Reference
| Command | Purpose |
|---|---|
git status |
Full status - staged, unstaged, untracked |
git status -s |
Short two-column format |
git status -sb |
Short format + branch info |
git status --porcelain |
Machine-readable (script-safe) output |
git diff --name-status --cached |
Staged files with status letter (A/D/R/M) |
git diff --diff-filter=D --cached --name-only |
Only staged deletions |
git diff --diff-filter=R --cached --name-only |
Only staged renames |
Tasks
01. Full Status - Read Every Section
Run the full status and identify what happened: which files were deleted, which were renamed.
Hint: git status
Solution
02. Short Format - Spot the Status Codes
Use the compact view to see every file’s two-letter status code at a glance.
Hint: git status -s
Solution
03. Machine-Readable Output
Get a stable format suitable for scripting or piping.
Hint: git status --porcelain
Solution
04. List Staged Changes with Status Letters
Use git diff --cached to see exactly what is staged, one file per line with its status letter.
Hint: git diff --name-status --cached
Solution
05. Filter - Only Staged Deletions
Show only the files that were deleted (ignore renames, modifications, and untracked).
Hint: git diff --diff-filter=D --cached --name-only
Solution
06. Filter - Only Staged Renames
Show only the files that were renamed, confirming what their new names are.
Hint: git diff --diff-filter=R --cached --name-status
Solution
07. Show Branch Info
Include the current branch name in the status output.
Hint: git status -sb
08. Find the Password
Look at all the deleted filenames. The longest one is the password.
Hint: git diff --diff-filter=D --cached --name-only
Solution
Short Status Code Reference
XY Meaning
── ─────────────────────────────
D Deleted and staged
R Renamed and staged
M Modified and staged
A New file staged
M Modified but NOT staged
D Deleted but NOT staged
?? Untracked file
MM Staged then modified again
[Protected] Room 07 - Git Commit: Saving Snapshots
GIT COMMIT: SAVING SNAPSHOTS
Room 07 - Your First Commit
📜 Your mission
A commit is a SNAPSHOT of your project at a point in time.
-
This repo has staged changes ready to commit.
Run:
git status -
Create your first commit:
git commit -m "My first commit"
-
View the commit:
git log --oneline
-
Make another change, stage it, and commit:
echo "update" >> file.txtgit add file.txtgit commit -m "Second commit"
-
Try committing with a multi-line message:
git commit(opens your editor)
-
Use the shortcut to stage + commit modified files:
git commit -am "Stage and commit in one step"- (Note: this does NOT add untracked files!)
-
View your commit history:
git log --oneline --graph
-
Find the password commit:
- Somewhere in the 250+ commits, one commit message starts with
password:. - That message contains the password for the next room.
Search the log for it:
The commit message itself is the clue — read it carefully. A file named
passwordwas also created in that commit. - Somewhere in the 250+ commits, one commit message starts with
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git commit -m "msg" |
Commit with inline message |
git commit -am "msg" |
Stage tracked + commit |
git commit |
Opens editor for message |
git commit --allow-empty -m "msg" |
Empty commit (CI triggers) |
git commit -v |
Show diff in editor |
Commit Message Best Practices
feat: add user login page ← type: subject (imperative mood)
← blank line
Implement OAuth2 login flow ← body (what and why)
with Google and GitHub providers.
← blank line
Closes #123 ← footer (references)
Conventional Commits types: feat, fix, docs, style, refactor, test, chore
What a Commit Contains
commit abc1234def5678...
├── tree → snapshot of ALL files at this point
├── parent → pointer to previous commit(s)
├── author → who wrote the changes + timestamp
├── committer → who applied the commit + timestamp
└── message → description of the changes
Tasks
01. Check What’s Ready to Commit
Before committing, always verify what is staged.
Hint: git status, git diff --staged
Solution
02. Create Your First Commit
Commit the staged changes with an inline message.
Hint: git commit -m "message"
Solution
03. View the Commit Log
See the commit you just made in the history.
Hint: git log --oneline
04. Make a Change, Stage, and Commit
Modify a tracked file, stage the change, and commit it - the core Git workflow.
Hint: echo >> file, git add, git commit -m
05. Stage and Commit in One Step
Use the -am shortcut to stage all modifications to tracked files and commit.
Hint: git commit -am "message"
Solution
06. Create an Empty Commit
Sometimes you need a commit with no file changes (e.g., to trigger CI).
Hint: git commit --allow-empty -m "message"
Solution
07. View the Diff Inside the Commit Editor
When writing longer commit messages, see the diff while you write.
Hint: git commit -v
Solution
08. Find the Password Commit
Somewhere among the 250+ commits, one commit message starts with password:.
Find it, read it — the value after the colon is the password.
Hint: git log --oneline --grep="password"
Solution
[Protected] Room 08 - Git Log: Exploring History
GIT LOG: EXPLORING HISTORY
Room 08 - The Time Machine
📜 Your mission
The git log is your time machine. Learn to navigate it!
-
This repo has a rich commit history. Explore it:
git log
-
Try different log formats:
git log --onelinegit log --oneline --graph --allgit log --statgit log --patch(or-p)
-
Filter the log:
git log --author="Alice"git log --since="2025-01-01"git log --grep="fix"git log -n 5(last 5 commits)
-
Show a specific commit:
git show HEADgit show HEAD~2(2 commits back)
-
Find the commit by “Bob” that mentions “secret” in its message. Read that commit’s message - it contains the password.
Once you have the password:
Quick Reference
| Command | Purpose |
|---|---|
git log |
Full log with all details |
git log --oneline |
One line per commit |
git log --oneline --graph --all |
Visual branch graph |
git log --stat |
Files changed per commit |
git log -p |
Full patch per commit |
git log -n 5 |
Last N commits |
git log --author="name" |
Filter by author |
git log --grep="text" |
Filter by commit message |
git log --since / --until |
Filter by date |
git log --all -S "text" |
Pickaxe: commits that added/removed text |
git log --all -G "regex" |
Pickaxe with regex |
git log --follow -- file |
Follow file through renames |
git log --merges |
Only merge commits |
git log --no-merges |
Exclude merge commits |
git log --diff-filter=R |
Only rename commits |
git log --simplify-by-decoration |
Only tagged/branched commits |
git log v1.0.0..v2.0.0 |
Commits between two refs |
git log --first-parent |
Main-branch only (skip merged) |
git log --pretty=format:"..." |
Custom output format |
git log --format="%an" \| sort \| uniq -c |
Commit counts per author |
git shortlog -sn |
Author commit counts, ranked |
git log --after="2026-01-01" |
Commits after a date |
git log --before="2026-01-01" |
Commits before a date |
git log --diff-filter=A -- "*.py" |
Commits that added a Python file |
Tasks
01. View the Full Log
Display the complete history with all details — hash, author, date, full message.
Hint: git log
Solution
02. Compact One-Line Log
Get one line per commit: short hash + subject.
Hint: git log --oneline
Solution
03. Visual Branch Graph
See how the feature/dark-mode branch diverged and was merged back.
Hint: git log --oneline --graph --all
Solution
04. Show Files Changed Per Commit
Use --stat to see which files were touched and how many lines changed.
Hint: git log --stat
Solution
05. Show Full Patches
View the actual diff introduced by each commit.
Hint: git log -p, git log --patch
Solution
06. Limit to the Last N Commits
Show only the 5 most recent commits.
Hint: git log -n 5, git log -5
07. Filter by Author
List all commits made by Alice.
Hint: git log --author="Alice"
Solution
08. Filter by Commit Message Keyword
Find all commits whose message contains the word fix.
Hint: git log --grep="fix"
Solution
09. Combine Author and Message Filters
Find only Bob’s commits that mention fix.
Hint: git log --author="Bob" --grep="fix"
Solution
10. Filter by Date Range
Show commits made in February 2025 only.
Hint: git log --since, git log --until
Solution
11. Commits After a Date
Show everything committed after 2026-01-01.
Hint: git log --after="2026-01-01"
Solution
12. Only Merge Commits
Show only commits that merged a branch.
Hint: git log --merges
13. Exclude Merge Commits
Show the linear history — no merge commits.
Hint: git log --no-merges
14. First-Parent Only
Walk only the main-branch line, ignoring commits that came in via merges.
Hint: git log --first-parent --oneline
Solution
15. Show Decorated Refs (Tags and Branches)
See which commits have tags or branch labels attached.
Hint: git log --oneline --decorate
Solution
16. Commits Between Two Tags
Show only the commits introduced between v1.0.0 and v2.0.0.
Hint: git log v1.0.0..v2.0.0 --oneline
Solution
17. Only Tagged or Branch-Tipped Commits
Collapse the log to only commits that are pointed to by a tag or branch.
Hint: git log --simplify-by-decoration --oneline
Solution
18. Follow a File Through a Rename
server.py was renamed to web_server.py. Show its full history across the rename.
Hint: git log --follow -- web_server.py
Solution
19. Pickaxe Search — Find When a String Was Added or Removed
Find the commits that added or removed the string OMEGA_INIT.
Hint: git log -S "OMEGA_INIT"
Solution
20. Pickaxe with Regex
Find commits that touched any line containing pool using a regex.
Hint: git log -G "pool"
Solution
21. Custom Format — Hash, Author, Date, Subject
Build a compact one-line format showing the short hash, author name, relative date, and subject.
Hint: git log --pretty=format:"%h | %an | %ar | %s"
Solution
git log --pretty=format:"%h | %an | %ar | %s" -10
# a1b2c3d | Alice | 9 days ago | feat: add passkey support
# d4e5f6a | Bob | 4 days ago | feat: add HTTP/2 support
# ...
# Useful format placeholders:
# %H full hash %h short hash
# %an author name %ae author email
# %ad author date %ar relative date
# %s subject %b body
# %D ref names (tags, branches)
22. Count Commits per Author
Rank all contributors by commit count.
Hint: git shortlog -sn
Solution
23. Find Only Commits That Added a File
Show commits where a new Python file was first introduced (status A).
Hint: git log --diff-filter=A --name-only -- "*.py"
Solution
24. Show the Full Log for All Branches Including Stale Ones
Include branches that are not reachable from HEAD, such as feature/dark-mode.
Hint: git log --all --oneline
Solution
25. Find the Password
There is one commit by Bob whose message contains the word secret.
The last word of that message is the password.
Hint: git log --oneline --author="Bob" --grep="secret"
Solution
Format Placeholder Reference
| Placeholder | Meaning |
|---|---|
%H |
Full commit hash |
%h |
Short commit hash |
%an |
Author name |
%ae |
Author email |
%ad |
Author date (respects --date=) |
%ar |
Author date, relative |
%cn |
Committer name |
%cd |
Committer date |
%s |
Subject (first line of message) |
%b |
Body (rest of message) |
%D |
Ref names (tags, branches) |
%n |
Newline |
[Protected] Room 09 - Git Diff: Comparing Changes
GIT DIFF: COMPARING CHANGES
Room 09 - Spot the Difference
📜 Your mission
git diff shows you EXACTLY what changed, line by line.
-
This repo has modified files. See what changed:
git diff(working dir vs staging)git diff --staged(staging vs last commit)git diff HEAD(working dir vs last commit)
-
Compare two commits:
git diff HEAD~2 HEAD
-
Compare specific files:
git diff -- file1.txt
-
Show just the names of changed files:
git diff --name-onlygit diff --name-status
-
Show word-level diffs:
git diff --word-diff
-
Count lines changed:
git diff --stat
-
In the file
puzzle.txt, there’s a line that was ADDED (marked with+). That line contains the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git diff |
Working dir vs Staging |
git diff --staged |
Staging vs Last commit |
git diff HEAD |
Working dir vs Last commit |
git diff HEAD~2 HEAD |
Between two commits |
git diff branch1..branch2 |
Between branches |
git diff --name-only |
Just filenames |
git diff --stat |
Summary statistics |
git diff --word-diff |
Word-level changes |
git diff -- file.txt |
Specific file only |
Reading Diff Output
diff --git a/file.txt b/file.txt
index abc1234..def5678 100644
--- a/file.txt ← old version
+++ b/file.txt ← new version
@@ -1,3 +1,4 @@ ← hunk header (line numbers)
unchanged line ← context (no prefix)
-removed line ← deleted (red -)
+added line ← added (green +)
another unchanged
Tasks
01. See Unstaged Changes
Compare working directory against the staging area.
Hint: git diff
Solution
02. See Staged Changes
Compare the staging area against the last commit.
Hint: git diff --staged
Solution
03. Compare Working Directory vs Last Commit
See ALL changes (staged + unstaged) relative to the last commit.
Hint: git diff HEAD
04. Compare Two Commits
See what changed between two specific points in history.
Hint: git diff <commit1> <commit2>
05. Diff a Specific File
Narrow the diff to just one file.
Hint: git diff -- <file>
Solution
06. Show Only Changed Filenames
Get a list of changed files without the full diff.
Hint: git diff --name-only, git diff --name-status
Solution
07. Word-Level Diff
See changes at the word level instead of line level.
Hint: git diff --word-diff
Solution
08. Summary Statistics
Get a quick summary of insertions and deletions.
Hint: git diff --stat
Solution
09. Find the Password in puzzle.txt
There’s a line ADDED (marked with +) in puzzle.txt that contains the password.
Hint: git diff puzzle.txt, look for the + line
[Protected] Room 10 - Git Branch: Parallel Universes
GIT BRANCH: PARALLEL UNIVERSES
Room 10 - Branching Out
📜 Your mission
Branches let you work on multiple things simultaneously!
-
List all branches:
git branch
-
Create a new branch:
git branch feature-login
-
Switch to it:
git checkout feature-login- (or:
git switch feature-login)
-
Create AND switch in one command:
git checkout -b feature-signup- (or:
git switch -c feature-signup)
-
This repo has several branches. List them all:
git branch -a
-
Find the branch that contains a file called
secret_key.txt. Switch to that branch and read the file.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git branch |
List local branches |
git branch -a |
List all (local + remote) |
git branch <name> |
Create new branch |
git branch -d <name> |
Delete merged branch |
git branch -D <name> |
Force delete branch |
git branch -m <old> <new> |
Rename branch |
git switch <name> |
Switch to branch |
git switch -c <name> |
Create + switch |
git checkout <name> |
Switch (older syntax) |
git checkout -b <name> |
Create + switch (older) |
How Branches Work
main: A ── B ── C ── D ← HEAD
\
feature: E ── F ← feature branch
# A branch is just a POINTER to a commit!
# Creating a branch is instant (just writes 41 bytes)
Tasks
01. List Local Branches
See which branches exist in this repo.
Hint: git branch
Solution
02. Create a New Branch
Create a branch without switching to it.
Hint: git branch <name>
03. Switch to a Branch
Move HEAD to the new branch.
Hint: git switch <name>, git checkout <name>
Solution
04. Create and Switch in One Command
Create a new branch and immediately switch to it.
Hint: git switch -c <name>, git checkout -b <name>
Solution
05. List All Branches Including Remote
See local and remote-tracking branches.
Hint: git branch -a
06. Rename a Branch
Rename the current branch or a named branch.
Hint: git branch -m <old> <new>
Solution
07. Delete a Branch
Remove a branch you no longer need.
Hint: git branch -d <name>, git branch -D <name>
Solution
08. Find the Secret Branch
One of the branches contains a file called secret_key.txt. Find it and read the password.
Hint: git branch, git switch <branch>, cat secret_key.txt
Solution
[Protected] Room 11 - Git Merge: Bringing Branches Together
GIT MERGE: BRINGING BRANCHES TOGETHER
Room 11 - Merging Branches
📜 Your mission
Merging combines the work from different branches.
-
This repo has a
featurebranch with new work.git log --oneline --graph --all
-
Merge the feature branch into main:
git checkout maingit merge feature
-
This creates a MERGE COMMIT (if it’s not fast-forward).
git log --oneline --graph
-
Try a fast-forward merge:
git merge bugfix- (Fast-forward: main just moves forward, no merge commit)
-
Delete merged branches:
git branch -d featuregit branch -d bugfix
-
Check which branches are merged:
git branch --merged
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git merge <branch> |
Merge branch into current |
git merge --no-ff <branch> |
Force merge commit |
git merge --squash <branch> |
Squash into one commit |
git merge --abort |
Cancel in-progress merge |
git branch --merged |
List merged branches |
Merge Types
Fast-Forward (linear)
mermaid
gitGraph
commit id: "A"
commit id: "B"
branch feature
commit id: "C"
commit id: "D"
checkout main
merge feature
Three-Way Merge
mermaid
gitGraph
commit id: "A"
commit id: "B"
branch feature
commit id: "C"
commit id: "D"
checkout main
commit id: "E"
merge feature id: "M" tag: "merge commit"
Tasks
01. Visualize All Branches
Get a graph view of all branches and their commits.
Hint: git log --oneline --graph --all
Solution
02. Fast-Forward Merge
Merge the bugfix branch into main. Since main has no new commits, this will be a fast-forward.
Hint: git checkout main, git merge bugfix
Solution
03. Three-Way Merge
Merge feature into main. Both branches have diverged, so this creates a merge commit.
Hint: git merge feature
Solution
04. Force a Merge Commit
Even when fast-forward is possible, create a merge commit for a clear history.
Hint: git merge --no-ff <branch>
Solution
05. Squash a Branch Into One Commit
Combine all of a branch’s commits into a single staged change.
Hint: git merge --squash <branch>
Solution
06. Check Which Branches Are Merged
See which branches have been fully merged into the current branch.
Hint: git branch --merged, git branch --no-merged
Solution
07. Clean Up Merged Branches
Delete branches that have been fully merged.
Hint: git branch -d <branch>
Solution
08. Find the Password
Merge all branches into main, then run git branch --merged and look at the log.
Hint: the password might be in a merged commit message or a file brought in by the merge
[Protected] Room 12 - Merge Conflicts
MERGE CONFLICTS
Room 12 - The Battle of Branches
📜 Your mission
When two branches modify the SAME lines, Git can’t auto-merge. YOU must resolve it!
-
Try merging the
conflict-branch:git merge conflict-branch- You’ll see:
CONFLICT (content): Merge conflict in battle.txt
-
Open the conflicted file:
cat battle.txt
You’ll see conflict markers:
-
RESOLVE the conflict by editing
battle.txt:- Remove ALL conflict markers (
<<<,===,>>>) - Keep the content you want (or combine both)
- Save the file
- Remove ALL conflict markers (
-
Mark as resolved and complete the merge:
git add battle.txtgit commit -m "Resolve merge conflict"
-
Verify with:
git log --oneline --graph
Once you have the password:
Conflict Markers
<<<<<<< HEAD
Your changes (current branch)
=======
Their changes (incoming branch)
>>>>>>> conflict-branch
Resolution Steps
# 1. Start merge (conflict occurs)
git merge conflict-branch
# 2. See conflicted files
git status
# 3. Edit files - remove markers, keep desired content
# 4. Stage resolved files
git add battle.txt
# 5. Complete the merge
git commit
# OR: abort the whole thing
git merge --abort
Tasks
01. Trigger a Merge Conflict
Attempt the merge and observe the conflict message.
Hint: git merge conflict-branch
Solution
02. Identify Conflicted Files
Check which files have conflicts after a failed merge.
Hint: git status
03. Read the Conflict Markers
Open the conflicted file and identify the three sections.
Hint: cat battle.txt
Solution
04. Resolve the Conflict
Edit the file to remove ALL conflict markers and keep the desired content.
Hint: open with an editor, remove <<<, ===, >>> lines
Solution
05. Complete the Merge
Stage the resolved file and create the merge commit.
Hint: git add, git commit
Solution
06. Abort a Merge Instead
Start the merge again on a different branch and abort it mid-conflict.
Hint: git merge --abort
Solution
07. Use Theirs or Ours Strategy
Resolve a conflict by picking one side entirely.
Hint: git checkout --ours <file>, git checkout --theirs <file>
Solution
08. Find the Password
Resolve the conflict in battle.txt and read the merged content. The password is in the resolved text.
Hint: resolve the conflict, then cat battle.txt
[Protected] Room 13 - Git Rebase: Linear History
GIT REBASE: LINEAR HISTORY
Room 13 - Rewriting the Timeline
📜 Your mission
Rebase replays your commits on top of another branch - creating a LINEAR history.
-
View the current branching history:
git log --oneline --graph --all
-
Switch to the feature branch:
git checkout feature
-
Rebase onto main:
git rebase main- This moves your feature commits to the TIP of main!
-
Compare before/after:
git log --oneline --graph --all- Notice: the history is now LINEAR (no merge commit).
-
Interactive rebase - edit the last 3 commits:
git rebase -i HEAD~3
You can:
pick= keep the commitreword= change the messagesquash= merge into previous commitdrop= remove the commit
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git rebase main |
Rebase current branch onto main |
git rebase -i HEAD~3 |
Interactive rebase last 3 commits |
git rebase --abort |
Cancel rebase |
git rebase --continue |
Continue after fixing conflicts |
git rebase --skip |
Skip current commit |
Merge vs Rebase
Merge: preserves history (creates merge commit)
mermaid
gitGraph
commit id: "A"
commit id: "B"
branch feature
commit id: "C"
commit id: "D"
checkout main
commit id: "E"
merge feature id: "M" tag: "merge commit"
Rebase: linear history (replays commits)
mermaid
gitGraph
commit id: "A"
commit id: "B"
commit id: "E"
commit id: "C'" tag: "rebased"
commit id: "D'" tag: "rebased"
Interactive Rebase Commands
pick = use commit as-is
reword = change commit message
squash = merge into previous commit
fixup = like squash but discard message
edit = stop to amend this commit
drop = remove this commit entirely
⚠️ Golden Rule: Never rebase commits that have been pushed to a shared remote!
Tasks
01. View the Branch Graph Before Rebase
See the current branch topology.
Hint: git log --oneline --graph --all
Solution
02. Rebase Feature onto Main
Make the feature branch linear on top of main.
Hint: git checkout feature, git rebase main
Solution
03. Compare Before and After
See how the graph changed from branched to linear.
Hint: git log --oneline --graph --all
Solution
04. Interactive Rebase - View Commands
Start an interactive rebase and explore the available commands.
Hint: git rebase -i HEAD~3
Solution
05. Squash Commits Together
Combine multiple commits into one using interactive rebase.
Hint: change pick to squash (or s) for the commits to combine
Solution
06. Reword a Commit Message
Change a commit message without changing its content.
Hint: reword in interactive rebase
Solution
07. Drop a Commit
Remove a specific commit from history entirely.
Hint: drop in interactive rebase, or delete the line
Solution
08. Abort a Rebase
If things go wrong, cancel the rebase in progress.
Hint: git rebase --abort
Solution
09. Find the Password
The password is hidden in one of the commit messages. Use interactive rebase to inspect them.
Hint: git log --oneline, or try git rebase -i and read the messages
[Protected] Room 14 - Git Stash: Emergency Shelf
GIT STASH: EMERGENCY SHELF
Room 14 - Stashing Your Work
📜 Your mission
Stash lets you SAVE uncommitted work temporarily and come back to it later.
-
This repo has uncommitted changes. Check:
git statusgit diff
-
Stash your current changes:
git stash- (Your working directory is now CLEAN!)
-
List your stashes:
git stash list
-
Apply the stash (keep it in the list):
git stash apply
-
Pop the stash (apply + remove from list):
git stash pop
-
Stash with a message:
git stash push -m "work in progress on login"
-
This repo has multiple stashes. Find the one with message containing “password”. Apply it to reveal the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git stash |
Stash current changes |
git stash push -m "msg" |
Stash with message |
git stash list |
List all stashes |
git stash apply |
Apply latest (keep in list) |
git stash pop |
Apply latest (remove from list) |
git stash apply stash@{2} |
Apply specific stash |
git stash drop stash@{0} |
Delete a stash |
git stash clear |
Delete ALL stashes |
git stash show -p |
Show stash diff |
git stash branch <name> |
Create branch from stash |
Tasks
01. Check for Uncommitted Changes
See what changes exist before stashing.
Hint: git status, git diff
02. Stash Your Changes
Save all uncommitted changes to the stash.
Hint: git stash
Solution
03. List All Stashes
View every stash entry.
Hint: git stash list
Solution
04. Apply a Stash Without Removing It
Restore stashed changes but keep the stash in the list.
Hint: git stash apply
Solution
05. Pop a Stash
Apply a stash and remove it from the list in one step.
Hint: git stash pop
06. Stash with a Descriptive Message
Create a stash with a custom message so you can find it later.
Hint: git stash push -m "message"
Solution
07. Apply a Specific Stash
Apply a stash by its index rather than the latest.
Hint: git stash apply stash@{N}
08. View Stash Contents Without Applying
Peek at what a stash contains.
Hint: git stash show -p stash@{N}
Solution
09. Find the Password
One of the stashes has a message containing “password”. Find and apply it.
Hint: git stash list, look for the right stash, then git stash apply stash@{N}
Solution
[Protected] Room 15 - Git Remote: Connecting to the World
GIT REMOTE: CONNECTING TO THE WORLD
Room 15 - Remote Repositories
📜 Your mission
Remotes are BOOKMARKS to other copies of your repository.
-
List current remotes:
git remote -v
-
Add a remote:
git remote add origin https://example.com/repo.gitgit remote add upstream https://example.com/upstream.git
-
View remote details:
git remote show origin
-
Rename a remote:
git remote rename origin primary
-
Remove a remote:
git remote remove upstream
-
This repo has several remotes configured. Find the remote named “secret” and read its URL. The URL path contains the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git remote -v |
List remotes with URLs |
git remote add <name> <url> |
Add a remote |
git remote remove <name> |
Remove a remote |
git remote rename <old> <new> |
Rename a remote |
git remote show <name> |
Show remote details |
git remote set-url <name> <url> |
Change remote URL |
Tasks
01. List Configured Remotes
See all remote names and their URLs.
Hint: git remote -v
Solution
02. Add a New Remote
Add a remote called backup pointing to a URL.
Hint: git remote add <name> <url>
Solution
03. Show Remote Details
Get detailed information about a specific remote.
Hint: git remote show <name>
Solution
04. Rename a Remote
Change a remote’s name.
Hint: git remote rename <old> <new>
Solution
05. Change a Remote URL
Update the URL for an existing remote.
Hint: git remote set-url <name> <new-url>
Solution
06. Remove a Remote
Delete a remote you no longer need.
Hint: git remote remove <name>
07. Find the Password
Find the remote named “secret” and read its URL. The URL path contains the password.
Hint: git remote -v
[Protected] Room 16 - Git Clone: Copying Repositories
GIT CLONE: COPYING REPOSITORIES
Room 16 - Cloning
📜 Your mission
Clone creates a COMPLETE copy of a repository with all its history.
-
Clone the local
upstreambare repo in this room:git clone upstream/ my-clone
-
Explore the clone:
cd my-clonegit log --onelinegit remote -v
-
Clone with options:
git clone --depth 1 upstream/ shallow-clone(only latest commit)git clone --branch feature upstream/ branch-clonegit clone --bare upstream/ bare-clone.git
-
Compare
.gitsizes:du -sh my-clone/.gitdu -sh shallow-clone/.git
-
The password is hidden in one of the commits in
upstream. Clone it, search the log, find the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git clone <url> |
Full clone |
git clone --depth 1 <url> |
Shallow clone (latest only) |
git clone --branch <br> <url> |
Clone specific branch |
git clone --bare <url> |
Bare clone (no working dir) |
git clone --recurse-submodules <url> |
Clone with submodules |
Tasks
01. Clone a Local Repository
Clone the upstream bare repo into a new directory.
Hint: git clone upstream/ my-clone
02. Inspect the Clone’s Remote
Check which remote was automatically configured.
Hint: git remote -v
03. Shallow Clone
Create a clone with only the latest commit (no full history).
Hint: git clone --depth 1 <url> <dir>
Solution
04. Clone a Specific Branch
Clone only a particular branch.
Hint: git clone --branch <name> <url> <dir>
05. Bare Clone
Create a bare clone (no working directory, just the Git database).
Hint: git clone --bare <url> <dir>
Solution
06. Compare Clone Sizes
Compare the .git directory sizes of different clone types.
Hint: du -sh <dir>/.git
Solution
07. Find the Password
Clone the upstream repo and search the commit log for the password.
Hint: git clone upstream/ search-clone, cd search-clone, git log --oneline
[Protected] Room 17 - Git Fetch: Download Without Merging
GIT FETCH: DOWNLOAD WITHOUT MERGING
Room 17 - Fetching Updates
📜 Your mission
Fetch downloads new data from a remote without changing your working files.
-
This repo is cloned from a remote that has new commits.
Check:
git log --oneline --all -
Fetch the latest:
git fetch origin
-
Compare local vs remote:
git log --oneline main..origin/main
-
View what was fetched:
git log --oneline --all --graph
-
Fetch DOES NOT change your working directory or current branch. It only updates remote-tracking branches (
origin/main, etc.) -
Fetch all remotes:
git fetch --all
-
Prune deleted remote branches:
git fetch --prune
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git fetch origin |
Fetch from origin |
git fetch --all |
Fetch from all remotes |
git fetch --prune |
Remove deleted remote branches |
git log main..origin/main |
See what was fetched |
Fetch vs Pull
fetch: Downloads data → Updates remote-tracking branches → Does NOT merge
pull: Downloads data → Updates remote-tracking branches → MERGES into current
Tasks
01. View Current State
Check what branches exist locally and remotely before fetching.
Hint: git log --oneline --all --graph
02. Fetch from Origin
Download new data from origin without merging.
Hint: git fetch origin
Solution
03. See What Was Fetched
Compare the local main with what origin has.
Hint: git log main..origin/main
Solution
04. Verify Working Directory Is Unchanged
Confirm that fetch did NOT modify your files.
Hint: git status, git diff
Solution
05. Fetch from All Remotes
If you have multiple remotes, fetch from all of them at once.
Hint: git fetch --all
06. Prune Stale Remote Branches
Clean up remote-tracking branches that no longer exist on the remote.
Hint: git fetch --prune
Solution
07. Integrate Fetched Changes
After fetching, merge or rebase to integrate the new commits.
Hint: git merge origin/main or git rebase origin/main
Solution
08. Find the Password
Fetch from origin, then look at the new commits that arrived. The password is in one of them.
Hint: git fetch origin, git log main..origin/main
Solution
[Protected] Room 18 - Git Pull: Fetch + Merge
GIT PULL: FETCH + MERGE
Room 18 - Pulling Updates
📜 Your mission
Pull = Fetch + Merge. It downloads AND integrates remote changes.
-
Pull from remote:
git pull origin main- This fetches from origin and merges into your current branch.
-
Pull with rebase instead of merge:
git pull --rebase origin main- (Creates a linear history instead of merge commits)
-
Configure pull strategy:
git config pull.rebase true(always rebase on pull)git config pull.ff only(only fast-forward)
-
Compare the results:
git log --oneline --graph
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git pull |
Pull from tracking remote |
git pull origin main |
Pull specific branch |
git pull --rebase |
Rebase instead of merge |
git pull --ff-only |
Only fast-forward |
git config pull.rebase true |
Default to rebase |
Tasks
01. Simple Pull
Fetch and merge from the remote in one command.
Hint: git pull origin main
02. Pull with Rebase
Pull using rebase instead of merge for linear history.
Hint: git pull --rebase origin main
Solution
03. Fast-Forward Only
Only pull if a fast-forward is possible (no merge commit needed).
Hint: git pull --ff-only
Solution
04. Configure Default Pull Strategy
Set your preferred pull behavior for all repos.
Hint: git config pull.rebase true
Solution
05. Check What Will Be Pulled
Preview incoming changes before pulling.
Hint: git fetch + git log main..origin/main
Solution
06. Compare Pull vs Fetch+Merge
Verify that pull is identical to doing fetch then merge manually.
Hint: git log --oneline --graph
Solution
07. Find the Password
Pull from origin and check the new commits or files that arrived.
Hint: git pull origin main, git log --oneline
[Protected] Room 19 - Git Push: Sharing Your Work
GIT PUSH: SHARING YOUR WORK
Room 19 - Pushing to Remote
📜 Your mission
Push sends your local commits to a remote repository.
-
This repo has local commits not yet pushed.
git log --oneline origin/main..main
-
Push to remote:
git push origin main
-
Push a new branch:
git push -u origin feature-branch- (
-usets up tracking so future pushes are simpler)
-
Push all branches:
git push --all origin
-
Delete a remote branch:
git push origin --delete old-branch
-
Force push (DANGEROUS - rewrites remote history):
git push --force(or--force-with-leasefor safety)
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git push origin main |
Push to remote |
git push -u origin <branch> |
Push + set upstream |
git push --all |
Push all branches |
git push --tags |
Push all tags |
git push --force-with-lease |
Safe force push |
git push origin --delete <br> |
Delete remote branch |
⚠️ Never --force on shared branches - use --force-with-lease instead!
Tasks
01. See Unpushed Commits
Check which commits exist locally but not yet on the remote.
Hint: git log origin/main..main
02. Push to Remote
Push your local main branch to origin.
Hint: git push origin main
Solution
03. Push and Set Upstream
Push a new branch and set up tracking.
Hint: git push -u origin <branch>
Solution
04. Push All Branches
Push every local branch to the remote.
Hint: git push --all origin
05. Push Tags
Send tags to the remote.
Hint: git push --tags
06. Delete a Remote Branch
Remove a branch from the remote.
Hint: git push origin --delete <branch>
07. Safe Force Push
When you’ve rewritten history, use the safe version of force push.
Hint: git push --force-with-lease
Solution
08. Find the Password
Check the unpushed commits or files in the repo for the password.
Hint: git log --oneline, cat the files
[Protected] Room 20 - Git Tag: Marking Milestones
GIT TAG: MARKING MILESTONES
Room 20 - Tagging Releases
📜 Your mission
Tags mark specific points in history - usually releases.
-
List existing tags:
git tag
-
Create a lightweight tag:
git tag v1.0
-
Create an annotated tag (recommended):
git tag -a v2.0 -m "Version 2.0 release"
-
Tag a specific commit:
git tag -a v0.5 abc1234 -m "Retroactive tag"
-
Show tag details:
git show v2.0
-
Push tags to remote:
git push origin v2.0git push origin --tags(push all tags)
-
Delete a tag:
git tag -d v1.0git push origin :refs/tags/v1.0(delete remote tag)
-
This repo has several tags. Find the tag whose message contains the password.
git tag -l | xargs -I{} git show {}
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git tag |
List tags |
git tag v1.0 |
Lightweight tag |
git tag -a v1.0 -m "msg" |
Annotated tag |
git show v1.0 |
Show tag info |
git push origin v1.0 |
Push specific tag |
git push origin --tags |
Push all tags |
git tag -d v1.0 |
Delete local tag |
Lightweight vs Annotated
Lightweight: just a pointer (like a branch that doesn't move)
Annotated: full object with tagger, date, message, and optional GPG signature
Tasks
01. List All Tags
See what tags already exist in this repo.
Hint: git tag
02. Create a Lightweight Tag
Create a simple pointer tag at the current commit.
Hint: git tag <name>
03. Create an Annotated Tag
Create a tag with a message, author, and date.
Hint: git tag -a <name> -m "message"
Solution
04. Tag a Past Commit
Tag a specific earlier commit.
Hint: git tag -a <name> <hash> -m "message"
Solution
05. Show Tag Details
Inspect the metadata and commit associated with a tag.
Hint: git show <tag>
06. Filter Tags by Pattern
Search for tags matching a glob pattern.
Hint: git tag -l "pattern*"
07. Delete a Tag
Remove a local tag.
Hint: git tag -d <name>
08. Find the Password
Examine each tag’s message. One of them contains the password.
Hint: git tag -l, then git show <tag> for each
Solution
[Protected] Room 21 - Git Cherry-Pick: Selective Commits
GIT CHERRY-PICK: SELECTIVE COMMITS
Room 21 - Cherry-Picking Commits
📜 Your mission
Cherry-pick applies a SPECIFIC commit from one branch to another.
-
View all branches and their commits:
git log --oneline --graph --all
-
Find the commit on
featurebranch that you need:git log --oneline feature
-
Cherry-pick that commit onto main:
git checkout maingit cherry-pick <commit-hash>
-
Cherry-pick without committing:
git cherry-pick --no-commit <hash>
-
Cherry-pick a range of commits:
git cherry-pick A..B
-
The
treasurebranch has a commit with message “KEY COMMIT”. Cherry-pick it to get the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git cherry-pick <hash> |
Apply a single commit |
git cherry-pick A..B |
Apply a range of commits |
git cherry-pick --no-commit |
Apply changes without committing |
git cherry-pick --abort |
Abort an in-progress cherry-pick |
git cherry-pick --continue |
Continue after resolving conflicts |
git log --oneline --all |
View commits across all branches |
How Cherry-Pick Works
feature: A --- B --- C --- D
↓ cherry-pick C
main: X --- Y --- C'
Cherry-pick copies the changes introduced by a commit and creates
a NEW commit (C') on your current branch. The original stays put.
Tasks
01. List All Branches and Commits
Visualize the commit graph across all branches.
Hint: git log --oneline --graph --all
Solution
02. Cherry-Pick a Single Commit
Apply one specific commit from feature onto main.
Hint: git checkout main, git cherry-pick <hash>
Solution
03. Cherry-Pick Without Committing
Apply changes from a commit but leave them staged, without creating a commit.
Hint: git cherry-pick --no-commit <hash>
Solution
04. Cherry-Pick a Range
Apply multiple consecutive commits at once.
Hint: git cherry-pick A..B (exclusive of A)
Solution
05. Handle Cherry-Pick Conflicts
When a cherry-pick conflicts, resolve it and continue.
Hint: git cherry-pick --continue, git cherry-pick --abort
Solution
06. Verify the Cherry-Picked Commit
Confirm the new commit was created on your branch.
Hint: git log --oneline
Solution
07. Find the Password
The treasure branch has a commit with message “KEY COMMIT”. Cherry-pick it.
Hint: git log --oneline treasure, git cherry-pick <hash>
Solution
[Protected] Room 22 - Git Reset: Rewinding History
GIT RESET: REWINDING HISTORY
Room 22 - The Three Modes of Reset
📜 Your mission
Reset moves HEAD (and optionally staging/working dir) to a different commit.
THREE MODES:
--soft→ Move HEAD only (staged + working dir unchanged)--mixed→ Move HEAD + clear staging (DEFAULT, working dir unchanged)-
--hard→ Move HEAD + clear staging + clear working dir (DESTRUCTIVE!) -
View the commit history:
git log --oneline
-
Soft reset - undo last commit but keep changes staged:
git reset --soft HEAD~1git status(changes are still staged!)
-
Mixed reset - undo last commit, unstage changes:
git reset HEAD~1git status(changes are in working directory)
-
Hard reset - COMPLETELY undo (DANGER!):
git reset --hard HEAD~1- (All changes GONE - use with extreme caution)
-
Reset a single file from staging:
git reset HEAD file.txt
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git reset --soft HEAD~1 |
Move HEAD; keep changes staged |
git reset HEAD~1 |
Move HEAD; unstage changes (mixed) |
git reset --hard HEAD~1 |
Move HEAD; discard all changes |
git reset <file> |
Unstage a specific file |
git reflog |
Find commits to recover after reset |
git diff --cached |
See what is currently staged |
The Three Modes Explained
Working Dir Staging Area HEAD
--soft ✓ ✓ ← moves back
--mixed (default) ✓ ← ← moves back
--hard ← ← ← moves back
✓ = unchanged ← = reset to match the target commit
⚠️ Danger Zone
git reset --hard permanently discards uncommitted changes.
Always check git stash or git reflog if you need a safety net.
Tasks
01. View Current History
See the commits before resetting.
Hint: git log --oneline
02. Soft Reset
Undo the last commit but keep changes staged.
Hint: git reset --soft HEAD~1
Solution
03. Mixed Reset (Default)
Undo the last commit and unstage the changes.
Hint: git reset HEAD~1
Solution
04. Hard Reset
Completely discard the last commit and all changes. Destructive!
Hint: git reset --hard HEAD~1
Solution
05. Reset a Single File
Unstage a specific file without moving HEAD.
Hint: git reset HEAD <file>
06. Compare the Three Modes
Make 3 commits, then try each reset mode and observe the differences.
Hint: git status after each reset shows the key difference
Solution
07. Recover from a Hard Reset
Use reflog to find and restore a commit after hard reset.
Hint: git reflog, git reset --hard <hash>
Solution
08. Find the Password
Use git reflog or git log to find the hidden password in this repo’s history.
Hint: the password may be in a commit that was “reset” away
[Protected] Room 23 - Git Revert: Safe Undo
GIT REVERT: SAFE UNDO
Room 23 - Reverting Commits
📜 Your mission
Revert creates a NEW commit that undoes a previous commit. Safe for shared branches!
DIFFERENCE FROM RESET:
reset→ rewrites history (dangerous for shared branches)-
revert→ adds new history (safe for shared branches) -
View the history and find the “bad commit”:
git log --oneline
-
Revert a specific commit:
git revert <commit-hash>- (Opens editor for the revert commit message)
-
Revert without auto-committing:
git revert --no-commit <hash>
-
Revert a merge commit:
git revert -m 1 <merge-commit-hash>
-
Revert the commit with message “BUGGY COMMIT” in this repo.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git revert HEAD |
Revert the latest commit |
git revert <hash> |
Revert a specific commit |
git revert --no-commit |
Apply reversal without committing |
git revert --abort |
Abort an in-progress revert |
git revert --continue |
Continue after resolving conflicts |
git revert HEAD~3..HEAD |
Revert a range of commits |
Revert vs Reset
reset: A --- B --- C → A --- B (C is gone from history)
revert: A --- B --- C --- C' → A --- B --- C --- C' (C' undoes C)
Revert is SAFE for shared branches - it never rewrites history.
Reset should only be used on local/private branches.
Tasks
01. View the History
Find the “bad commit” you need to revert.
Hint: git log --oneline
Solution
02. Revert a Commit
Create a new commit that undoes the buggy one.
Hint: git revert <hash>
Solution
03. Revert Without Auto-Committing
Apply the reversal but leave changes staged for you to review.
Hint: git revert --no-commit <hash>
Solution
04. Revert the Latest Commit
Revert HEAD (the most recent commit).
Hint: git revert HEAD
05. Revert a Range of Commits
Undo multiple consecutive commits.
Hint: git revert HEAD~3..HEAD
Solution
06. Abort a Revert in Progress
Cancel a revert if you change your mind mid-conflict.
Hint: git revert --abort
Solution
07. Verify History Is Preserved
Confirm that revert ADDS history (unlike reset).
Hint: git log --oneline
Solution
08. Find the Password
Revert the “BUGGY COMMIT” and read the resulting file contents.
Hint: git revert <hash>, then check the files
Solution
[Protected] Room 24 - Git Commit --Amend: Fixing Mistakes
GIT COMMIT –AMEND: FIXING MISTAKES
Room 24 - Amending Commits
📜 Your mission
Amend lets you modify the MOST RECENT commit.
-
View the last commit:
git log -1
-
Fix the commit message:
git commit --amend -m "Better commit message"
-
Add forgotten files to the last commit:
git add forgotten-file.txtgit commit --amend --no-edit
-
This repo’s last commit has a typo in its message and is missing a file. Fix both using
--amend. -
Compare before/after with:
git log -1git show HEAD
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git commit --amend |
Open editor to change last message |
git commit --amend -m "new msg" |
Replace last commit message |
git commit --amend --no-edit |
Amend files without changing message |
git commit --amend --author="Name <e>" |
Fix the author of the last commit |
git log -1 --format=fuller |
View full details of last commit |
git diff HEAD~1 |
See what the last commit changed |
What Amend Actually Does
Before: A --- B --- C (HEAD)
git commit --amend
After: A --- B --- C' (HEAD - new hash!)
Amend REPLACES the last commit with a new one.
The old commit (C) still exists in reflog but is no longer on any branch.
⚠️ Never amend commits that have been pushed
Amending rewrites history - only use on local, unpushed commits.
Tasks
01. View the Last Commit
See what the current last commit looks like.
Hint: git log -1, git show HEAD
Solution
02. Fix the Commit Message
Change the last commit’s message.
Hint: git commit --amend -m "new message"
Solution
03. Add a Forgotten File
Stage a file and add it to the last commit without changing the message.
Hint: git add <file>, git commit --amend --no-edit
Solution
04. Change the Author
Fix the author info on the last commit.
Hint: git commit --amend --author="Name <email>"
Solution
05. Verify the Hash Changed
Confirm that amending creates a new commit with a different hash.
Hint: git log --oneline, git reflog
Solution
06. Amend Content of the Last Commit
Modify a file that was already in the last commit and include the change.
Hint: edit the file, git add, git commit --amend --no-edit
Solution
07. Find the Password
Fix the typo in the commit message and add the forgotten file. The password is revealed in the process.
Hint: git commit --amend, check git show HEAD
Solution
[Protected] Room 25 - Git Blame: Line-by-Line Detective
GIT BLAME: LINE-BY-LINE DETECTIVE
Room 25 - Who Wrote That?
📜 Your mission
Blame shows who last modified each line of a file and when.
-
Blame a file - see who wrote each line:
git blame app.txt
-
Blame with date format:
git blame -e app.txt(show emails)
-
Blame a specific range of lines:
git blame -L 5,10 app.txt
-
Blame ignoring whitespace:
git blame -w app.txt
-
This repo’s
codebase.txtwas written by multiple authors. Find the line written by “Spy” - it contains the password.git blame codebase.txt | grep "Spy"
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git blame <file> |
Show per-line commit info |
git blame -L 5,10 <file> |
Blame only lines 5–10 |
git blame -w <file> |
Ignore whitespace changes |
git blame -M <file> |
Detect moved lines within a file |
git blame -C <file> |
Detect lines moved from other files |
git log -p <file> |
Show full patch history of a file |
git blame --date=short |
Show dates in short format |
Reading Blame Output
a1b2c3d4 (Alice 2025-03-15 5) echo "Hello World"
^^^^^^^^ ^^^^^ ^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^
commit author date line content
Each line shows the LAST commit that touched it - not who originally wrote it.
Use git log --follow <file> to trace a file through renames.
Tasks
01. Blame a Whole File
See who last modified each line of app.txt.
Hint: git blame app.txt
Solution
02. Blame a Line Range
Check only lines 5-10 of a file.
Hint: git blame -L 5,10 <file>
03. Show Emails in Blame
Display author email addresses instead of names.
Hint: git blame -e <file>
04. Ignore Whitespace Changes
Skip blame attribution for commits that only changed whitespace.
Hint: git blame -w <file>
Solution
05. Detect Moved Lines
Find lines that were moved from elsewhere in the same file.
Hint: git blame -M <file>
Solution
06. Detect Copied Lines
Find lines copied from other files.
Hint: git blame -C <file>
Solution
07. View Full History of a File
See every change ever made to a file.
Hint: git log -p <file>
Solution
08. Find the Password
Blame codebase.txt and find the line written by “Spy”.
Hint: git blame codebase.txt | grep "Spy"
[Protected] Room 26 - Git Bisect: Bug Hunting
GIT BISECT: BUG HUNTING
Room 26 - Binary Search for Bugs
📜 Your mission
Bisect uses binary search to find the EXACT commit that introduced a bug.
-
This repo has 20 commits. Somewhere a bug was introduced. The file
test.shreturns exit code 1 (fail) on the bad commit. -
Start bisecting:
git bisect start
-
Mark the current commit as bad:
git bisect bad
-
Mark a known good commit:
git bisect good <earliest-commit-hash>
-
Git will checkout a middle commit. Test it:
bash test.sh- If it passes:
git bisect good - If it fails:
git bisect bad
-
Repeat until Git finds the first bad commit!
-
Automate it:
git bisect start HEAD <good-hash>git bisect run bash test.sh
-
When done:
git bisect reset
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git bisect start |
Begin a bisect session |
git bisect bad |
Mark current commit as bad |
git bisect good <hash> |
Mark a commit as good |
git bisect reset |
End bisect and return to original HEAD |
git bisect skip |
Skip a commit that can’t be tested |
git bisect log |
Show bisect steps so far |
git bisect run <script> |
Automate bisect with a test script |
How Bisect Works
good bad
↓ ↓
A --- B --- C --- D --- E --- F --- G --- H --- I
↑
Git checks here first (midpoint)
If D is good → bug is in E..I → check midpoint of E..I
If D is bad → bug is in A..D → check midpoint of A..D
Binary search finds the culprit in O(log n) steps.
100 commits? Only ~7 checks needed!
Tasks
01. Start a Bisect Session
Begin the binary search.
Hint: git bisect start
02. Mark Current as Bad
Tell Git the current commit has the bug.
Hint: git bisect bad
03. Mark a Known Good Commit
Find the earliest commit and mark it as good.
Hint: git log --oneline --reverse, git bisect good <hash>
Solution
04. Test and Mark Each Step
Run the test and mark the commit as good or bad.
Hint: bash test.sh, then git bisect good or git bisect bad
Solution
05. Automate Bisect
Let Git run the test script automatically.
Hint: git bisect run bash test.sh
Solution
06. View Bisect Log
See the steps taken so far.
Hint: git bisect log
07. End the Bisect Session
Return to your original branch.
Hint: git bisect reset
08. Find the Password
Use bisect to find the first bad commit. The commit message contains the password.
Hint: git bisect run bash test.sh, then read the commit message
Solution
[Protected] Room 27 - Git Reflog: Your Safety Net
GIT REFLOG: YOUR SAFETY NET
Room 27 - Recovering Lost Work
📜 Your mission
Reflog records EVERY move of HEAD - even after reset --hard!
-
View the reflog:
git reflog
-
Each entry shows:
- The commit hash
- What action was performed (commit, checkout, reset, etc.)
- The position (
HEAD@{0}= current,HEAD@{1}= previous, etc.)
-
This repo had a commit that was “lost” via
reset --hard. Find it using reflog:git reflog
-
Recover the lost commit:
git checkout <lost-hash>- (or:
git branch recovery <lost-hash>)
-
The lost commit contains a file with the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git reflog |
Show HEAD movement history |
git reflog show <branch> |
Show reflog for a specific branch |
git checkout <hash> |
Jump to a reflog entry |
git branch recovered <hash> |
Create branch from a lost commit |
git reset --hard <hash> |
Restore HEAD to a reflog entry |
git reflog expire --expire=now |
Clear the reflog (dangerous!) |
Understanding the Reflog
$ git reflog
a1b2c3d HEAD@{0}: commit: add feature
f4e5d6c HEAD@{1}: reset: moving to HEAD~2
7g8h9i0 HEAD@{2}: commit: work in progress
b1c2d3e HEAD@{3}: checkout: moving from main to feature
Reflog records every HEAD movement for ~90 days.
Even after reset --hard, your commits are still recoverable!
💡 Pro Tip
Reflog is LOCAL only - it is never pushed to a remote. If you lose work, check the reflog before panicking.
Tasks
01. View the Reflog
See every HEAD movement in this repo.
Hint: git reflog
Solution
02. Understand Reflog Entries
Identify what action each line represents.
Hint: look at the action description after the hash
Solution
03. Find a Lost Commit
Identify commits that were “lost” by a hard reset.
Hint: git reflog, look for reset: moving to entries
Solution
04. Recover a Lost Commit
Create a branch from the lost commit to restore it.
Hint: git branch <name> <hash>
Solution
05. View Branch-Specific Reflog
See the reflog for a specific branch.
Hint: git reflog show <branch>
06. Use Reflog References Directly
Reference previous HEAD positions using HEAD@{N} syntax.
Hint: git show HEAD@{1}, git diff HEAD@{0} HEAD@{2}
Solution
07. Find the Password
A commit was lost via reset --hard. Use the reflog to find and inspect it.
Hint: git reflog, find the lost hash, git show <hash>
Solution
[Protected] Room 28 - Git Alias: Custom Shortcuts
GIT ALIAS: CUSTOM SHORTCUTS
Room 28 - Speed Up Your Workflow
📜 Your mission
Create your own Git shortcuts to work faster!
-
Create a simple alias:
git config --global alias.st statusgit config --global alias.co checkoutgit config --global alias.br branchgit config --global alias.ci commit
-
Create complex aliases:
git config --global alias.lg "log --oneline --graph --all"git config --global alias.last "log -1 HEAD"git config --global alias.unstage "restore --staged"
-
Use shell commands in aliases (prefix with
!):git config --global alias.visual "!gitk"
-
List all aliases:
git config --get-regexp alias
-
This repo has a custom alias already configured. Find it:
git config --get-regexp aliasRun the alias to reveal the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git config --global alias.st status |
Create a global alias |
git config alias.co checkout |
Create a repo-level alias |
git config --get-regexp alias |
List all aliases |
git config --global --unset alias.st |
Remove an alias |
git st |
Use the alias |
git config --global -e |
Edit global config directly |
Popular Aliases
# Quick shortcuts
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
# Fancy log
git config --global alias.lg "log --oneline --graph --decorate --all"
# Show last commit
git config --global alias.last "log -1 HEAD"
# Unstage files
git config --global alias.unstage "reset HEAD --"
Tasks
01. Create Simple Aliases
Set up common shortcuts.
Hint: git config alias.st status
Solution
02. Test Your Aliases
Run the aliases to verify they work.
Hint: git st, git br
03. Create a Complex Alias
Build a fancy log alias with graph and colors.
Hint: git config alias.lg "log --oneline --graph --all"
Solution
04. Create a Last-Commit Alias
An alias that shows the last commit.
Hint: git config alias.last "log -1 HEAD"
05. Create a Shell Command Alias
Use ! to run arbitrary shell commands.
Hint: git config alias.root '!pwd'
06. List All Aliases
See every alias configured in this repo.
Hint: git config --get-regexp alias
Solution
07. Remove an Alias
Delete an alias you no longer need.
Hint: git config --unset alias.<name>
08. Find the Password
This repo has a custom alias already defined. Find it and run it.
Hint: git config --get-regexp alias
Solution
[Protected] Room 29 - Gitignore: Hiding Files from Git
GITIGNORE: HIDING FILES FROM GIT
Room 29 - Ignoring the Noise
📜 Your mission
.gitignore tells Git which files/directories to IGNORE.
-
View the current
.gitignore:cat .gitignore
-
Common patterns:
*.log- ignore all .log filesbuild/- ignore the build directory!important.log- DO track this specific file (exception)**/temp- ignoretempin any directorydoc/*.txt- ignore .txt in doc/ only (not subdirs)
-
Check what’s being ignored:
git status --ignored
-
Force-add an ignored file:
git add -f secret.env
-
Remove a file that’s already tracked:
git rm --cached file-to-untrack.txt
-
This room has files that SHOULD be ignored but aren’t in
.gitignore. Create the proper.gitignoreto ignore:*.log,node_modules/,.env,*.pyc -
Global gitignore:
git config --global core.excludesfile ~/.gitignore_global
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git check-ignore -v <file> |
Check why a file is ignored |
git status --ignored |
Show ignored files in status |
git add -f <file> |
Force-add an ignored file |
git rm --cached <file> |
Stop tracking a previously added file |
git check-ignore * |
List all ignored files in directory |
git ls-files --ignored --exclude-standard |
List all ignored tracked files |
.gitignore Patterns
# Compiled output
*.o
*.class
build/
# Dependencies
node_modules/
vendor/
# IDE files
.vscode/
.idea/
*.swp
# OS files
.DS_Store
Thumbs.db
# Environment / secrets
.env
*.pem
💡 Precedence
.gitignore files can exist at any level. Patterns in deeper
directories override higher ones. A global gitignore can be set with
git config --global core.excludesFile ~/.gitignore_global
Tasks
01. View Current .gitignore
See what’s already being ignored.
Hint: cat .gitignore
02. Check Ignored Files
See which files are currently being ignored.
Hint: git status --ignored
03. Add Ignore Patterns
Add patterns to ignore log files, node_modules, .env, and .pyc files.
Hint: echo "pattern" >> .gitignore
Solution
04. Check Why a File Is Ignored
Diagnose which rule is ignoring a specific file.
Hint: git check-ignore -v <file>
Solution
05. Force-Add an Ignored File
Track a file that matches an ignore pattern.
Hint: git add -f <file>
06. Stop Tracking a File
Remove a file from Git’s tracking without deleting it from disk.
Hint: git rm --cached <file>
Solution
07. Use Negation Patterns
Ignore all .log files except important.log.
Hint: !important.log in .gitignore
Solution
08. Find the Password
Create the proper .gitignore, then run git status to see what’s revealed.
Hint: check the files that appear in git status after updating .gitignore
Solution
[Protected] Room 30 - Gitattributes: File-Level Rules
GITATTRIBUTES: FILE-LEVEL RULES
Room 30 - Fine-Grained File Control
📜 Your mission
.gitattributes controls how Git handles specific file types.
-
Create a
.gitattributesfile with patterns like:*.txt text*.jpg binary*.sh text eol=lf*.bat text eol=crlf
-
Line ending normalization:
* text=auto- auto-detect text files*.sh text eol=lf- always use LF for .sh files*.bat text eol=crlf- always use CRLF for .bat files
-
Binary files:
*.png binary*.zip binary
-
Diff drivers:
*.md diff=markdown
-
Export-ignore (excluded from
git archive):.gitignore export-ignoretests/ export-ignore
-
Merge strategies:
database.xml merge=ours
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
echo "* text=auto" > .gitattributes |
Normalize line endings |
echo "*.png binary" >> .gitattributes |
Mark PNG files as binary |
git check-attr -a <file> |
Show attributes for a file |
git check-attr diff <file> |
Check the diff attribute |
git add --renormalize . |
Re-apply attributes to tracked files |
cat .gitattributes |
View current attribute rules |
Common .gitattributes Patterns
# Auto-detect text files and normalize line endings
* text=auto
# Force specific line endings
*.sh text eol=lf
*.bat text eol=crlf
# Binary files - no diff, no merge
*.png binary
*.jpg binary
*.zip binary
# Custom diff for specific file types
*.md diff=markdown
# Merge strategy: keep ours on conflict
database.xml merge=ours
# Linguist: language statistics for GitHub
docs/* linguist-documentation
Tasks
01. Create a .gitattributes File
Set up auto line-ending normalization.
Hint: echo "* text=auto" > .gitattributes
02. Set Line Endings Per File Type
Force LF for shell scripts and CRLF for batch files.
Hint: *.sh text eol=lf, *.bat text eol=crlf
03. Mark Binary Files
Tell Git to treat image and archive files as binary.
Hint: *.png binary
04. Check File Attributes
Inspect what attributes apply to a specific file.
Hint: git check-attr -a <file>
Solution
05. Set Export-Ignore
Exclude files from git archive exports.
Hint: .gitignore export-ignore
Solution
06. Set a Custom Merge Strategy
Keep your version of a config file during merges.
Hint: database.xml merge=ours
Solution
07. Re-Normalize Tracked Files
Apply the new attributes to already-tracked files.
Hint: git add --renormalize .
Solution
08. Find the Password
Inspect the existing .gitattributes or check file attributes for a clue.
Hint: cat .gitattributes, git check-attr -a *
Solution
[Protected] Room 31 - Git Hooks: Automation Triggers
GIT HOOKS: AUTOMATION TRIGGERS
Room 31 - Hooking Into Git
📜 Your mission
Hooks are scripts that Git runs automatically at certain events.
-
Explore the hooks directory:
ls .git/hooks/- (All
.samplefiles - remove.sampleto activate)
-
Create a pre-commit hook:
-
Common hooks:
pre-commit→ runs before commit (linting, tests)commit-msg→ validate commit message formatpre-push→ runs before push (CI checks)post-merge→ runs after merge (install deps)pre-rebase→ runs before rebase
-
This room has a
commit-msghook. Read it to find the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
ls .git/hooks/ |
List available hook samples |
chmod +x .git/hooks/pre-commit |
Make a hook executable |
git commit --no-verify |
Skip hooks for this commit |
cat .git/hooks/pre-commit.sample |
View the sample pre-commit hook |
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit |
Activate sample hook |
git config core.hooksPath <dir> |
Set a custom hooks directory |
Common Git Hooks
CLIENT-SIDE HOOKS:
pre-commit → Runs before commit is created (lint, tests)
prepare-commit-msg → Modify the default commit message
commit-msg → Validate or format commit message
pre-push → Runs before pushing (run tests)
post-checkout → Runs after checkout (install deps)
SERVER-SIDE HOOKS:
pre-receive → Runs before accepting a push
update → Runs once per branch being updated
post-receive → Runs after push is accepted (deploy)
💡 Sharing Hooks
Hooks in .git/hooks/ are NOT committed to the repo.
To share hooks, store them in a directory like .githooks/
and set: git config core.hooksPath .githooks
Tasks
01. Explore the Hooks Directory
List all available hook samples.
Hint: ls .git/hooks/
Solution
02. Read a Sample Hook
Examine a sample hook to understand the format.
Hint: cat .git/hooks/pre-commit.sample
03. Create a Pre-Commit Hook
Write a hook that rejects commits containing “TODO”.
Hint: write a script to .git/hooks/pre-commit
Solution
04. Test the Hook
Try committing a file with “TODO” and observe the rejection.
Hint: echo "TODO: fix this" > test.txt, git add test.txt, git commit -m "test"
Solution
05. Bypass a Hook
Skip the hook check for a one-time commit.
Hint: git commit --no-verify
Solution
06. Create a Commit-Msg Hook
Validate that commit messages follow a pattern.
Hint: .git/hooks/commit-msg receives the message file path as $1
Solution
07. Set a Custom Hooks Path
Share hooks with the team by storing them in the repo.
Hint: git config core.hooksPath <dir>
Solution
08. Find the Password
Read the commit-msg hook in this repo. It contains the password.
Hint: cat .git/hooks/commit-msg
[Protected] Room 32 - Git Submodule: Repos Within Repos
GIT SUBMODULE: REPOS WITHIN REPOS
Room 32 - Managing Submodules
📜 Your mission
Submodules let you include another Git repository inside yours.
-
Add a submodule:
git submodule add <url> path/to/submodule
-
Check submodule status:
git submodule status
-
When cloning a repo with submodules:
git clone --recurse-submodules <url>- OR after cloning:
git submodule initgit submodule update
-
Update submodules to latest:
git submodule update --remote
-
View
.gitmodulesfile:cat .gitmodules
-
This repo has submodules configured. Explore the
.gitmodulesfile.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git submodule add <url> <path> |
Add a new submodule |
git submodule status |
Show current commit of each submod |
git submodule update --init --recursive |
Initialize and fetch submodules |
git submodule update --remote |
Update submodules to latest remote |
git submodule foreach 'git pull origin main' |
Run command in every submodule |
git rm <submodule-path> |
Remove a submodule |
cat .gitmodules |
View submodule configuration |
Submodule Structure
my-project/
├── .gitmodules ← tracks submodule URLs and paths
├── .git/
│ └── modules/ ← actual submodule git data
├── src/
└── libs/
└── shared-lib/ ← submodule (pinned to a specific commit)
├── .git ← file pointing to ../../.git/modules/...
└── ...
Submodules are pinned to a SPECIFIC COMMIT, not a branch.
You must explicitly update them to pull in new changes.
Tasks
01. Check for Submodules
See if this repo has any submodules configured.
Hint: cat .gitmodules, git submodule status
Solution
02. Initialize Submodules
Register and clone submodule content.
Hint: git submodule init, git submodule update
Solution
03. Explore Submodule Content
Enter a submodule directory and see its own git history.
Hint: cd <submodule-path>, git log --oneline
04. Update Submodules to Latest
Pull the latest changes from the submodule’s remote.
Hint: git submodule update --remote
Solution
05. Run a Command in All Submodules
Execute a command inside every submodule.
Hint: git submodule foreach '<command>'
Solution
06. Add a New Submodule
Add an external repo as a submodule.
Hint: git submodule add <url> <path>
Solution
07. Find the Password
Explore the .gitmodules file or the submodule content for the password.
Hint: cat .gitmodules, explore the submodule directories
Solution
[Protected] Room 33 - Git Worktree: Parallel Branches
GIT WORKTREE: PARALLEL BRANCHES
Room 33 - Multiple Working Directories
📜 Your mission
Worktree lets you check out MULTIPLE branches simultaneously in separate directories!
-
List current worktrees:
git worktree list
-
Create a new worktree for a branch:
git worktree add ../hotfix-dir hotfix-branch- (Now you have TWO working directories!)
-
Create a worktree with a new branch:
git worktree add -b new-feature ../feature-dir
-
Switch between them:
cd ../hotfix-dir(you’re on hotfix-branch)cd ../repo(you’re on main)
-
Remove a worktree:
git worktree remove ../hotfix-dir
-
Prune stale worktrees:
git worktree prune
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git worktree list |
List all linked worktrees |
git worktree add <path> <branch> |
Create worktree for existing branch |
git worktree add -b <new> <path> |
Create worktree with new branch |
git worktree remove <path> |
Remove a worktree |
git worktree prune |
Clean up stale worktree references |
git worktree lock <path> |
Prevent a worktree from being pruned |
How Worktrees Work
~/project/ (main worktree - main branch)
├── .git/
├── src/
└── ...
~/project-hotfix/ (linked worktree - hotfix branch)
├── .git ← file (points back to ~/project/.git)
├── src/
└── ...
Both directories share the SAME repository.
Each worktree checks out a DIFFERENT branch.
No need to stash, commit, or switch - just cd!
!!! tip “💡 Use Cases” - Review a PR while your current work stays untouched - Run tests on one branch while coding on another - Compare behavior across branches side by side
Tasks
01. List Current Worktrees
See how many worktrees this repo has.
Hint: git worktree list
02. Create a Worktree for an Existing Branch
Check out a branch in a separate directory.
Hint: git worktree add <path> <branch>
Solution
03. Create a Worktree with a New Branch
Create a new branch and check it out in a separate directory.
Hint: git worktree add -b <new-branch> <path>
Solution
04. Work in Multiple Directories
Switch between worktrees and verify each is on a different branch.
Hint: cd <dir>, git branch
05. Verify Shared Repository
Confirm both worktrees share the same Git data.
Hint: cat .git in the linked worktree
Solution
06. Remove a Worktree
Clean up a worktree you no longer need.
Hint: git worktree remove <path>
Solution
07. Find the Password
Create a worktree for each branch and look for the password file.
Hint: git branch -a, then create worktrees and explore
Solution
[Protected] Room 34 - Git Sparse-Checkout: Partial Repos
GIT SPARSE-CHECKOUT: PARTIAL REPOS
Room 34 - Checkout Only What You Need
📜 Your mission
Sparse checkout lets you check out only PART of a large repository.
-
Enable sparse checkout:
git sparse-checkout init
-
Set which directories to include:
git sparse-checkout set src/ docs/
-
List what’s included:
git sparse-checkout list
-
Add more directories:
git sparse-checkout add tests/
-
Cone mode (faster, directory-based):
git sparse-checkout init --conegit sparse-checkout set src/frontend src/backend
-
Disable sparse checkout:
git sparse-checkout disable
-
This is useful for HUGE monorepos where you only need part of the code.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git sparse-checkout init --cone |
Enable cone-mode sparse-checkout |
git sparse-checkout set <dirs> |
Set which directories to include |
git sparse-checkout add <dir> |
Add a directory to the sparse set |
git sparse-checkout list |
List currently included directories |
git sparse-checkout disable |
Disable sparse-checkout (full repo) |
git clone --sparse <url> |
Clone with sparse-checkout enabled |
Sparse-Checkout in Action
Full repo on remote:
├── src/
│ ├── frontend/
│ └── backend/
├── docs/
├── tests/
├── infra/
└── scripts/
After: git sparse-checkout set src/backend docs/
Your working directory:
├── src/
│ └── backend/ ✓ checked out
├── docs/ ✓ checked out
└── (everything else is hidden but still in .git)
Git history is COMPLETE - only the working directory is filtered.
💡 Cone Mode vs Non-Cone
--cone mode (recommended) works at the directory level and is fast.
Non-cone mode uses gitignore-style patterns for file-level control
but is slower on large repos.
Tasks
01. Enable Sparse-Checkout
Set up sparse-checkout in cone mode.
Hint: git sparse-checkout init --cone
02. Select Directories
Choose which directories to include.
Hint: git sparse-checkout set <dirs>
03. List What’s Included
See which paths are currently checked out.
Hint: git sparse-checkout list
04. Add More Directories
Include additional directories without removing existing ones.
Hint: git sparse-checkout add <dir>
05. Verify History Is Complete
Confirm the full git history is available even with sparse checkout.
Hint: git log --oneline --all
Solution
06. Disable Sparse-Checkout
Return to a full checkout.
Hint: git sparse-checkout disable
07. Find the Password
Use sparse-checkout to include the hidden secrets/ directory.
Hint: git sparse-checkout set secrets/
Solution
[Protected] Room 35 - Git Assume-Unchanged: Hiding Local Edits
GIT ASSUME-UNCHANGED: HIDING LOCAL EDITS
Room 35 - Invisible Local Changes
📜 Your mission
Sometimes you need to modify a tracked file locally without Git noticing.
-
Mark a file as “assume unchanged”:
git update-index --assume-unchanged config.local.txt- Now Git IGNORES local changes to this file!
-
Modify the file - Git won’t show it in status:
echo "local override" >> config.local.txtgit status(no changes shown!)
-
List assume-unchanged files:
git ls-files -v | grep ^h- (lowercase
h= assume-unchanged)
-
Undo assume-unchanged:
git update-index --no-assume-unchanged config.local.txt
-
Alternative: skip-worktree (stronger):
git update-index --skip-worktree config.local.txtgit ls-files -v | grep ^S
-
Use cases:
- Local config overrides
- IDE settings files
- Environment-specific files
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git update-index --assume-unchanged <file> |
Ignore local changes to a file |
git update-index --no-assume-unchanged <file> |
Resume tracking changes |
git ls-files -v \| grep '^h' |
List all assume-unchanged files |
git update-index --skip-worktree <file> |
Stronger variant (survives reset) |
git update-index --no-skip-worktree <file> |
Undo skip-worktree |
git ls-files -v \| grep '^S' |
List all skip-worktree files |
assume-unchanged vs skip-worktree
assume-unchanged skip-worktree
──────────────────────────────────────────────────────────────
Purpose Performance hint User intent
Survives checkout No (may be reset) Yes
Survives reset No Yes
Use case Large files, build opts Local config overrides
Flag in ls-files -v h (lowercase) S (uppercase)
WHEN TO USE WHICH:
assume-unchanged → "I know this file won't change, skip checking"
skip-worktree → "I changed this file locally, don't overwrite it"
⚠️ Not a replacement for .gitignore
These flags only work on TRACKED files. For untracked files,
use .gitignore instead.
Tasks
01. Mark a File as Assume-Unchanged
Hide local changes to a config file from Git.
Hint: git update-index --assume-unchanged <file>
02. Modify Without Git Noticing
Edit the file and verify Git doesn’t show changes.
Hint: echo >> config.local.txt, git status
Solution
03. List Assume-Unchanged Files
Find all files marked with the assume-unchanged flag.
Hint: git ls-files -v | grep '^h'
04. Remove the Flag
Resume tracking changes to the file.
Hint: git update-index --no-assume-unchanged <file>
Solution
05. Use Skip-Worktree Instead
Apply the stronger variant that survives resets.
Hint: git update-index --skip-worktree <file>
Solution
06. Undo Skip-Worktree
Remove the skip-worktree flag.
Hint: git update-index --no-skip-worktree <file>
Solution
07. Find the Password
Check which file has the assume-unchanged flag set. Read its real content.
Hint: git ls-files -v | grep '^h', then cat that file
Solution
[Protected] Room 36 - Git Clean: Remove Untracked Files
GIT CLEAN: REMOVE UNTRACKED FILES
Room 36 - Sweep the Working Tree
📜 Your mission
Clean removes files that are NOT tracked by Git.
-
See what would be cleaned (dry run):
git clean -n
-
Remove untracked files:
git clean -f
-
Remove untracked directories too:
git clean -fd
-
Remove ignored files as well:
git clean -fX(ONLY ignored files)git clean -fx(untracked AND ignored)
-
Interactive clean:
git clean -i
-
This room has tons of “junk” files. Clean them up, but be careful NOT to delete
important.txt! Use:git clean -nfirst to preview.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git clean -n |
Dry run - show what WOULD be removed |
git clean -f |
Force remove untracked files |
git clean -fd |
Remove untracked files AND directories |
git clean -fX |
Remove only files matched by .gitignore |
git clean -fx |
Remove ALL untracked files (ignored + unignored) |
git clean -i |
Interactive mode - pick what to delete |
Clean Modes Cheat Sheet
Untracked Ignored Directories
───────────────────────────────────────────────────────
git clean -f ✅ ❌ ❌
git clean -fd ✅ ❌ ✅
git clean -fX ❌ ✅ ❌
git clean -fx ✅ ✅ ❌
git clean -fdx ✅ ✅ ✅
git clean -fdX ❌ ✅ ✅
Safety tip: ALWAYS run git clean -n first to preview!
⚠️ Destructive Operation
git clean -f permanently deletes files that are NOT tracked by Git.
There is no undo - these files are gone forever!
Tasks
01. Preview What Would Be Cleaned
Dry-run to see what clean would remove.
Hint: git clean -n
02. Remove Untracked Files
Delete untracked files (not directories).
Hint: git clean -f
03. Remove Untracked Directories Too
Clean untracked files AND directories.
Hint: git clean -fd
04. Clean Only Ignored Files
Remove files matched by .gitignore patterns.
Hint: git clean -fX
Solution
05. Use Interactive Clean
Pick and choose what to delete.
Hint: git clean -i
Solution
06. Nuclear Clean (Everything)
Remove ALL untracked files, directories, AND ignored files.
Hint: git clean -fdx
Solution
07. Find the Password
Clean up the junk files, then check what remains. The password is in a tracked file revealed after cleaning.
Hint: git clean -fd, then ls and cat the remaining files
Solution
[Protected] Room 37 - Git Archive: Export Without .git
GIT ARCHIVE: EXPORT WITHOUT .GIT
Room 37 - Package Your Code
📜 Your mission
Archive creates a tarball or zip of your repo WITHOUT the .git directory.
-
Create a tar archive:
git archive --format=tar HEAD > project.tar
-
Create a zip:
git archive --format=zip HEAD > project.zip
-
Archive a specific branch/tag:
git archive --format=tar v1.0 > release-v1.0.tar
-
Archive a subdirectory:
git archive HEAD src/ > src-only.tar
-
Archive with prefix (adds a directory wrapper):
git archive --prefix=myproject/ HEAD > myproject.tar
-
Compress with gzip:
git archive HEAD | gzip > project.tar.gz
-
.gitattributes:export-ignoreFiles marked withexport-ignoreare EXCLUDED from archives.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git archive --format=tar HEAD |
Create a tar archive of HEAD |
git archive --format=zip HEAD |
Create a zip archive of HEAD |
git archive --prefix=dir/ HEAD |
Add a prefix directory to all paths |
git archive HEAD src/ |
Archive only specific paths |
git archive v1.0 -o release.tar.gz |
Archive a specific tag |
git archive --remote=<url> HEAD |
Archive from a remote repository |
Archive vs Clone
git clone git archive
─────────────────────────────────────────────────
Full repo + .git history Snapshot only
Can push/pull Read-only export
Large download Minimal size
For development For distribution
Use cases for git archive:
┌─────────────────────────────────────────┐
│ • Release tarballs for distribution │
│ • CI/CD build inputs │
│ • Sharing code without history │
│ • Creating deployment packages │
└─────────────────────────────────────────┘
Tasks
01. Create a Tar Archive
Export the current HEAD as a tar file.
Hint: git archive --format=tar HEAD > project.tar
Solution
02. Create a Zip Archive
Export as a zip file.
Hint: git archive --format=zip HEAD > project.zip
Solution
03. Archive with a Prefix Directory
Wrap the archive contents in a named directory.
Hint: git archive --prefix=myproject/ HEAD
Solution
04. Archive a Specific Tag or Branch
Export a release version.
Hint: git archive v1.0
05. Archive Only a Subdirectory
Export just part of the repo.
Hint: git archive HEAD src/
Solution
06. Verify No .git in Archive
Confirm the archive doesn’t contain Git history.
Hint: tar -tf project.tar | grep .git
07. Find the Password
Archive the repo and inspect its contents. Or explore tags for the password.
Hint: git tag, git archive <tag>, or check the file contents
[Protected] Room 38 - Git Bundle: Offline Transfer
GIT BUNDLE: OFFLINE TRANSFER
Room 38 - Sneakernet Git
📜 Your mission
Bundle packages a repo (or part of it) into a single file for offline transfer.
-
Create a bundle of the entire repo:
git bundle create repo.bundle --all
-
Bundle only specific branches:
git bundle create main.bundle main
-
Bundle only new commits:
git bundle create updates.bundle HEAD~5..HEAD
-
Verify a bundle:
git bundle verify repo.bundle
-
Clone from a bundle:
git clone repo.bundle my-clone
-
Fetch from a bundle:
git fetch repo.bundle main:refs/remotes/bundle/main
-
Use cases:
- Transfer repos without network access
- Sneakernet (USB drive) Git
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git bundle create repo.bundle --all |
Bundle the entire repository |
git bundle create repo.bundle main |
Bundle a specific branch |
git bundle verify repo.bundle |
Check if a bundle is valid |
git clone repo.bundle my-clone |
Clone from a bundle file |
git fetch repo.bundle main:other-main |
Fetch branches from a bundle |
git bundle create inc.bundle main ^origin/main |
Create an incremental bundle |
Bundle Workflow
mermaid
flowchart LR
subgraph A["Machine A (no network)"]
A1["git bundle create\nrepo.bundle --all"] --> B1["📦 .bundle"]
end
B1 -- "USB / email" --> B2["📦 .bundle"]
subgraph B["Machine B"]
B2 --> C1["git clone\nrepo.bundle"]
C1 --> C2["✅ Full repo!"]
end
Incremental updates:
- Day 1:
git bundle create full.bundle --all - Day 2:
git bundle create inc.bundle main ^<last-bundled-commit>
Tasks
01. Create a Full Bundle
Package the entire repository into a single file.
Hint: git bundle create repo.bundle --all
02. Verify a Bundle
Check that a bundle file is valid.
Hint: git bundle verify repo.bundle
03. Clone from a Bundle
Create a new repo from the bundle file.
Hint: git clone repo.bundle my-clone
Solution
04. Bundle a Specific Branch
Create a bundle containing only one branch.
Hint: git bundle create main.bundle main
05. Create an Incremental Bundle
Bundle only recent commits (not the entire history).
Hint: git bundle create inc.bundle HEAD~5..HEAD
06. Fetch from a Bundle
Use a bundle as a remote to fetch from.
Hint: git fetch repo.bundle main:refs/remotes/bundle/main
Solution
07. Find the Password
A bundle file is provided. Clone it or inspect its contents.
Hint: git bundle verify *.bundle, git clone *.bundle tmp
Solution
[Protected] Room 39 - Git Format-Patch & Am: Email Patches
GIT FORMAT-PATCH & AM: EMAIL PATCHES
Room 39 - Old-School Collaboration
📜 Your mission
Patches are the OLD-SCHOOL way to share changes - via email or files.
-
Create patches from commits:
git format-patch -3(last 3 commits → 3.patchfiles)git format-patch main..feature
-
View a patch file:
cat 0001-*.patch
-
Apply patches:
git am 0001-*.patch(apply and commit)git apply 0001-*.patch(apply without committing)
-
Apply a series of patches:
git am *.patch
-
If there’s a conflict during
am:git am --abort(cancel)git am --skip(skip this patch)git am --continue(after fixing conflicts)
-
Create a single combined patch:
git diff main..feature > combined.patchgit apply combined.patch
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git format-patch -3 |
Create patches for last 3 commits |
git format-patch main..feature |
Patches for all commits in a range |
git am *.patch |
Apply patch files as commits |
git am --abort |
Abort a failed patch apply |
git apply file.patch |
Apply a diff (no commit created) |
git diff > file.patch |
Generate a simple diff patch |
format-patch vs diff
| Feature | git format-patch |
git diff > file.patch |
|---|---|---|
| Output | One file per commit | Single file for all changes |
| Metadata | Preserves author & message | Only the diff |
| Apply with | git am |
git apply |
| Result | Creates commits | Only modifies working tree |
mermaid
flowchart LR
A["👤 Author"] -- "git format-patch" --> P["📄 .patch files"]
P -- "email" --> M["👤 Maintainer"]
M -- "git am *.patch" --> R["✅ Commits applied!"]
💡 Linux Kernel Workflow
The Linux kernel still uses git format-patch and git am as its
primary contribution method - patches are sent via email to mailing lists.
Tasks
01. Create Patches from Recent Commits
Generate patch files for the last 3 commits.
Hint: git format-patch -3
Solution
02. Read a Patch File
Examine the contents of a generated patch.
Hint: cat 0001-*.patch
03. Apply Patches with git am
Apply patch files as commits.
Hint: git am *.patch
Solution
04. Apply a Diff Patch
Apply a simple diff (no commit created).
Hint: git apply file.patch
Solution
05. Create Patches for a Branch Range
Generate patches for all commits on a feature branch.
Hint: git format-patch main..feature
06. Abort a Failed Patch Apply
Handle conflicts during git am.
Hint: git am --abort
Solution
07. Find the Password
Examine the patch files in this room. One of them contains the password.
Hint: ls *.patch, cat *.patch | grep -i password
[Protected] Room 40 - Git Grep: Search Tracked Files
GIT GREP: SEARCH TRACKED FILES
Room 40 - Find the Needle
📜 Your mission
git grep searches content in tracked files (faster than regular grep!).
-
Search for a pattern in current files:
git grep "TODO"
-
Search in a specific commit:
git grep "password" HEAD~5
-
Count occurrences:
git grep -c "function"
-
Show line numbers:
git grep -n "import"
-
Search with context:
git grep -C 3 "error"(3 lines context)
-
Search across ALL branches:
git grep "secret" $(git branch -a --format='%(refname)')
-
Search with regex:
git grep -e "def .*test" --and -e "assert"
-
This repo has a hidden password string. Use
git grepto find it in one of the old commits.git log --all -S "PASSWORD" --oneline
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git grep "TODO" |
Search tracked files for a pattern |
git grep -n "pattern" |
Show line numbers with matches |
git grep -c "pattern" |
Count matches per file |
git grep -C 3 "pattern" |
Show 3 lines of context around matches |
git grep -l "pattern" |
List only filenames with matches |
git log -S "string" |
Find commits that added/removed string |
git grep vs regular grep
git grep grep -r
════════ ══════
Only tracked files All files (incl. .git, node_modules)
Respects .gitignore Searches everything
Much faster on large repos Slower (no index)
Can search specific commits Only working directory
Power moves:
┌────────────────────────────────────────────────────────┐
│ git grep -n "TODO" -- '*.py' # Only Python files │
│ git grep "bug" HEAD~5 # Search older commit │
│ git grep -e "foo" --and -e "bar" # Both patterns │
│ git log -S "API_KEY" --all # Pickaxe search │
│ git log -G "regex" --all # Regex in diffs │
└────────────────────────────────────────────────────────┘
Tasks
01. Search for a Pattern
Find all occurrences of “TODO” in tracked files.
Hint: git grep "TODO"
Solution
02. Search with Line Numbers
Show exact line numbers for each match.
Hint: git grep -n "pattern"
03. Count Matches Per File
Get a summary of how many matches each file has.
Hint: git grep -c "pattern"
04. List Only Matching Filenames
Show just the file names, not the matched lines.
Hint: git grep -l "pattern"
05. Search with Context
Show surrounding lines for context.
Hint: git grep -C 3 "pattern"
06. Search in a Specific Commit
Search older versions of the codebase.
Hint: git grep "pattern" HEAD~5
07. Pickaxe Search
Find commits that added or removed a specific string.
Hint: git log -S "string"
Solution
08. Search Only Specific File Types
Limit search to Python files.
Hint: git grep "pattern" -- '*.py'
09. Find the Password
Use pickaxe or git grep to find the hidden password string.
Hint: git log --all -S "PASSWORD" --oneline, or git grep "password"
Solution
[Protected] Room 41 - Git Shortlog: Contributor Stats
GIT SHORTLOG: CONTRIBUTOR STATS
Room 41 - Who Did What?
📜 Your mission
Shortlog summarizes git log output by author.
-
View contributor summary:
git shortlog
-
Count commits per author:
git shortlog -sn(sorted by count, numbers only)
-
Shortlog with email:
git shortlog -sne
-
Shortlog for a range:
git shortlog v1.0..v2.0
-
Group by committer (not author):
git shortlog -c
-
This repo has contributions from many authors. Find who has the MOST commits. The contributor with the most commits has a username that IS the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git shortlog |
Group commits by author with messages |
git shortlog -s |
Show only commit counts |
git shortlog -sn |
Sort by number of commits (descending) |
git shortlog -sne |
Include email addresses, sorted |
git shortlog --no-merges |
Exclude merge commits |
git log --format='%aN' \| sort -u |
List unique contributors |
Reading the Output
$ git shortlog -sn
152 Alice Johnson
89 Bob Smith
34 Charlie Davis
$ git shortlog -sne
152 Alice Johnson <alice@example.com>
89 Bob Smith <bob@example.com>
34 Charlie Davis <charlie@example.com>
Use cases:
┌─────────────────────────────────────────────┐
│ • Generate release credits / CONTRIBUTORS │
│ • Audit who changed what │
│ • Identify code ownership │
│ • Measure team activity │
└─────────────────────────────────────────────┘
Pro tip: Pipe to head for top contributors
$ git shortlog -sn | head -10
Tasks
01. View Contributor Summary
List commits grouped by author.
Hint: git shortlog
Solution
02. Count Commits Per Author
Get a sorted count of commits by author.
Hint: git shortlog -sn
03. Include Email Addresses
Show author emails in the shortlog.
Hint: git shortlog -sne
04. Shortlog for a Range
View contributions between two tags or commits.
Hint: git shortlog v1.0..v2.0
05. Exclude Merge Commits
Get a cleaner view by excluding merges.
Hint: git shortlog --no-merges
06. List Unique Contributors
Get a plain list of all contributor names.
Hint: git log --format='%aN' | sort -u
07. Find the Password
The author with the MOST commits has a username that IS the password.
Hint: git shortlog -sn | head -1
[Protected] Room 42 - Git Describe: Human-Readable Names
GIT DESCRIBE: HUMAN-READABLE NAMES
Room 42 - Name That Commit
📜 Your mission
Describe gives you a human-readable name based on the nearest tag.
-
Describe the current commit:
git describe- Output:
v1.2-3-gabc1234 - Means: 3 commits after tag
v1.2, hashabc1234
-
Describe with more detail:
git describe --long(always show full format)git describe --tags(use lightweight tags too)git describe --all(use any ref, not just tags)
-
Describe an arbitrary commit:
git describe abc1234
-
This is useful for:
- Build version strings
- Release naming
- CI/CD pipelines
-
Create a tag and describe again - notice the difference.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git describe |
Describe using annotated tags only |
git describe --long |
Always show long format |
git describe --tags |
Include lightweight tags |
git describe --all |
Use any ref (branches, tags, etc.) |
git describe --abbrev=0 |
Show only the tag name |
git describe --dirty |
Append “-dirty” if working tree modified |
Understanding the Output
$ git describe
v2.1.0-14-g2414721
│ │ │
│ │ └── g + abbreviated commit hash
│ └── 14 commits since the tag
└── nearest annotated tag
$ git describe --long
v2.1.0-14-g2414721 (always includes count + hash)
$ git describe --tags
v2.1.1-3-gabcdef0 (includes lightweight tags)
$ git describe --abbrev=0
v2.1.0 (just the tag name)
Common use: version strings in builds
┌──────────────────────────────────────────────┐
│ VERSION=$(git describe --tags --always) │
│ echo "Building version: $VERSION" │
│ # Output: v2.1.0-14-g2414721 │
└──────────────────────────────────────────────┘
Tasks
01. Describe Current Commit
Get a human-readable name for HEAD.
Hint: git describe
02. Use Long Format
Always show the full describe format.
Hint: git describe --long
03. Include Lightweight Tags
Describe using both annotated and lightweight tags.
Hint: git describe --tags
04. Get Only the Tag Name
Show just the nearest tag without the commit count and hash.
Hint: git describe --abbrev=0
05. Check for Dirty Working Tree
Detect if the working tree has uncommitted changes.
Hint: git describe --dirty
Solution
06. Use Describe in Build Scripts
Generate a version string for your build.
Hint: VERSION=$(git describe --tags --always)
Solution
07. Find the Password
Describe the commits or explore the tags to find the password.
Hint: git describe --tags, git show <tag>
[Protected] Room 43 - Git Notes: Commit Metadata
GIT NOTES: COMMIT METADATA
Room 43 - Annotate Without Altering
📜 Your mission
Notes let you attach information to commits WITHOUT modifying the commit.
-
Add a note to a commit:
git notes add -m "This commit needs review"
-
Add a note to a specific commit:
git notes add -m "Performance fix" abc1234
-
View notes:
git log --show-notesgit notes show HEAD
-
Edit a note:
git notes edit HEAD
-
Remove a note:
git notes remove HEAD
-
Notes are stored in
refs/notes/commits. They’re separate from the commit itself! -
Push/fetch notes:
git push origin refs/notes/*git fetch origin refs/notes/*:refs/notes/*
-
This repo has a note on one of its commits. Find it.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git notes add -m "message" |
Add a note to HEAD |
git notes add -m "msg" <commit> |
Add a note to a specific commit |
git notes show |
Show note on HEAD |
git notes edit HEAD |
Edit an existing note |
git notes remove HEAD |
Remove a note from HEAD |
git log --show-notes |
Display notes in log output |
Notes Internals
mermaid
flowchart LR
C1["Commit abc1234"] -. "📝 Note" .-> N1["Reviewed by QA"]
C2["Commit def5678"] -. "📝 Note" .-> N2["Perf regression found"]
C3["Commit 789abcd"] -.- N3["(no note)"]
Notes live in refs/notes/commits
Key Properties
- Notes do NOT change the commit hash
- Notes are stored as separate Git objects
- Notes must be pushed explicitly:
git push origin refs/notes/* - Multiple note namespaces supported:
git notes --ref=review add -m "LGTM" - Use cases: code review comments, CI results, deployment tracking, audit trails
Tasks
01. Add a Note to HEAD
Attach a note to the current commit.
Hint: git notes add -m "message"
02. View Notes in the Log
See notes displayed alongside commits.
Hint: git log --show-notes
03. Show a Specific Note
Read the note on a specific commit.
Hint: git notes show <commit>
04. Add a Note to an Older Commit
Attach a note to a commit from the past.
Hint: git notes add -m "message" <hash>
05. Edit an Existing Note
Modify a note that’s already attached.
Hint: git notes edit <commit>
06. Remove a Note
Delete a note from a commit.
Hint: git notes remove <commit>
07. Find the Password
One of the commits has a note attached. Find it using git log --show-notes.
Hint: git log --show-notes, look for the note content
Solution
[Protected] Room 44 - Git Replace: Transparent Object Swap
GIT REPLACE: TRANSPARENT OBJECT SWAP
Room 44 - The Switcheroo
📜 Your mission
Replace lets you swap one Git object for another, transparently.
-
Replace a commit with another:
git replace <old-commit> <new-commit>
-
List replacements:
git replace -l
-
Delete a replacement:
git replace -d <old-commit>
-
Use cases:
- Fix a commit message without rewriting history
- Graft histories together
- Replace a tree (directory state)
-
Replacements are stored in
refs/replace/. They’re transparent - Git acts as if the original was the replacement. -
Create a “fixed” version of a commit:
git commit-tree <tree> -p <parent> -m "Fixed message"git replace <bad-commit> <new-commit>
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git replace <original> <replacement> |
Replace an object transparently |
git replace -l |
List all active replacements |
git replace -d <object> |
Delete a replacement |
git commit-tree <tree> -p <parent> -m "msg" |
Create a new commit object |
git cat-file -p <object> |
Inspect any Git object |
git log --no-replace-objects |
View log ignoring replacements |
How Replace Works
mermaid
flowchart LR
A --> B --> C --> D
D -. "git replace D D'" .-> D'["D' (replacement)"]
style D stroke-dasharray: 5 5
style D' fill:#4CAF50,color:#fff
Normal view: Everyone sees D' in place of D
Behind the scenes: Original D still exists. Replacements stored in refs/replace/<original-sha>
Key Properties
- Original object is NOT deleted
- All Git commands see the replacement
--no-replace-objectsbypasses replacements- Must push
refs/replace/*explicitly - Useful for grafting history or fixing commits
Tasks
01. List Existing Replacements
Check if any objects have been replaced.
Hint: git replace -l
02. Inspect an Object
Look at the raw content of a Git object.
Hint: git cat-file -p <hash>
Solution
03. Create a Replacement Commit
Build a new commit object with a fixed message.
Hint: git commit-tree <tree> -p <parent> -m "Fixed message"
Solution
04. Replace an Object
Swap the original commit for the new one.
Hint: git replace <original> <replacement>
05. View Without Replacements
See the original, unreplaced objects.
Hint: git --no-replace-objects log
06. Remove a Replacement
Delete a replacement and restore the original.
Hint: git replace -d <hash>
07. Find the Password
Check for existing replacements. View the original vs replaced content.
Hint: git replace -l, git --no-replace-objects log
Solution
[Protected] Room 45 - Git Filter-Branch & Filter-Repo: History Rewrite
GIT FILTER-BRANCH & FILTER-REPO: HISTORY REWRITE
Room 45 - Rewriting the Past
📜 Your mission
WARNING: These commands rewrite ENTIRE repository history!
-
Remove a file from ALL history (filter-branch, deprecated):
git filter-branch --tree-filter 'rm -f secrets.txt' HEAD
-
The modern replacement - git-filter-repo:
git filter-repo --invert-paths --path secrets.txt
-
Change author across all commits:
-
Remove large files from history:
git filter-repo --strip-blobs-bigger-than 10M
-
Use cases:
- Remove accidentally committed secrets
- Reduce repository size
- Fix author information
WARNING: NEVER do this on shared/published history!
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git filter-repo --invert-paths --path <file> |
Remove a file from all history |
git filter-repo --path <dir> --subdirectory-filter |
Extract a subdirectory |
git filter-branch --tree-filter 'rm -f file' HEAD |
Legacy: remove file from history |
git filter-branch --env-filter '...' |
Rewrite author/committer info |
git filter-repo --mailmap mailmap.txt |
Rewrite author identities |
git filter-repo --strip-blobs-bigger-than 10M |
Remove large files from history |
filter-branch vs filter-repo
git filter-branch (DEPRECATED) git filter-repo (RECOMMENDED)
══════════════════════════════ ════════════════════════════════
Built-in but slow External tool, very fast
Error-prone Safe with clear warnings
Complex syntax Simple, readable syntax
Still in Git (legacy) Install: pip install git-filter-repo
Common use cases:
┌───────────────────────────────────────────────────┐
│ • Remove accidentally committed secrets/passwords │
│ • Delete large binary files from history │
│ • Split a subdirectory into its own repo │
│ • Change author email across all commits │
│ • Remove sensitive data for compliance │
└───────────────────────────────────────────────────┘
☠️ Destructive Operation
Both commands REWRITE commit hashes for the entire history. All collaborators must re-clone after a history rewrite. Always back up your repo first!
Tasks
01. Inspect Current History
View the full commit log before rewriting.
Hint: git log --oneline --all
02. Find a File in All History
Locate which commits touched a specific file.
Hint: git log --all -- secrets.txt
03. Remove a File with filter-branch (Legacy)
Remove secrets.txt from every commit in history.
Hint: git filter-branch --tree-filter 'rm -f secrets.txt' HEAD
Solution
04. Use filter-repo (Modern)
The recommended way to remove files from history.
Hint: git filter-repo --invert-paths --path secrets.txt
Solution
05. Verify File Is Gone
Confirm the file no longer exists in any commit.
Hint: git log --all -- secrets.txt
Solution
06. Remove Large Files
Strip files larger than a threshold from history.
Hint: git filter-repo --strip-blobs-bigger-than 10M
Solution
07. Find the Password
Before rewriting, check the file that’s about to be removed. It contains the password.
Hint: git show HEAD:secrets.txt, or git log --all -- secrets.txt
Solution
[Protected] Room 46 - Git Rerere: Reuse Recorded Resolution
GIT RERERE: REUSE RECORDED RESOLUTION
Room 46 - Conflict Memory
📜 Your mission
Rerere = “REuse REcorded REsolution” - Git remembers how you resolved conflicts!
-
Enable rerere:
git config rerere.enabled true
-
Now when you resolve a merge conflict, Git RECORDS the resolution. Next time the SAME conflict happens, Git auto-resolves it!
-
View recorded resolutions:
git rerere statusgit rerere diff
-
Clear recorded resolutions:
git rerere forget <file>
-
Use case: rebasing long-lived branches
- You rebase often
- Same conflicts keep appearing
- rerere remembers your choices
-
The rerere cache is stored in
.git/rr-cache/
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git config rerere.enabled true |
Enable rerere globally or locally |
git rerere status |
Show files with recorded resolutions |
git rerere diff |
Show what rerere would apply |
git rerere forget <file> |
Forget a recorded resolution |
git rerere gc |
Prune old recorded resolutions |
git rerere remaining |
Show conflicts not yet resolved |
How rerere Works
rerere = **RE**use **RE**corded **RE**solution
First conflict:
mermaid
flowchart TD
M1["🔀 merge"] --> C1["❌ CONFLICT!"]
C1 --> R1["You resolve it manually"]
R1 --> REC["rerere RECORDS the resolution"]
REC --> CACHE[".git/rr-cache/"]
Same conflict again:
mermaid
flowchart TD
M2["🔀 merge"] --> C2["❌ CONFLICT!"]
C2 --> APP["rerere APPLIES saved resolution"]
APP --> OK["✅ Auto-resolved!"]
Perfect for: long-running topic branches with repeated rebases
Tasks
01. Enable rerere
Turn on the reuse-recorded-resolution feature.
Hint: git config rerere.enabled true
02. Create a Merge Conflict
Merge two branches that conflict so rerere can record the resolution.
Hint: git merge conflict-branch
03. Resolve and Record
Resolve the conflict manually. Rerere records your resolution automatically.
Hint: edit the file, git add, git commit
Solution
04. Check Recorded Resolutions
See what rerere has saved.
Hint: git rerere status, git rerere diff
05. Trigger the Same Conflict Again
Abort the merge, then redo it. Watch rerere auto-resolve.
Hint: git reset --hard HEAD~1, then git merge conflict-branch again
Solution
06. Forget a Resolution
Clear a recorded resolution for a specific file.
Hint: git rerere forget <file>
07. Explore the rerere Cache
Look at where resolutions are stored.
Hint: ls .git/rr-cache/
Solution
08. Find the Password
Resolve the conflict in this room. The merged content reveals the password.
Hint: merge, resolve the conflict, read the file
Solution
[Protected] Room 47 - Git Fsck: Filesystem Check
GIT FSCK: FILESYSTEM CHECK
Room 47 - Health Inspector
📜 Your mission
Fsck verifies the integrity and connectivity of Git objects.
-
Run a filesystem check:
git fsck
-
Find dangling objects (orphaned commits, blobs):
git fsck --unreachable
-
Find lost commits:
git fsck --lost-found- (Recovers lost objects to
.git/lost-found/)
-
Verbose output:
git fsck --verbose
-
Use case: data recovery!
- After a failed reset/rebase
- Corrupted repository
- Finding “lost” work
-
Combine with show to inspect found objects:
git fsck --lost-foundgit show <dangling-commit-hash>
-
This repo has a dangling commit with the password.
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git fsck |
Verify connectivity and validity of objects |
git fsck --unreachable |
Show objects not reachable from any ref |
git fsck --lost-found |
Write dangling objects to lost-found dir |
git fsck --no-reflogs |
Ignore reflog entries (stricter check) |
git show <hash> |
Inspect a recovered object |
git reflog |
Another way to find “lost” commits |
Object States
| State | Description |
|---|---|
| Reachable | Referenced by a branch, tag, or reflog entry |
| Dangling | Has no ref pointing to it |
| Unreachable | Not reachable from ANY ref (including reflogs) |
mermaid
flowchart TD
A["1. git fsck --lost-found"] --> B["2. ls .git/lost-found/"]
B --> C["commit/ ← lost commits"]
B --> D["other/ ← lost blobs, trees"]
C --> E["3. git show hash"]
D --> E
E --> F["4. git branch recovered hash"]
When to use git fsck:
- After a crash or power failure
- Suspecting repository corruption
- Recovering accidentally deleted branches
- Auditing repo health before migration
Tasks
01. Run a Basic Fsck
Check repository integrity.
Hint: git fsck
Solution
02. Find Unreachable Objects
List all objects not reachable from any ref.
Hint: git fsck --unreachable
03. Recover Lost Objects
Write dangling objects to the lost-found directory.
Hint: git fsck --lost-found
04. Inspect a Dangling Commit
View the content of a dangling commit.
Hint: git show <hash>
05. Recover a Lost Branch
Create a branch from a dangling commit to restore it.
Hint: git branch recovered <hash>
Solution
06. Strict Check (No Reflogs)
Run fsck ignoring reflog entries for a stricter check.
Hint: git fsck --no-reflogs
07. Find the Password
Inspect the dangling commit - it contains the password.
Hint: git fsck, git show <dangling-hash>
Solution
[Protected] Room 48 - Git GC: Garbage Collection
GIT GC: GARBAGE COLLECTION
Room 48 - Take Out the Trash
📜 Your mission
GC cleans up and optimizes your repository.
-
Run garbage collection:
git gc
-
Aggressive garbage collection:
git gc --aggressive
-
What gc does:
- Packs loose objects into packfiles
- Removes unreachable objects (after expiry)
- Compresses file storage
-
Related commands:
git prune- Remove unreachable objectsgit repack- Pack loose objectsgit pack-refs- Pack loose refs
-
View object storage:
git count-objects -v
-
Before gc: note the count of loose objects. After gc: notice how they’re packed.
-
Automatic gc runs after ~6700 loose objects (configurable).
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git gc |
Run garbage collection |
git gc --aggressive |
More thorough (slower) optimization |
git gc --auto |
Run only if thresholds are exceeded |
git prune |
Remove unreachable loose objects |
git repack -a -d |
Combine packs and delete old ones |
git count-objects -v |
Show object store statistics |
What gc Actually Does
git gc performs these steps:
mermaid
flowchart TD
A["1. git prune-packed\nRemove loose objects already in packs"] --> B["2. git reflog expire\nRemove old reflog entries"]
B --> C["3. git repack -a -d\nCombine pack files, delete old ones"]
C --> D["4. git prune\nRemove unreachable loose objects"]
D --> E["5. git rerere gc\nPrune old rerere cache entries"]
mermaid
flowchart LR
subgraph Before["Before gc: .git/objects/"]
B1["ab/cd1234..."]
B2["ef/567890..."]
B3["12/345678..."]
B4["pack-old.pack"]
B5["pack-old.idx"]
end
Before -- "git gc" --> After
subgraph After["After gc: .git/objects/"]
A1["pack/pack-abc.pack"]
A2["pack/pack-abc.idx"]
end
Tasks
01. Check Object Store Stats
See how many objects and packs exist.
Hint: git count-objects -v
Solution
02. Run Garbage Collection
Pack loose objects and optimize the repo.
Hint: git gc
Solution
03. Compare Before and After
Check object stats again after gc.
Hint: git count-objects -v
Solution
04. Aggressive GC
Run a more thorough optimization.
Hint: git gc --aggressive
Solution
05. Prune Unreachable Objects
Remove objects that are no longer referenced.
Hint: git prune
06. Repack the Repository
Manually repack objects into a single pack.
Hint: git repack -a -d
Solution
07. Find the Password
Check the gc output or repository stats for clues.
Hint: git count-objects -v, git log --oneline
[Protected] Room 49 - Git Plumbing Commands: Internals
GIT PLUMBING COMMANDS: INTERNALS
Room 49 - Under the Hood
📜 Your mission
Plumbing commands are Git’s LOW-LEVEL commands. Porcelain commands (add, commit, etc.) are built ON TOP of these.
-
Hash an object:
echo "Hello" | git hash-object --stdinecho "Hello" | git hash-object -w --stdin(write to object db)
-
Read an object:
git cat-file -p <hash>(print content)git cat-file -t <hash>(show type: blob, tree, commit, tag)git cat-file -s <hash>(show size)
-
List tree contents:
git ls-tree HEADgit ls-tree -r HEAD(recursive)
-
List files in index:
git ls-filesgit ls-files -s(with staging info)
-
Read a tree into the index:
git read-tree HEAD
-
Write the index to a tree object:
git write-tree
-
Create a commit from a tree:
git commit-tree <tree-hash> -m "message"
-
Update a ref:
git update-ref refs/heads/main <commit-hash>
Once you have the password:
Key Commands
| Command | Purpose |
|---|---|
git hash-object --stdin |
Compute the SHA-1 hash of content |
git cat-file -p <hash> |
Pretty-print object content |
git cat-file -t <hash> |
Show object type |
git cat-file -s <hash> |
Show object size |
git ls-tree HEAD |
List tree (directory) contents |
git ls-files |
List files in the index |
git write-tree |
Create a tree from the current index |
git commit-tree <tree> -p <parent> -m "msg" |
Create a commit object |
git update-ref refs/heads/branch <hash> |
Point a ref to a commit |
Porcelain vs Plumbing
Porcelain (user-facing) Plumbing (low-level)
═══════════════════════ ════════════════════
git add git hash-object + git update-index
git commit git write-tree + git commit-tree
git log git rev-list + git cat-file
git branch git update-ref
git checkout git read-tree + git checkout-index
Creating a commit manually:
┌─────────────────────────────────────────────────────┐
│ BLOB=$(echo "hi" | git hash-object -w --stdin) │
│ git update-index --add --cacheinfo 100644,$BLOB,f │
│ TREE=$(git write-tree) │
│ COMMIT=$(git commit-tree $TREE -m "first commit") │
│ git update-ref refs/heads/main $COMMIT │
└─────────────────────────────────────────────────────┘
Tasks
01. Hash an Object
Compute the SHA-1 hash of some content.
Hint: echo "Hello" | git hash-object --stdin
02. Store a Blob
Write content directly to the object database.
Hint: echo "content" | git hash-object -w --stdin
Solution
03. Read an Object
Inspect a stored object’s type, size, and content.
Hint: git cat-file -t, -s, -p
Solution
04. List Tree Contents
Explore a tree object (directory listing).
Hint: git ls-tree HEAD
Solution
05. List Files in the Index
See what’s in the staging area.
Hint: git ls-files -s
06. Create a Commit with Plumbing
Build a commit manually using low-level commands.
Hint: git write-tree, git commit-tree
Solution
07. Update a Reference
Point a branch to a specific commit hash.
Hint: git update-ref refs/heads/<branch> <hash>
Solution
08. Find the Password
Trace the object chain from HEAD: commit → tree → blobs. The password is in one of the blobs.
Hint: git cat-file -p HEAD, then follow the tree hash, then blob hashes
Solution
[Protected] Room 50 - Git Object Model: The Four Objects
GIT OBJECT MODEL: THE FOUR OBJECTS
Room 50 - The Foundation of Git
📜 Your mission
Git’s entire data model is built on just FOUR object types.
THE FOUR GIT OBJECTS:
blob- File contents (no filename, just data)tree- Directory listing (maps names → blobs/trees)commit- Snapshot pointer (tree + parent + author + message)tag- Named pointer to a commit (annotated tags)
Steps:
-
Explore object storage:
find .git/objects -type f
-
Examine each object type:
git cat-file -t <hash>(type)git cat-file -p <hash>(content)
-
Trace a commit:
git cat-file -p HEAD→ shows tree, parent, authorgit cat-file -p <tree-hash>→ shows blobs and subtreesgit cat-file -p <blob-hash>→ shows file content
-
The object graph:
- commit → tree → blob
- → tree → blob
-
Every object is identified by its SHA-1 hash. The SAME content always produces the SAME hash. This is how Git detects duplicates and verifies integrity!
-
You’ve mastered Git internals. Find the final password hidden in this room.
Once you have the password:
The Four Git Objects
| Object | Stores | Points To |
|---|---|---|
| blob | File content (no name!) | Nothing |
| tree | Directory listing | Blobs and trees |
| commit | Snapshot + metadata | Tree + parent(s) |
| tag | Annotated tag info | A commit |
The Object Graph
mermaid
flowchart TD
TAG["🏷️ tag: v1.0"] --> COMMIT
COMMIT["📌 commit: abc1234\nauthor: Alice\nmessage: Add feature"] --> TREE1
COMMIT -. "parent" .-> PARENT["📌 commit: 789abcd\n(previous commit)"]
TREE1["🌳 tree: def5678\n(root directory)"] --> BLOB1["📄 blob: aaa111\nREADME.md"]
TREE1 --> BLOB2["📄 blob: bbb222\nmain.py"]
TREE1 --> TREE2["🌳 tree: ccc333\nsrc/"]
TREE2 --> BLOB3["📄 blob: ddd4\napp.py"]
TREE2 --> BLOB4["📄 blob: eee5\nutil.py"]
Everything is content-addressed by SHA-1: Same content = same hash = stored only once!
.git/objects/ layout:
objects/
├── aa/a111... ← blob (README.md content)
├── bb/b222... ← blob (main.py content)
├── cc/c333... ← tree (src/ directory)
├── de/f567... ← tree (root directory)
├── ab/c123... ← commit
└── pack/ ← packed objects (after git gc)
🎓 You’ve reached the core of Git!
Understanding these four objects means you understand how Git actually works. Everything else is built on top of this model.
Tasks
01. Find All Objects
List all objects in the repository.
Hint: find .git/objects -type f
Solution
02. Identify Object Types
Determine the type of several objects.
Hint: git cat-file -t <hash>
Solution
03. Trace the Object Chain
Follow: commit → tree → blobs.
Hint: git cat-file -p at each level
Solution
04. Verify Content Addressing
Prove that the same content always gives the same hash.
Hint: echo "test" | git hash-object --stdin
Solution
05. Explore Annotated Tag Object
Find a tag and inspect its object.
Hint: git tag, git cat-file -p <tag>
Solution
06. Build a Commit from Scratch
Create a full commit using only plumbing commands.
Hint: hash-object, update-index, write-tree, commit-tree, update-ref
Solution
# 1. Create a blob
BLOB=$(echo "Hello Git!" | git hash-object -w --stdin)
# 2. Add to index
git update-index --add --cacheinfo 100644,$BLOB,hello.txt
# 3. Write tree
TREE=$(git write-tree)
# 4. Create commit
COMMIT=$(git commit-tree $TREE -m "Plumbing commit")
# 5. Update branch
git update-ref refs/heads/plumbing $COMMIT
git log --oneline plumbing
07. Find the Password
Explore the object database. One of the blobs contains the final password.
Hint: git ls-tree -r HEAD, then git cat-file -p <blob-hash> for each
Solution
[Protected] Room 99 - The Final Exam: Prove Your Git Mastery
THE FINAL EXAM: PROVE YOUR GIT MASTERY
Room 99 - The Grand Escape
📜 Your Final Mission
Complete these 10 challenges to prove you’ve truly escaped.
Once you’ve finished all 10, you’re officially a Git master!
Tasks
01. Init & Commit with Plumbing Only
Create a new repo, add a file, and make a commit using only plumbing commands.
Hint: hash-object, update-index, write-tree, commit-tree, update-ref
Solution
mkdir final-test && cd final-test
git init
BLOB=$(echo "Hello Final Exam!" | git hash-object -w --stdin)
git update-index --add --cacheinfo 100644,$BLOB,hello.txt
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "First commit via plumbing")
git update-ref refs/heads/main $COMMIT
git log --oneline
cat hello.txt
02. Branch Surgery (Squash 3 into 1)
Create a branch, make 3 commits, then use interactive rebase to squash them into one.
Hint: git switch -c, make 3 commits, git rebase -i HEAD~3
Solution
git switch -c feature
echo "a" > a.txt && git add a.txt && git commit -m "Add a"
echo "b" > b.txt && git add b.txt && git commit -m "Add b"
echo "c" > c.txt && git add c.txt && git commit -m "Add c"
git rebase -i HEAD~3
# Change 2nd and 3rd to 'squash', save
# Edit the combined message, save
git log --oneline
# One commit with all 3 files
03. Conflict Master (Resolve + rerere)
Create a merge conflict between two branches, resolve it, and verify rerere recorded the resolution.
Hint: git config rerere.enabled true, create conflicting branches, merge, resolve
Solution
git config rerere.enabled true
git switch main
echo "main version" > shared.txt
git add shared.txt && git commit -m "Main change"
git switch -c conflict-test HEAD~1
echo "branch version" > shared.txt
git add shared.txt && git commit -m "Branch change"
git switch main
git merge conflict-test
# CONFLICT! Resolve:
echo "resolved version" > shared.txt
git add shared.txt && git commit -m "Merge resolved"
git rerere status
# Recorded resolution for 'shared.txt'
04. History Detective (Bisect)
Use git bisect to find which of 10 commits introduced a bug.
Hint: git bisect start, git bisect bad, git bisect good, git bisect run
Solution
05. Time Traveler (Recover Deleted Branch)
Use reflog to recover a commit from a deleted branch.
Hint: git reflog, git branch recovered <hash>
Solution
06. Clean Export (Archive)
Create a .tar.gz release bundle with a version prefix directory.
Hint: git archive --prefix=project-v1.0/ HEAD | gzip > release.tar.gz
Solution
07. Secret Removal (filter-repo)
Remove a file called secrets.txt from the entire history.
Hint: git filter-repo --invert-paths --path secrets.txt
Solution
# Create the scenario:
echo "API_KEY=secret123" > secrets.txt
git add secrets.txt && git commit -m "Oops committed secrets"
# Remove from all history:
git filter-repo --invert-paths --path secrets.txt
# Or legacy:
git filter-branch --tree-filter 'rm -f secrets.txt' HEAD
git log --all -- secrets.txt
# No results - completely gone!
08. Object Inspector (Trace the Chain)
Given HEAD, trace the entire object chain: commit → tree → blobs.
Hint: git cat-file -p HEAD, then follow tree and blob hashes
Solution
09. Patch Pipeline (format-patch + am)
Generate patches, create a new branch, and apply them.
Hint: git format-patch -3, git switch -c, git am *.patch
Solution
10. Health Check (fsck + gc + count-objects)
Run all three diagnostic commands and understand the output.
Hint: git fsck, git gc, git count-objects -v
Solution
# 1. Check integrity
git fsck
# Reports dangling objects, missing refs, etc.
# 2. View stats before GC
git count-objects -v
# count: N loose objects, in-pack: M packed objects
# 3. Run garbage collection
git gc
# 4. View stats after GC
git count-objects -v
# count: 0 (loose objects packed), packs: 1
🎉🎉🎉 CONGRATULATIONS! YOU’VE ESCAPED! 🎉🎉🎉
╔══════════════════════════════════════════════════════════════╗
║ ║
║ 🏆 G I T E S C A P E R O O M C O M P L E T E 🏆 ║
║ ║
║ You have mastered the art of Git! ║
║ ║
║ From your first commit to plumbing internals, ║
║ from rebasing to the object model - ║
║ you now understand Git inside and out. ║
║ ║
║ ┌──────────────────────────────────────────────┐ ║
║ │ Rooms completed: 50 │ ║
║ │ Commands learned: 200+ │ ║
║ │ Git mastery level: ████████████████ 100% │ ║
║ └──────────────────────────────────────────────┘ ║
║ ║
║ "Any sufficiently advanced Git user is ║
║ indistinguishable from a wizard." 🧙 ║
║ ║
╚══════════════════════════════════════════════════════════════╝
🌟 What’s Next?
- Contribute to open-source projects using your Git skills
- Set up Git hooks to automate your workflow
- Explore
git worktreefor parallel development - Teach someone else - the best way to solidify knowledge!