sy

Git from Zero to Advanced: Interactive Terminal Adventure

15 May 2026

Version control is the single most important skill a developer can build early. Most tutorials show you commands to copy-paste without making them stick.

This post ships a runnable terminal adventure — a bash script that creates a safe sandbox and walks you through each concept interactively. Type the real commands. Get immediate feedback. No cloud account, no setup, nothing to break.

Table of contents

Open Table of contents

Download and run

curl -fsSL https://shukyusof.com/git-101.sh | bash

Or save it first if you prefer to read before running:

curl -fsSL https://shukyusof.com/git-101.sh -o git-101.sh
bash git-101.sh

Requirements: Git installed, bash or zsh. Works on macOS, Linux, and WSL on Windows.

The script creates a sandbox at ~/git-101-sandbox. It never touches any of your existing projects.

Options

FlagWhat it does
--level NJump straight to level N (1–14)
--resetDelete the sandbox and exit
--helpShow usage

During a challenge, type hint for a clue (−1 point) or skip to move on (−2 points).


Why Git?

Git is a distributed version control system. Every change is stored as a snapshot. You can branch to try ideas, merge to combine work, and recover from any mistake — because Git never forgets.

Every serious software project uses it. Learning Git pays dividends for your entire career.


Tier 1 — Beginner (Levels 1–5)

Level 1 — Init & commit

A repository is a folder Git watches. You create one once per project.

git init                       # start tracking this folder
git status                     # see what has changed
git add README.md              # stage a file (mark it for the snapshot)
git commit -m "Add README"     # save the snapshot with a message

Think of add as putting items into a box, and commit as sealing the box and labelling it. Git only packages what you explicitly place in the box.

Level 2 — Branching

A branch is a parallel copy of your codebase. Changes on a branch don’t affect others until you deliberately merge them.

git switch -c feature-login    # create a branch and move to it
# ... make your changes ...
git add .
git commit -m "Add login feature"
git switch master              # go back to the main branch

The golden rule: never work directly on master / main. Branches are free — use one for every piece of work.

Level 3 — Merging

When a feature is ready, merge its branch into the main branch.

git merge feature-login        # bring feature-login into the current branch
git log --oneline --graph --all

If two branches changed the same lines, Git pauses for a merge conflict — you decide which version wins.

Level 4 — Remotes

A remote is another copy of your repo — usually on GitHub, GitLab, or Bitbucket.

git remote add origin <URL>    # register the remote address as "origin"
git push -u origin master      # upload commits; -u sets the default upstream

Level 5 — Pulling teammate changes

git pull    # fetch + merge the remote's commits into your current branch

git pull is shorthand for git fetch (download) followed by git merge (apply).


Tier 2 — Intermediate (Levels 6–10)

Level 6 — Undoing mistakes

Git gives you several escape hatches:

SituationCommand
Un-stage a file (keep changes on disk)git restore --staged <file>
Discard working-directory changesgit restore <file>
Undo a commit by creating a reverse commitgit revert HEAD --no-edit
Undo last commit but keep changes stagedgit reset --soft HEAD~1
Wipe last commit and its changes entirelygit reset --hard HEAD~1

revert is safe for shared branches — it adds a new commit. reset --hard rewrites history — only use it on commits that haven’t been pushed.

Level 7 — Inspecting history

git diff                        # working dir vs last commit
git diff --staged               # staged changes vs last commit
git log --oneline               # compact history
git log --oneline --graph --all # ASCII branch graph
git blame app.js                # who changed each line, and when

Common git log filters:

git log --author="Alice"
git log --since="2 weeks ago"
git log --grep="fix"
git log -p                      # show the full diff for each commit

Level 8 — .gitignore

.gitignore tells Git which files and patterns to ignore entirely:

node_modules/
.env
*.log
dist/
build/
.DS_Store

Rules use glob patterns. * matches anything. A trailing / means directory only. A leading ! negates (un-ignores) a pattern.

Once you commit .gitignore, the ignored files vanish from git status. They are never staged or committed.

Level 9 — Stashing

Stash temporarily shelves uncommitted changes so you can switch context:

