Chapter 04Lesson 05~125 minutes

Checkpoint Lab — Repositories, Working Tree, Index, HEAD, and the File Lifecycle

Checkpoint Git's file-state machine by moving paths through untracked, ignored, staged, staged-plus-modified, committed, renamed, and deleted states while predicting and verifying every transition.

CheckpointState matrixVerificationSafe cleanup

Learning objectives

  • Create and maintain a file-state matrix across HEAD, index, and working tree.
  • Predict status and diff output before each state transition.
  • Recover only intended local changes without touching committed history.
  • Verify rename, deletion, ignore, and clean-state outcomes using multiple Git views.
  • Produce a learner-written state-transition diagram and finish with a clean disposable repository.

1. Checkpoint scenario — build a file-state matrix

You will maintain five paths with distinct roles: tracked.txt, split.txt, rename-me.txt, delete-me.txt, and ignored runtime.log. The goal is not speed; it is to predict which of the HEAD/index/working-tree comparisons will change before every command.

2. State matrix you will fill in

Moment HEAD Index Working tree Expected status idea
New path absent absent present untracked
After add absent/old new same as index staged
Modified after add old staged version newer version both index + worktree differ
After commit new commit matches HEAD matches index clean
Rename/delete staged old paths proposed rename/delete matches proposal staged R/D

3. Setup and preflight

Git Bash / Bash / zsh

mkdir git-state-checkpoint
cd git-state-checkpoint
git init -b trunk
git config user.name "State Checkpoint"
git config user.email "state-checkpoint@example.invalid"
printf "runtime.log\n" > .gitignore
printf "baseline tracked\n" > tracked.txt
printf "line 1\nline 2\nline 3\nline 4\nline 5\nline 6\n" > split.txt
printf "rename baseline\n" > rename-me.txt
printf "delete baseline\n" > delete-me.txt
git status --short

PowerShell alternative

New-Item -ItemType Directory git-state-checkpoint | Out-Null
Set-Location git-state-checkpoint
git init -b trunk
git config user.name "State Checkpoint"
git config user.email "state-checkpoint@example.invalid"
Set-Content .gitignore 'runtime.log'
Set-Content tracked.txt 'baseline tracked'
1..6 | ForEach-Object { "line $_" } | Set-Content split.txt
Set-Content rename-me.txt 'rename baseline'
Set-Content delete-me.txt 'delete baseline'
git status --short

Prediction 1: all five versionable files are untracked; runtime.log does not exist yet. No commit exists, so HEAD is unborn even though HEAD symbolically names trunk.

4. Stage and commit the baseline

git add -- .gitignore tracked.txt split.txt rename-me.txt delete-me.txt
git status --short
git diff --staged
git commit -m "Create file-state baseline"
git status --short --branch
git ls-files

Prediction 2: after the commit, HEAD, index, and working tree agree for all tracked paths, so both ordinary and staged diffs should be empty.

5. Create one untracked and one ignored path

Git Bash / Bash / zsh

printf "candidate\n" > candidate.txt
printf "runtime data\n" > runtime.log
git status --short
git check-ignore -v -- runtime.log
git ls-files --others --exclude-standard

candidate.txt should appear as untracked. runtime.log should be omitted from ordinary status but confirmed by check-ignore.

6. Move the untracked file into the index

git add -- candidate.txt
git status --short
git diff --staged -- candidate.txt
git diff -- candidate.txt

The staged diff contains the new path. The ordinary diff is empty because the working-tree version matches the staged version.

7. Modify the staged new file again

Git Bash / Bash / zsh

printf "candidate plus working-only line\n" > candidate.txt
git status --short
git diff --staged -- candidate.txt
git diff -- candidate.txt

Predict both columns: the index proposes a new file relative to HEAD, while the working tree contains a newer version than the index.

8. Recover only the intended local change

Suppose the staged candidate content is correct and only the later working-tree edit was a mistake. Inspect, then restore the working tree from the index:

This deliberately discards only the unstaged edit to candidate.txt.
git diff -- candidate.txt
git restore -- candidate.txt
git status --short
git diff -- candidate.txt
git diff --staged -- candidate.txt

The staged new file remains; the working-tree-only mistake is gone. No committed path was rewritten.

9. Commit the intended new file

git commit -m "Add candidate file"
git status --short --branch
git log -2 --oneline

10. Create a staged-plus-modified tracked file

