Skip to content

VOL 00 / CH 03 / LESSON 02

3.2 Staging Area, Differences, and Safe Undo ​

Prerequisites: Creating Your First Git Repository

Estimated time: 15 minutes

Practice environment: Continue using the temporary repository from the previous page

You are ready to continue when: you can identify which layer a change belongs to and then choose between restore, amend, or revert accordingly

The first snapshot is saved. Before undoing a later change, locate it: is it unstaged, staged, or committed? Those states require different operations. Start with status and diff so the command restores the intended layer.

Two Common Types of Diff ​

bash
printf '%s\n' "print('hello, Git')" > main.py
git diff
git add main.py
git diff --staged
git commit -m 'Update greeting'
  • git diff: Between the working directory and the staging area.
  • git diff --staged: Between the staging area and HEAD.
  • git show HEAD: Within a single commit.

Unstaged: Restore Workspace Files ​

bash
printf '%s\n' "print('temporary draft')" >> main.py
git diff
git restore -- main.py
git diff

The first diff shows the draft line; the second should be empty. Restore overwrites the working file with its staged version. Git generally cannot recover text it never saved, so read git diff before proceeding. If you need to preserve your current state, copy the files, create a temporary branch and commit, or use git stash push -u; by default, stash does not include untracked files, and restoration may result in conflicts.

Staged: Undo Only add ​

bash
printf '%s\n' 'draft' > notes.txt
git add notes.txt
git restore --staged -- notes.txt
git status --short

notes.txt is still in the workspace, just no longer part of the next commit.

Most Recent Local Commit: amend ​

bash
git add notes.txt
git commit -m 'Add notes'
printf '%s\n' 'more context' >> notes.txt
git add notes.txt
git commit --amend --no-edit

The amend command creates a new commit, causing its ID to change. This operation is only safe when the history hasn't been depended upon by others. If you're working on a personal remote branch and need to update it, coordinate first and prefer using git push --force-with-lease; it will still rewrite remote history and is not a substitute for a regular push.

Already Shared: revert ​

bash
git revert --no-edit HEAD

revert adds a reverse commit that preserves the original history, making it suitable for shared branches. Merge commits require checking the parent commit on the main line and cannot be blindly applied.

git reset --hard simultaneously moves references and overwrites the staging area and working directory. This is not presented as a typical undo tool in this section.

The Boundaries of .gitignore ​

bash
printf '%s\n' '__pycache__/' '*.pyc' '.env' > .gitignore
mkdir -p __pycache__
touch __pycache__/cache.pyc .env
git status --short

Ignore rules only affect untracked paths. Files already tracked in the repository must be reviewed and explicitly untracked using git rm --cached -- path before changes can be committed. If sensitive keys have already been committed or pushed, rotate the keys first. Deleting files from the workspace or adding them via .gitignore will not remove secrets from repository history.

Large objects also remain in history. Datasets and artifacts are typically stored in dedicated storage; when versioning is necessary, evaluate Git LFS. Using git filter-repo to clean history will alter commit IDs and requires backups and coordination with repository users.

These ignore files are only for observing the current state, never committed or carried forward into future branch experiments:

bash
rm -r -- __pycache__
rm -- .env .gitignore
git status --short

Ensure the output is empty before proceeding to create a new branch.

→ Next: Branches and Merging

Built with VitePress | Software Systems Atlas