Skip to content

fix(terminal): git reads real files, and every output matches Git 2.56 - #399

Merged
thierryvm merged 1 commit into
mainfrom
fix/git-fidelity
Sep 29, 2026
Merged

thierryvm merged 1 commit into
mainfrom
fix/git-fidelity

Conversation

@thierryvm

Copy link
Copy Markdown
Owner

Summary

The simulated git kept a list of file names. That produced three visible faults:

  • git add accepted files that do not exist and printed staged:, which real git never writes.
  • git status never saw a modified or deleted file.
  • git diff always printed the same invented example.

The Git lessons and the reference page taught against that simulation.

Git now works on the simulated files themselves. Every expected value in the new tests was printed by Git 2.56 on a copy of the lesson project.

Model (src/app/data/commands/gitTree.ts is new):

  • The state holds the repository path, the HEAD tree, the index, file modes and stash entries.
  • gitTree.ts provides:
    • reading the working tree;
    • .gitignore rules, including ! patterns and directory rules;
    • Myers diff with git's hunk grouping and function-context headers;
    • SHA-1 blob ids. index 7d825c5..6827029 matches real git byte for byte.
  • The simulator stores text without its final newline, following the convention wc already uses. Git reads each file with that newline.

Commands. These follow git's wording, exit codes and option parsing (-rf, -am, -uno, --source HEAD~1):

  • status: long, -s, -b, --porcelain, -u.
  • add: ., paths, -A, -u, -f, -n, -v. Ignored and missing paths are refused.
  • rm: refuses to lose work, and removes the directories it empties.
  • restore: --staged, --source.
  • commit: root commit, stats, create and delete mode lines, -a, -q, --allow-empty, -m without a value.
  • diff: HEAD, --staged, --name-only, --name-status, --numstat, --shortstat, -U.
  • check-ignore: -v, -q, -n.
  • reset: --soft, --mixed, --hard. Paths only change the index; --hard and --soft with paths are refused.
  • stash: -m, pop and apply the delta, overwrite conflicts, drop, clear.
  • init -b and init -q, and clone -b.

Commands that are still not simulated say so explicitly: add -p, diff --stat, branch-to-branch diff, commit --amend, stash -u.

Lessons and reference

  • ~/projets in Git lessons is now a real repository, with .git/, a .gitignore that keeps .env out, and index.html. The lesson warns that git add . takes .env; the prepared repository now protects it.
  • git diff & .gitignore starts from a real change (new gitRepoWithChange setup).
  • Theory blocks show real output:
    • status, status -s and diff;
    • check-ignore -v;
    • the refusal to add an ignored file;
    • the root commit.
  • Clone examples each use their own directory, and the fork workflow now runs cd projet before git remote add.
  • Reference: the SSH clone example cloned the same repository into an existing folder. It now clones alice/site.git.
  • Theory gaps: 158 → 148, none added.

UI

  • New output line type removed: standard output rendered in --github-red, used for deleted diff lines and unstaged or untracked paths. It is routed to stdout, so pipes and redirections keep it.
  • The lesson terminal now remounts when the environment changes. Setups now depend on the environment, for Windows file modes and .git/config, and the state is only read on mount (ui-auditor W1).

Gates

  • curriculum-validator: 0 CRITICAL.
  • ui-auditor: 0 CRITICAL. W1 (remount on environment change) is fixed. W2: red is shared with errors; the - prefix and deleted: carry the meaning in text.
  • terminal-fidelity-auditor:
    • About 600 comparisons against real git; P1 findings fixed in this PR.
    • Remaining items are listed below for the next Git PR: log options, renames, mode changes, nested .gitignore, pathspec globs, branch/checkout/config wording, ls on empty directories, grep -c.
    • Incident: the auditor ran a lesson's code index.html in a real shell and opened two VS Code windows. The agent's deny rules will be tightened in a follow-up docs(agents) commit.
  • feature-dev:code-reviewer: 4 IMPORTANT, all fixed, plus two below-threshold suspicions that real git confirmed:
    • hunk headers typed info were lost in pipes;
    • reset <commit> -- <path> moved HEAD;
    • git init -b dev dev lost the branch name;
    • long options did not take a space-separated value;
    • check-ignore reported tracked files;
    • git rm -r left empty directories.