git stash                       # shelve everything
git stash push -m 'feature wip' # shelve with a label
git stash list                  # show all stash entries
git stash pop                   # re-apply and remove the latest stash
git stash apply stash@{1}       # re-apply a specific entry (keep it in list)
git stash drop stash@{0}        # delete an entry without applying
git stash clear                 # delete all stash entries

Level 10 — Tagging

Tags mark specific commits as meaningful — usually version releases.

git tag v1.0                    # lightweight tag (just a pointer)
git tag -a v1.1 -m "Release v1.1"  # annotated tag (stores author, date, message)
git tag                         # list all tags
git push origin --tags          # push all tags to the remote
git tag -d v1.0                 # delete a local tag

Annotated tags are preferred for releases because they carry metadata and can be signed.


Tier 3 — Advanced (Levels 11–14)

Level 11 — Merge conflicts

Conflicts are unavoidable in team work. Here is the resolution flow:

git merge hotfix                # → CONFLICT: automatic merge failed

Git marks the conflicting sections in the file:

<<<<<<< HEAD
console.log("master version");
=======
console.log("hotfix version");
>>>>>>> hotfix

Edit the file to keep what you want, then:

git add app.js                  # mark as resolved
git commit -m "Resolve merge conflict"
git branch -d hotfix            # clean up

git mergetool opens a visual diff editor if you prefer a GUI.

Level 12 — Rebase

Rebase replays your branch’s commits on top of another branch, giving you a straight line of history instead of a merge bubble.

# On feature-rebase, after master has new commits:
git rebase master               # move feature commits on top of master

# Then fast-forward master:
git switch master
git merge feature-rebase        # fast-forward, no new commit

Interactive rebase — rewrite, squash, or reorder commits before sharing:

git rebase -i HEAD~3            # edit the last 3 commits

Commands in the interactive editor:

Warning: never rebase commits that have already been pushed to a shared branch — it rewrites history and forces everyone else to re-sync.

Level 13 — Cherry-pick

Cherry-pick applies one specific commit from any branch onto HEAD:

git log experimental --oneline  # find the SHA you want
git cherry-pick <sha>           # apply it to the current branch

Classic use-cases:

Level 14 — Reflog & recovery

git reflog records every movement of HEAD — even ones caused by reset --hard.

git reflog                      # show all HEAD positions with SHAs

To recover a “lost” commit:

git reflog                      # find the SHA just before the reset
git reset --hard <lost-sha>     # restore HEAD to that commit

You can also create a branch from a lost commit without moving HEAD:

git branch recovered <lost-sha>

Reflog entries expire after 90 days by default — act quickly if you lose something important.


What to learn next

Once you’re comfortable with all 14 levels:

TopicCommand(s)
Bisecting bugsgit bisect start / bad / good / run
Worktreesgit worktree add
Submodulesgit submodule add / update
Git hooks.git/hooks/pre-commit, pre-push
Signing commitsgit commit -S (GPG)
Shallow clonesgit clone --depth 1
Sparse checkoutgit sparse-checkout

Quick reference card

GoalCommand
Start trackinggit init
Current stategit status
Stage filegit add <file>
Stage allgit add .
Snapshotgit commit -m "msg"
Compact historygit log --oneline
Branch graphgit log --oneline --graph --all
Who changed whatgit blame <file>
Working dir diffgit diff
Staged diffgit diff --staged
Create+switch branchgit switch -c <name>
Switch branchgit switch <name>
Mergegit merge <branch>
Register remotegit remote add origin <URL>
Uploadgit push
Download+applygit pull
Download onlygit fetch
Unstagegit restore --staged <file>
Discard changesgit restore <file>
Reverse a commitgit revert HEAD --no-edit
Undo commit (keep staged)git reset --soft HEAD~1
Wipe commit + changesgit reset --hard HEAD~1
Shelve WIPgit stash
Restore WIPgit stash pop
Lightweight taggit tag <name>
Annotated taggit tag -a <name> -m "msg"
Rebasegit rebase <branch>
Interactive rebasegit rebase -i HEAD~N
Copy one commitgit cherry-pick <sha>
Safety netgit reflog

The sandbox is yours to experiment in. Break things, reset with bash git-101.sh --reset, and start again — that is exactly how Git internalises.