Git Bash / Bash / zsh

printf "baseline tracked\nstaged line\n" > tracked.txt
git add -- tracked.txt
printf "baseline tracked\nstaged line\nworking-only line\n" > tracked.txt
git status --short
git diff --staged -- tracked.txt
git diff -- tracked.txt

Before running status, predict that tracked.txt has an index change and a separate working-tree change.

11. Unstage without discarding any working-tree content

git restore --staged -- tracked.txt
git status --short
git diff -- tracked.txt
git diff --staged -- tracked.txt

The full two-line working-tree edit remains. The index returns to the HEAD version. This demonstrates “change proposal” versus “work on disk.”

12. Discard only the local tracked-file edits

Preflight: verify git diff -- tracked.txt contains nothing you want to keep.
git diff -- tracked.txt
git restore -- tracked.txt
git status --short

13. Stage a rename and deletion

git mv rename-me.txt renamed.txt
git rm -- delete-me.txt
git status --short
git diff --staged --summary
git diff --staged

Predict: the index no longer contains rename-me.txt or delete-me.txt in the proposed snapshot; it contains renamed.txt. Status may report the rename using similarity detection.

14. Commit the structural changes

git commit -m "Rename and remove lifecycle files"
git status --short --branch
git ls-files
git ls-tree -r HEAD --name-only

The repository should now be clean. Both the index and HEAD should list renamed.txt and omit the deleted/old path.

15. Learner-written state-transition diagram

Before looking at this reference, draw your own diagram using these nodes: untracked, ignored, tracked clean, staged, staged + modified, staged rename, staged deletion. Label each arrow with the command that moved the path.

Reference transition map
flowchart TD
U[Untracked working-tree path] -->|git add path| S[Staged in index]
U -->|matching ignore rule| I[Ignored untracked path]
S -->|edit again| SM[Staged + working-tree modified]
SM -->|git restore path| S
S -->|git restore --staged path| U2[Working copy retained / index restored]
S -->|git commit| C[Tracked clean]
C -->|edit| M[Tracked modified]
M -->|git add| S2[Staged modification]
C -->|git mv| R[Staged rename/move]
C -->|git rm| D[Staged deletion]
R -->|git commit| C2[New tracked path clean]
D -->|git commit| A[Path absent from new snapshot]

16. Verification checklist

  • git status --short --branch reports a clean trunk.
  • candidate.txt is committed with only the intended content.
  • The accidental working-only edit was removed without altering prior committed history.
  • tracked.txt matches its committed baseline after the local edits were deliberately discarded.
  • renamed.txt is tracked; rename-me.txt is absent.
  • delete-me.txt is absent from the current tree.
  • runtime.log remains ignored and untracked.
  • No destructive reset, clean, force push, reflog expiry, or pruning command was used.

17. Cleanup

Git Bash / Bash / zsh

git status --short --branch
cd ..
pwd
rm -rf git-state-checkpoint

PowerShell

git status --short --branch
Set-Location ..
Get-Location
Remove-Item -Recurse -Force git-state-checkpoint

18. Knowledge check

Question 1. Why did restoring candidate.txt in step 8 not remove the staged new file?

Question 2. What was the effect of git restore --staged -- tracked.txt?

Question 3. Why can status show a rename even though commits do not store a rename instruction?

Question 4. A file is absent from ordinary status. How do you distinguish “ignored” from “already tracked and clean”?

Question 5. Which command in this lab changed committed history retroactively?

19. What Chapter 04 adds to a production Git operating model

You can now inspect the exact source state a build or commit will consume, stage only intended changes, diagnose hidden/ignored paths, distinguish branch/HEAD state, and discard local work only when the destination layer and source snapshot are explicit. This state literacy is the prerequisite for disciplined commits, diffs, revision ranges, and message policy in Chapter 05.

20. Chapter checkpoint summary

The working tree is editable reality, the index is a proposed next snapshot, HEAD identifies the checked-out commit context, and the object database holds immutable history. Safe Git work is the practice of choosing which of those layers a command is allowed to change.

Next chapter

Commits, Diffs, History Inspection, Revision Ranges, and Message Discipline

Chapter 05 builds on the now-observable state machine to make commits intentional, explain diff endpoints precisely, navigate revision ranges, and write history that remains useful to reviewers and operators.

Authoritative references

 git-status
 git-add
 git-restore
 git-mv
 git-rm
 git-check-ignore

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.