Test plan

  • tsc, eslint src, full vitest, vite build.
    • Live-Supabase integration tests time out under full-suite concurrency. This flakiness is known; they pass when run serially (39/39).
  • New src/test/gitFidelity.test.ts (52 tests, real Git 2.56 values), updated engine and setup tests.
  • Local Chrome check:
    • Desktop 1280: git diff lesson with red/green lines and exercise validated; git status, git add .env refused, check-ignore -v, .git in ls -a.
    • Mobile 390: status and diff, no horizontal overflow.
    • Windows switch: fresh PowerShell session, script.sh committed as 100644.
    • No console errors.
  • CI, Sourcery, preview smoke test, merge, production check.

🤖 Generated with Claude Code

The simulated git kept a list of names: `git add` accepted missing files
and printed `staged:`, `git status` never saw a modified file, and
`git diff` always printed the same invented example.

- Model: repository path, HEAD tree, index, file modes and stash, read
  from the simulated filesystem (new commands/gitTree.ts: working tree,
  .gitignore rules, Myers diff, unified hunks, SHA-1 blob ids).
- status (long, -s, -b, --porcelain, -u), add, rm, restore, commit,
  diff (HEAD, --staged, --name-only/-status, --numstat, --shortstat,
  -U), check-ignore, reset, stash and init follow git's wording, exit
  codes and option parsing (`-rf`, `-am`, `-uno`, `--source HEAD~1`).
- Lesson repositories have .git/, a .gitignore that keeps .env out, and
  index.html; the git diff lesson starts from a real change.
- Lesson and reference examples no longer add missing files or run
  `git remote` outside the cloned directory. Theory gaps: 158 -> 148.
- A deleted diff line is stdout shown red (new line type `removed`);
  the lesson terminal restarts when the environment changes.

Expected values in src/test/gitFidelity.test.ts come from real Git 2.56.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
terminal-learning Ready Ready Preview Sep 29, 2026 5:41pm UTC

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @thierryvm, your pull request is larger than the review limit of 150,000 diff characters

@thierryvm
thierryvm merged commit dafa18f into main Sep 29, 2026
4 checks passed
@thierryvm
thierryvm deleted the fix/git-fidelity branch September 29, 2026 17:42
thierryvm added a commit that referenced this pull request Sep 29, 2026
… 2.56 (#400)

A branch was only a name: switching changed no file, git merge recorded a
fake merge commit, and the conflicts lesson never showed a conflict. Git is
now a commit graph with refs, real object ids, three-way merges and
conflict states.

- gitHistory.ts: commit graph, merge base, log order, three-way merge with
  conflict markers, the --stat graph, tree/commit/tag ids as git computes
- gitUsage.ts: usage texts generated from Git 2.56
- branch/switch/checkout move the working tree, carry or refuse local
  changes; merge fast-forwards, commits, squashes or stops on conflicts;
  status/add/rm/restore/reset/commit handle the merge state
- log/show/diff/tag/cherry-pick/rebase work on the graph (ranges, paths,
  --graph on a straight history, A...B, tag filters, rebase <up> <branch>)
- options git knows but the simulator does not do say "not simulated"
- lessons: gitRepoWithBranch is one commit ahead, new gitRepoWithConflict
  gives the conflicts lesson a real conflict; replayable theory examples
- 60 tests in gitBranches.test.ts, every expected value from real git
- CHANGELOG/STORY, and the #399 entries dated 29 September, not 30

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — 61f74564 Deployed Sep 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant