# Git & Version Control Lab

24 guided missions · DiscoveryVIP

This is a local, single-tracked-file teaching model, not a Git executable. Synthetic commit IDs, simplified reflog and restricted operations are intentional. No repository, filesystem or remote is connected.

## 1. Read the three places

Your working tree is the file you edit. The index holds the snapshot prepared for the next commit. HEAD identifies the current commit through the current branch in this lab. They can contain three different versions of the same file. Start by inspecting status before changing anything.

**Mission:** Run git status and identify which area contains the uncommitted edit.

**Worked steps:**

```sh
git status
```

**Knowledge check:** Where is the new launch line initially?

Only in the working tree

## 2. Compare before you stage

git diff normally compares the working tree with the index. It reveals edits that are not staged yet. This lab shows complete before/after text rather than a real unified diff, making the two snapshots explicit. A diff inspects changes; it does not save a commit.

**Mission:** Inspect the unstaged change with git diff.

**Worked steps:**

```sh
git diff
```

**Knowledge check:** Does git diff change the index?

No, it only inspects differences

## 3. Stage a snapshot

git add copies the current file content into the index. Later edits to the working tree do not automatically update that staged snapshot. Staging lets you choose the content of your next commit independently of other edits. Here one tracked file keeps the distinction easy to see.

**Mission:** Stage the launch plan without creating a commit.

**Worked steps:**

```sh
git add notes.txt
```

**Knowledge check:** What does add prepare?

The index snapshot for a future commit

## 4. Inspect the staged change

git diff --staged compares the index with HEAD. This is the review immediately before a commit. It answers what the next commit would record, which can differ from what is currently open in your editor. Read both the staged and unstaged comparisons when the file has changed twice.

**Mission:** Run the staged diff to review the proposed commit.

**Worked steps:**

```sh
git diff --staged
```

**Knowledge check:** Which snapshots does --staged compare?

HEAD and index

## 5. Make a focused commit

A commit records the index snapshot with a message and links to its parent. It is local history; committing does not publish it to a hosting service. A useful message explains the change. Real commit IDs are content-derived hashes; this lab uses short synthetic IDs such as c1 for readability.

**Mission:** Commit the staged launch plan with message Plan launch.

**Worked steps:**

```sh
git commit -m "Plan launch"
```

**Knowledge check:** Does a local commit automatically push online?

No, publishing is a separate action

## 6. Commit only what was staged

Staging records a version at a point in time. If you then edit the file again, a normal commit still uses the index. The newer edit remains in the working tree. This is why inspecting the editor alone is not enough to know what a commit will contain.

**Mission:** Commit the staged launch plan while leaving the accessibility line uncommitted.

**Worked steps:**

```sh
git commit -m "Plan launch"
```

**Knowledge check:** Which version does this commit record?

The staged version, without the later line

## 7. Unstage without losing work

Unstaging and discarding are different operations. git restore --staged notes.txt restores the index from HEAD by default, while keeping the working file. You can reconsider the next commit without deleting the edit you have made. Watch which panel changes.

**Mission:** Unstage the launch line while keeping it in the working tree.

**Worked steps:**

```sh
git restore --staged notes.txt
```

**Knowledge check:** Does unstaging erase the working edit?

No, the working file is preserved

## 8. Discard an unstaged edit

git restore notes.txt replaces the working file with its index version. In a real project this can discard uncommitted edits. In the lab, Undo lab step can restore the preceding practice state. Notice that the source here is the index, not necessarily the latest commit.

**Mission:** Discard the unstaged launch line so all three snapshots match.

**Worked steps:**

```sh
git restore notes.txt
```

**Knowledge check:** Where does plain restore get this file’s content?

The index by default

## 9. Restore to a staged version

When the index differs from HEAD, restoring the working file from the index keeps the staged version. It does not erase the staged change. This is useful when a second experiment went wrong but the earlier staged change is still wanted. Always identify the source snapshot before restoring.

**Mission:** Remove only the accessibility edit while retaining the staged launch plan.

**Worked steps:**

```sh
git restore notes.txt
```

**Knowledge check:** Will this operation also remove the staged launch line?

No, it restores the staged version

## 10. Name a branch

A branch is a movable name pointing to a commit. git branch feature creates a name but does not switch to it. Initially both branch names can point to the same commit. Creating a branch does not duplicate all project files into a separate folder.

**Mission:** Create feature while staying on main.

**Worked steps:**

```sh
git branch feature
```

**Knowledge check:** Does git branch feature switch branches?

No, it only creates the name

## 11. Switch and create together

git switch -c creates a branch and makes it current. Future commits advance that branch. This teaching model requires a clean tree for all branch switches; real Git can carry non-conflicting edits across some switches. Commit or stash changes here before switching.

**Mission:** Create and switch to a branch named experiment.

**Worked steps:**

```sh
git switch -c experiment
```

**Knowledge check:** Which branch will the next commit advance?

experiment

## 12. Keep feature work separate

Committing on a feature branch moves only that branch pointer. The main branch stays at its earlier commit until you deliberately integrate the work. The history graph makes that relationship visible. Switching between clean branches changes the file snapshots to the selected tip.

**Mission:** On feature, write and commit the launch plan. Keep main at c0.

**Worked steps:**

Edit notes.txt to:
```text
Hello team.
Plan the launch.
```

```sh
git add notes.txt
```

```sh
git commit -m "Plan launch"
```

**Knowledge check:** Does main move when feature receives a commit?

No, main stays where it was

## 13. Return to main

When the feature branch is ahead and its working tree is clean, switching to main restores main’s older file version. The feature commit still exists and its branch still points to it. Seeing older content after switching does not mean the other branch’s work has been deleted.

**Mission:** Switch from feature to main and inspect the initial file.

