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.
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:
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
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.
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 --branchreports a cleantrunk. -
candidate.txtis committed with only the intended content. - The accidental working-only edit was removed without altering prior committed history.
-
tracked.txtmatches its committed baseline after the local edits were deliberately discarded. -
renamed.txtis tracked;rename-me.txtis absent. delete-me.txtis absent from the current tree.runtime.logremains 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?
git restore -- candidate.txt restored the
working tree from the index. It did not change the index; the
staged new file remained proposed for commit.
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”?
git check-ignore -v -- path and
git ls-files -- path. Ignore diagnosis and index
membership answer different questions.
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.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.