← Developer workflow · Chapter 2

Make a change reviewable and recoverable with Git

Understand commit scope through working-tree and staged snapshots, then connect branch recovery, SSH identity checks, and review evidence into a focused collaboration workflow.

After this guide, you can

Predict commit content from both diffs, preserve unrelated edits, and prepare a change with reproducible review evidence.

A change contains a search fix, temporary logging, and a personal configuration file. The feature may work, yet committing the entire directory makes its scope hard to review. Git records snapshots and history; the developer still chooses which content belongs in the next snapshot.

This lesson follows a synthetic document application through two versions and turns Git's state model into a review procedure. The Python example copies dictionaries in memory. It does not create a repository or contact a remote server.

Working files, the index, and commits differ

The working tree contains files being edited. The index, also called the staging area, records content prepared for the next commit. A commit records a snapshot and its historical relationships. Editing a file after git add does not automatically update its staged content. One file can therefore have both staged and unstaged changes.

git status distinguishes these states. Plain git diff primarily compares the working tree with the index; git diff --staged compares the index with the current commit. Inspect both before committing. The first exposes remaining work and unrelated edits; the second shows what the next commit will contain. Also check whether new files have been tracked.

An ignore rule can prevent an untracked file from being added casually, but it cannot erase a secret already recorded in history. Deleting a leaked credential is insufficient: revoke or rotate it and follow the repository's history-cleanup process. Teaching configurations should contain synthetic data and placeholders from the outset.

Branches point into history

A branch is a movable reference to a commit, not a separate directory. Parent links form the commit graph. Switching a checkout to another branch updates files according to that history and can be affected by uncommitted edits. Inspect the current state and preserve existing work before switching.

git fetch obtains remote objects and updates relevant remote-tracking references. It normally does not merge your current branch. Compare local work against the fetched state afterward. A merge joins histories; a rebase reapplies changes on another base and creates new commit identities. Coordinate before rebasing published history used by collaborators.

Recovery methods also differ. Revert adds a commit expressing an inverse change, preserving an audit trail. Reset moves references and, depending on its options, can change the index and working files. Specify which edits must survive and whether history has been shared before choosing a recovery operation.

Check staging with a snapshot model

The application starts at v1. Its staged copy remains v1 after the working version changes to v2. Only staging again prepares v2. The example uses shallow copies because all values are immutable strings. It omits Git's objects, index format, and parent graph.

working = {"app": "v1"}
index = working.copy()
working["app"] = "v2"
commit = index.copy()
assert commit["app"] == "v1"
index["app"] = working["app"]
next_commit = index.copy()
assert next_commit["app"] == "v2"
assert commit["app"] == "v1"
print(commit, next_commit)

The output is {'app': 'v1'} {'app': 'v2'}. The final assertion verifies that preparing the second snapshot does not alter the first. This explains one reason a visible edit might be absent from a commit. Inspect the actual staged diff to diagnose a real repository.

Mutable nested values would make shallow copying insufficient. Git's content-addressed storage is not a Python dictionary; the model demonstrates a relationship rather than its internal implementation.

Prepare a change for review

In a disposable repository, record the initial commit and create a task branch. Change one behavior, such as returning an explicit error for an unknown document ID. Inspect status and diff, remove temporary logging you introduced, and stage the intended files or patch sections. Inspect the staged diff again and preserve unrelated edits.

Run checks covering the original failure and nearby boundary cases. Use a conventional commit message such as fix: correct unknown-document errors. Describe the final behavior and record the tested inputs and results. Inspect the working tree after committing; remaining edits may be intentional, but their exclusion should be understood.

A PR or MR description should explain the trigger, previous behavior, resulting behavior, validation, and material compatibility risks. Reviewers need the final change and its evidence. A focused change is easier to compare and reverse, though a low file count does not itself establish simplicity.

SSH verifies two identities

Server host-key verification asks whether the connection reaches the expected server. User authentication asks whether the client may log in. Neither substitutes for the other. Register a public key as required by the service and protect the private key locally. Never commit or send the private key as an attachment.

When a host key changes, verify the server change and fingerprint through a trusted channel. Deleting the known_hosts entry and accepting a new key skips the identity question. Diagnose connection failures through the host, port, username, selected identity, and server permissions rather than assuming every failure is a Git-password problem.

Successful SSH login does not establish repository write access. Open-source participation also requires reading the license, contribution guide, and maintainer requirements. A useful issue includes a minimal reproduction, expected behavior, and actual behavior without private data. Authentication does not replace code review.

Review generated artifacts and local configuration before staging, unless the repository explicitly treats them as deliverables. Inspect new files and ignore-rule scope, and confirm deletions belong to the task. Record runtime versions and check commands so reviewers can distinguish behavior changes from local environment differences.

Exercise: detect an unstaged edit

Stage a change in a temporary repository, then edit the same line again. Predict what each diff will show before inspecting it. Commit the staged version, confirm that the newer edit remains in the working tree, stage it explicitly, and create the second commit. Retain both identifiers and diffs.

A reviewer must predict commit content from the staged diff, locate both versions in history, and restore the chosen behavior with an additional inverse commit. Prepare a separate SSH failure classification covering unexpected host identity, user authentication, and repository permissions. The exercise requires neither a real private key in its report nor rewritten shared history.

Sources & further reading

Sources checked on 2026-11-10. Original engineering explanation; examples are teaching data, not production measurements.