Skip to content
← Free FDE training guides

Free learning / 40-minute Git lab

Git 101: know which change you are handing over

Define the working tree, staging area, commit and branch. Run real Git in a disposable repository and see why a passing working-copy check can describe different bytes from the commit.

No account needed. Use your own copy for writing and keep the original as a reference.

Engineering lab library / Run locally

See which bytes the commit actually contains

Predict seven states, inspect both diffs, then change staging and file selection separately. Match the evidence to the exact snapshot you hand over.

Real Git commands run in a new temporary repository that is removed after capture. No remote, model or network; your existing repository and global Git configuration are unchanged.

  1. Start here / Python 3.11+ · Standard library

    Git snapshot and evidence lab · Python

    Compare seven actual Git states, restage one edit and inspect an unrelated path added to the commit.

    Python 3.11+ and Git 2.28+ · No account or network

An original 40-minute introduction for someone who can reason about software but is new to Git. Follow one fictional configuration change through the files you edit, the snapshot you select and the history you record. Then run real Git commands through a small, disposable local lab.

1. Name the pieces before using the commands

Git is a distributed version-control tool. It records project snapshots and their relationships so people can compare changes and collaborate. It is not a programming language, a coding agent or a hosting website. GitHub and other hosting services can store Git repositories and add review workflows. A local Git commit does not require a hosting account.

A repository holds the project's Git history and metadata. In the ordinary checkout used here, that metadata lives in .git; the editable project files around it form the working tree. A downloaded archive of code may have no Git history. Having a folder of files and having a repository are different.

The index, often called the staging area, holds the proposed next snapshot. Think of preparing a package for a teammate: editing changes your desk copy; staging selects bytes for the package; committing records the selected snapshot. The analogy has limits: staging is not approval, and a commit is neither a deployment nor proof that the code works. Git stores more than a folder copy, including parent relationships and author/message metadata.

A commit ID identifies a particular recorded commit. A branch is a named reference to a commit that normally advances when you commit on it. HEAD normally identifies your checked-out branch, although Git can also check out a commit directly. A branch is not a second folder or a backup of uncommitted work.

For an FDE using Claude Code or another coding agent, these distinctions answer a practical question: “Which exact change am I asking someone to accept?” The agent may edit files; Git records selected content. Neither substitutes for your review of scope, behavior and customer requirements.

2. Read the three versions of one file

The fictional file policy.json contains one setting, max_items. The lab records 1, stages 2, then edits the working copy to 3. At that moment there are three versions worth inspecting: committed 1, staged 2 and working 3.

Read-only commandComparison or evidenceWhat it cannot establish
git status --shortStaged, unstaged and untracked pathsWhether a change is correct
git diff -- policy.jsonWorking file against the indexThe complete next commit
git diff --cached -- policy.jsonIndex against HEADLater unstaged edits
git show HEAD:policy.jsonContent recorded in the current commitThe current file on your desk

git add -- policy.json copies that file's current content into the index. It does not keep following future edits. An ordinary git commit -m ... records the index; the lab deliberately avoids options that select content differently. -- ends command options and makes the following item a path.

For the tracked file in this exercise, the two leading status columns compare index to HEAD, then working file to index. A space followed by M ( M) means an unstaged modification; M followed by a space (M ) means a staged modification; MM means both comparisons changed. ?? marks an untracked file. Preserve the spaces when reading the printed strings. Conflict status uses additional rules outside this introduction.

The second file, note.txt, is an unrelated fictional note. The ordinary diff above does not display its untracked contents. Read status and inspect the intended paths; an empty diff does not mean there are no files left to consider.

UNDERSTAND THE SYSTEM

Which version are you handing over?

Follow one fictional policy.json change through actual Git states. The diagram explains the local lab; it does not edit your files. Values show max_items in each version.

FOLLOW ONE EXAMPLE

See what moves and why.

Authored illustration
01 / EXPLORE THE PARTSTap a part to explain it
Direction of information or workReturn / feedback

WHAT THIS PART DOES

Working tree

The editable file on disk. An editor or coding agent changes these bytes; Git does not automatically commit them.

CONNECTED TO
  • git add: Index / staging area
  • Check these bytes: Working-copy check
Read the connections in plain English
  1. 01
    Working tree → Index / staging area

    Copy the selected file's current bytes into the index.

  2. 02
    Index / staging area → Recorded commit

    Record the current index in a new local commit.

  3. 03
    Working tree → Working-copy check

    The fixture check reads the working file, not Git history.

  4. 04
    Working-copy check → Handoff evidence

    A passing result is useful only for the content it actually checked.

  5. 05
    Recorded commit → Handoff evidence

    Read the committed file and compare it with the checked candidate.

Check your understanding: An agent says the working-copy check passed. Does that prove the commit contains the checked change?