**Worked steps:**

```sh
git switch main
```

**Knowledge check:** Where is the launch-plan commit after switching?

Still referenced by feature

## 14. Fast-forward a completed feature

A fast-forward is possible when the current branch is an ancestor of the target. Git can move the current branch name to the target commit without creating a merge commit. --ff-only refuses a divergent merge, making the expected operation explicit. This lab supports this form only.

**Mission:** Fast-forward main to feature.

**Worked steps:**

```sh
git merge --ff-only feature
```

**Knowledge check:** Does a fast-forward create a new merge commit?

No, it moves the current branch pointer

## 15. Clean up a merged branch

Deleting a merged branch name removes that pointer, not the changes already reachable from main. Git protects the current branch from deletion. The lab also refuses deleting a branch whose tip is not an ancestor of the current branch; it has no force-delete command.

**Mission:** Delete feature after it has been merged into main.

**Worked steps:**

```sh
git branch -d feature
```

**Knowledge check:** Does deleting this merged branch erase the work on main?

No, main still references the commit

## 16. Put unfinished work aside

A stash is a temporary local holding area for uncommitted changes. A normal stash saves tracked edits and cleans the working tree and index. Untracked files require additional options in real Git; this lab contains only one tracked file and models no untracked files.

**Mission:** Stash the launch edit and leave a clean initial file.

**Worked steps:**

```sh
git stash push
```

**Knowledge check:** Is a stash a remote backup?

No, it is local state

## 17. Bring a stash back

git stash pop applies the saved changes and removes the stash if application succeeds. It can conflict in real Git; failed application does not simply discard the stash. This lab permits pop only on a clean matching base. It restores tracked work as unstaged edits, without --index.

**Mission:** Pop the saved launch edit back into the working tree.

**Worked steps:**

```sh
git stash pop
```

**Knowledge check:** Without --index, should you assume original staging is restored?

No, inspect and stage again as needed

## 18. Inspect local history

git log follows commit ancestry from the current tip. A commit on another branch may not appear in a plain log from main. The graph in this lab shows the complete retained practice object store, which can include commits not reachable from the current branch.

**Mission:** Run the log from main and identify the launch commit.

**Worked steps:**

```sh
git log --oneline
```

**Knowledge check:** Does plain log necessarily show every retained commit on every branch?

No, it follows the selected history

## 19. Undo a commit, keep it staged

A soft reset moves the branch pointer while leaving the index and working tree unchanged. If both contained the removed tip’s snapshot, the change now appears staged relative to the earlier HEAD. This rewrites the branch’s visible history; it is different from adding a reversing commit.

**Mission:** Soft-reset one commit back, retaining the launch plan staged.

**Worked steps:**

```sh
git reset --soft HEAD~1
```

**Knowledge check:** Which snapshots does soft reset leave alone?

Index and working tree

## 20. Undo a commit, keep the edit

A mixed reset moves the branch and resets the index to the target, but leaves working files alone. The former committed change becomes an unstaged edit. In real Git, mixed is the usual default reset mode; this lab asks you to type the mode to make its effect explicit.

**Mission:** Mixed-reset one commit back and keep the launch edit unstaged.

**Worked steps:**

```sh
git reset --mixed HEAD~1
```

**Knowledge check:** Where does the launch edit remain after this reset?

In the working tree only

## 21. See what hard reset replaces

A hard reset moves the current branch and replaces the index and tracked working files to match the target. It can discard local changes in a real repository and can affect obstructing untracked paths. This model has only one tracked file; use its undo control to explore the consequences.

**Mission:** Hard-reset one commit back so all three snapshots show the initial text.

**Worked steps:**

```sh
git reset --hard HEAD~1
```

**Knowledge check:** What is replaced by hard reset in this single-file lab?

HEAD, index and working file

## 22. Recover a retained commit

Resetting a branch does not immediately delete the old commit object. Reflogs can help locate previous tips while the records and objects are still retained. They are local and expire, so they are not permanent backups. This lab retains its synthetic commits until the mission is reset.

**Mission:** Inspect the reflog, then restore main to retained commit c1.

**Worked steps:**

```sh
git reflog
```

```sh
git reset --hard c1
```

**Knowledge check:** Is reflog a permanent remote backup?

No, it is local and retention is limited

## 23. Reverse a change with new history

Revert records an inverse change in a new commit, preserving the earlier commits. This is often appropriate when others already depend on the history. Real reverts can conflict and merge commits need special handling; this lab implements only a clean revert of the current single-parent tip.

**Mission:** Revert the launch commit while preserving its ancestry.

**Worked steps:**

```sh
git revert HEAD
```

**Knowledge check:** How does revert differ from moving the branch back?

It creates a new reversing commit

## 24. Ship a small feature locally

Combine a focused branch, a reviewed snapshot, a commit and a fast-forward. A lightweight tag names a specific commit and does not advance with later branch commits. This capstone stays local: there is no remote, push, pull request or deployment in the model.

**Mission:** Create feature, commit the launch plan, fast-forward main, tag it release, then delete feature.

**Worked steps:**

```sh
git switch -c feature
```

Edit notes.txt to:
```text
Hello team.
Plan the launch.
```

```sh
git add notes.txt
```

```sh
git commit -m "Plan launch"
```

```sh
git switch main
```

```sh
git merge --ff-only feature
```

```sh
git tag release
```

```sh
git branch -d feature
```

**Knowledge check:** Will release automatically move with future main commits?

No, it continues to name its chosen commit

## Official documentation

https://git-scm.com/docs/git-reset
https://git-scm.com/docs/git-restore
https://git-scm.com/docs/git-revert
https://git-scm.com/docs/git-stash
https://git-scm.com/docs/git-merge
