Git Project: Messy Repository
Diagnose a cluttered working tree, recover the intended files, and leave a clean status with an explained history.
Turn mixed staged, unstaged, ignored, untracked, stashed, and badly committed work into a clean repository whose final snapshots and recovery evidence you can defend.
Correct work in the wrong shape
The tip mixes two intentions, the index and working tree disagree, an ignored environment file must remain local, and a debug artifact must disappear.
A six-commit history with proof
You will preserve every wanted line, split the mixed tip, recover unfinished edits, remove noise, and explain each pointer and state transition.
Project brief
You are taking over a small local “response tool” repository after an interrupted work session. Nothing has been pushed, but the repository contains several kinds of state. Your job is not to make status quiet as quickly as possible. Your job is to determine what each state means, preserve the wanted work, and leave an auditable history.
Evidence tracker
Mark a gate complete only after the named command or review proves it. Progress is saved in this browser.
Safety boundary
Disposable repository only
Create a new practice directory. Never run the project’s reset or cleanup steps in SovranCode, your home directory, or valuable work.
No remote
The scenario is explicitly unpublished. Do not add a remote, push, or simulate shared history during this project.
No hard reset
The required recovery uses preservation, stash, restore, and mixed reset. A hard reset fails the safety contract.
Fake local values only
The environment file must contain obvious placeholders. Never use a real token, password, customer record, or private URL.
Required starting scenario
Build or ask an instructor to provide a repository named response-tool-recovery. The exact short IDs will differ, but its history, status, and files must match this contract.
Three commits on main
* d31f8a2 (HEAD -> main) Mix formatter behavior and release notes
* a82c517 Add text formatter
* 19f0e44 Initialize response toolThree visible paths
M src/format.js
M README.md
?? debug.logThe repository also contains an ignored .env.local with fake values. Normal status omits it; git status --short --ignored shows it with !!. There are no existing stashes, linked worktrees, remotes, or unmerged paths.
File and change contract
Mixed tip commit
d31f8a2 modifies src/format.js to normalize output and adds docs/release-notes.md. Both changes are wanted, but they belong in separate commits.
Staged formatter edit
The index adds explicit handling for blank input in src/format.js. This is wanted and must become its own commit after the tip is split.
Unstaged README edit
The working tree documents formatter usage. This is wanted, but it must remain separate from behavior changes.
Untracked debug log
debug.log is disposable runtime output. It must not appear in a commit or in the final working tree.
Ignored environment file
.env.local contains only fake local values, remains present and ignored, and must never become tracked or stashed with -a.
Recovery evidence
A branch named recovery/original-tip must preserve the original mixed commit for audit after main is rebuilt.
Target repository state
* <new> (HEAD -> main) Document formatter usage
* <new> Handle blank formatter input
* <new> Add release notes
* <new> Normalize formatter output
* a82c517 Add text formatter
* 19f0e44 Initialize response toolThe exact new IDs will differ. The final main branch contains six commits: two original commits followed by four single-purpose commits in the order shown. The recovery branch still points to the original three-commit line.
Original tip reachable
The recovery branch still resolves to the original mixed commit and its tree remains inspectable.
git show --stat recovery/original-tipNo hidden unfinished work
Normal status is clean, only the expected environment path is ignored, and the stash list is empty.
git status --short --ignoredSix coherent snapshots
Main has exactly six commits with four distinct recovery outcomes after the original baseline.
git rev-list --count mainMilestone 1: inventory without changing state
git status --short --ignored
git diff
git diff --cached
git log --oneline --decorate --graph --all
git stash list
git worktree list
git reflog --date=iso -12Write a state ledger before running any mutating command. For every path, record whether it exists in HEAD, the index, the working tree, or only as ignored/untracked content. For each commit, record its parent, purpose, and whether another ref contains it.
Milestone 2: inspect every change
Use path-limited and full comparisons to prove the scenario contract:
git show --stat HEAD
git show HEAD -- src/format.js
git show HEAD -- docs/release-notes.md
git diff
git diff --cached
git diff HEAD
git check-ignore -v .env.local
git ls-files --error-unmatch .env.localThe final ls-files command should fail because the environment file is not tracked. Record that as expected evidence. Open debug.log only long enough to confirm it is disposable and contains no sensitive information.
Milestone 3: create two preservation points
First preserve the committed tip with a branch. Then package the staged, unstaged, and untracked visible state in a named stash. Do not include ignored files.
git branch recovery/original-tip HEAD
git show --stat recovery/original-tip
git stash push -u -m "recovery: preserve mixed working state"
git stash list
git stash show --patch stash@{0}
git status --short --ignoredAfter stashing, normal status should be clean and .env.local should remain in place as ignored content. The stash patch should contain the staged formatter edit, README edit, and untracked debug log—never the ignored environment file.
Milestone 4: split the accidental tip
The mixed commit is unpublished and protected by recovery/original-tip. Move main back one commit with mixed reset, leaving the mixed tip’s content in the working tree.
git rev-parse --show-toplevel
git reset --mixed HEAD~1
git status --short
git diff -- src/format.js
git diff -- docs/release-notes.mdStage and commit the formatter change first, then the release notes. Review the complete cached patch before each commit.
git add src/format.js
git diff --cached
git commit -m "Normalize formatter output"
git add docs/release-notes.md
git diff --cached
git commit -m "Add release notes"Milestone 5: restore the unfinished work
Apply the named stash without dropping it. The formatter file changed during the history rebuild, so inspect carefully even if Git applies without conflict.
git stash apply stash@{0}
git status --short
git diff
git diff --cached
git diff HEADIf a conflict occurs, resolve the file to preserve both normalization and blank-input handling. Stage only the resolved formatter behavior. Do not use ours/theirs mechanically, and do not drop the stash while recovery remains unproven.
Milestone 6: classify and commit recovered paths
- 01Remove runtime noise
Delete
debug.logafter confirming it is disposable. Do not add a broad ignore rule merely to hide an unexplained artifact. - 02Commit blank-input behavior
Stage only
src/format.js, run cached diff and--check, test the formatter, then commitHandle blank formatter input. - 03Commit usage documentation
Stage only
README.md, inspect the patch, then commitDocument formatter usage. - 04Verify recovered content
Inspect both new commits and prove normalization, blank handling, release notes, and usage documentation all remain.
- 05Drop the preserved stash
Only after the commits and final files prove recovery, drop the exact stash entry and confirm the list is empty.
Milestone 7: audit history and state
git status
git status --short --ignored
git log --oneline --decorate --graph --all
git rev-list --count main
git diff recovery/original-tip..main
git diff recovery/original-tip main --stat
git stash list
git worktree list
git reflog --date=iso -12Main count
git rev-list --count main prints 6.
Normal status
The working tree and index are clean; no debug log or unexpected untracked file remains.
Ignored status
Only the expected local environment path appears and verbose ignore tracing names the intended rule.
Recovery branch
The original tip is still reachable and visibly diverges from the rebuilt main branch.
Stash and worktrees
The stash list is empty and only the intended primary worktree remains registered.
Reflog
The reset and subsequent commits are explainable; reflog supports the narrative but is not the only preservation mechanism.
Required failure drills
Complete both drills after saving the required final evidence. Use the recovery branch and disposable paths so the assessed main branch can be restored exactly.
Apply on a divergent branch
Create a temporary branch from a82c517, make a conflicting formatter change, and attempt to apply a recreated practice stash. Resolve or abort deliberately, then delete the temporary branch only when clean.
Recover a moved tip
Create a temporary branch, move it with mixed reset, find its previous tip in reflog, and create a recovery ref there. Never use hard reset in this project.
Submission evidence
- The initial state ledger with HEAD, index, working-tree, untracked, and ignored classifications.
- The original graph, status, plain diff, cached diff, and ignored-path proof.
- The verified
recovery/original-tipbranch and named stash patch. - Cached diffs for all four rebuilt/recovered commits.
- Test output or repeatable manual assertions for normalization and blank-input behavior.
- The final six-commit graph, clean status, ignored status, empty stash list, worktree list, and reflog excerpt.
- A short incident report explaining what was wrong, what was preserved, each state transition, and why no shared history was rewritten.
Self-assessment rubric: 25 points
5 · Diagnosis
Complete state ledger, correct diff interpretation, exact commit inspection, and no mutation before inventory.
5 · Preservation
Verified recovery branch, named inspected stash, ignored environment file excluded, and no hard reset.
5 · History repair
Mixed tip split into two coherent commits with complete cached review and accurate messages.
5 · Work recovery
Wanted staged and unstaged edits become separate tested commits; debug output is removed; no content is lost.
5 · Final audit
Six main commits, clean normal state, expected ignored state, empty stash list, valid recovery ref, and clear incident report.
Automatic stop
Any real credential, operation in a valuable repository, hard reset, or unexplained loss requires rebuilding the exercise safely.
Optional extension: compare with a worktree
Create a linked worktree at recovery/original-tip in a sibling directory. Compare the original mixed checkout with final main side by side, then remove the clean linked worktree through Git. This extension must not alter the required main history or delete the recovery branch.
Project checklist
- I performed the exercise only in the intended disposable repository.
- I inventoried every state before changing commits, index entries, or files.
- The original tip and unfinished work had verified preservation points.
- Main contains six coherent commits in the required order.
- Wanted code and documentation remain; debug noise is gone; local environment data stays ignored.
- Final status, graph, stash list, worktree list, diffs, and reflog support my incident report.