No. Inspect the selected and committed bytes. In the default lab, the working file contains 3 but the commit contains 2. Match test evidence to the exact candidate; a Git snapshot alone proves no application behavior.

3. Predict and run the local history

Download fde-git-snapshot-lab.py. Use Python 3.11+ and an approved Git 2.28+ installation. No Python packages, account, model, credentials or internet are needed to execute it. Run these commands from any ordinary working folder:

Code example
python3 --version
git --version
python3 fde-git-snapshot-lab.py

The program creates a new temporary repository and runs real Git commands only there. It uses a fictional author, ignores inherited Git repository/configuration overrides and uses an empty initialization template. It does not change your global Git configuration or the directory from which you launched it. The temporary repository is removed after the report is captured. The report includes the actual diff text and commit IDs; IDs may differ between runs.

Predict each event before comparing its JSON output. working, index and committed report actual file contents, not hardcoded expected answers.

EventWorking / index / committed max_itemsObservation
baseline1 / 1 / 1One recorded file; clean status
edited2 / 1 / 1Policy unstaged; note untracked
staged2 / 2 / 1Policy staged; note still untracked
edited-after-stage3 / 2 / 1Policy status is MM
review3 / 2 / 1The two diffs compare different changes
committed3 / 2 / 2Commit contains 2; working edit to 3 remains
branch-reference3 / 2 / 2New reference points to baseline 1; checkout stays on main

In committed, one small fixture check asks whether max_items equals 3. The working file passes; the committed file does not. This is an actual value comparison, not an application test suite or a quality score. It exposes a common handoff problem: evidence from one set of bytes can be attached to another.

The final command creates review/baseline at the first commit. It does not switch branches, copy the current working edits or merge anything. There are no remotes. Nothing is pushed, published or deployed.

4. Change one decision and inspect the result

Make two separate copies of the Python file and keep the original for comparison.

Experiment A — stage the later edit. In one copy, set RESTAGE_AFTER_EDIT = True. The review now shows 3 in the working tree and index. The next commit records 3, the policy diff becomes empty, and the unrelated note remains untracked. Both fixture checks pass. Explain why this is an evidence match, not proof that a limit of 3 is a good product decision.

Experiment B — include another path. In a fresh copy, set INCLUDE_NOTE = True and leave restaging false. The next commit now contains note.txt as well as policy.json; the policy mismatch remains. The note is harmless fictional text, but its inclusion illustrates a scope error. In a real repository, inspect all staged paths and bytes for unrelated work and sensitive material before committing or publishing. A tracked secret is not removed from history merely by deleting its current file.

For each experiment, keep the changed setting, actual status, committed tree and your explanation. Do not substitute a screenshot of a green process exit for the contents you intend to hand over.

5. Carry this into an agent-assisted change

A fictional client asks for one bounded policy change. An assistant edits the policy and writes a planning note. Before accepting its proposed commit:

  1. Confirm the intended repository and current branch. Read status before edits so you can distinguish existing work from the agent's contribution.
  2. Review the changed behavior and its requirement. Inspect working and staged differences, including relevant untracked paths. Do not sweep unrelated files into a commit to make the status look clean.
  3. Select the intended content deliberately. If the file changes after staging, review the new content before staging it again.
  4. Associate test evidence with the exact candidate contents and commit. A clean checkout of that commit is one way to verify the handoff independently; this lab does not run the application's tests for you.
  5. Treat remote publication and deployment as separate authorized operations. A pull request is a hosting-service review mechanism, not a Git commit.

You do not need a clever command sequence to explain this. Say which bytes were changed, which were recorded, what evidence covers those bytes and what remains outside the handoff. The Claude Code setup lesson applies that habit to the offline ticket-triage project. The supplied project intentionally starts with failing tests; this introduction does not erase them.

6. Keep your evidence and continue

Before moving on, explain why the default run can have a successful working-copy check and a different committed value. Draw the working tree, index and commit, then label the two comparisons made by the diff commands. Ask a teammate to identify the intended snapshot without watching your terminal session.

Continue to the client delivery workbook to connect technical evidence to a request, owner and acceptance decision. If the terminal itself is unfamiliar, start with your first command.

Primary references checked 21 October 2026. This explanation, fictional example and program are original LockedIn Labs instruction.

Before you move on

Keep the evidence of your work.

  • A sketch of the working tree, index and recorded commit.
  • Actual diffs and both changed-copy experiment results.
  • A handoff note identifying which content the test evidence covers.

Keep these in your own working copy. Reading this page does not save work or record completion.

Suggested next free session

Tests 101: understand what a green result means

Understand what a test result establishes about the selected code. This is a suggested sequence; choose the practice that addresses your current gap.

Open the next free guide
Have Academy access?

Continue with worked explanations, practice and review in the related lesson.

Open the related Academy lesson →
Back to top ↑