Skip to content

feat(terminal): real git branches, merges and conflicts, matching Git 2.56 - #400

Merged
thierryvm merged 1 commit into
mainfrom
feature/git-real-branches
Sep 29, 2026
Merged

thierryvm merged 1 commit into
mainfrom
feature/git-real-branches

Conversation

@thierryvm

Copy link
Copy Markdown
Owner

Why

A branch in the simulator 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 modelled as a commit graph, and every output was compared with Git 2.56.

What changes

  • Commit graph (commands/gitHistory.ts, new): commits with parents and dates, branches and tags as refs, merge base, log order, git's three-way merge with conflict markers, the --stat graph as diff.c lays it out, and object ids computed like git (tree, commit, annotated tag). Same files, author, date and message give the same id as a real repository — checked against real git.
  • Branches: git branch (list, create, -d/-D, -m, -v, -a), git switch / git checkout update the working tree, carry local changes (M\tfile first) or refuse with git's messages (local changes, untracked files in the way), switch -, tracking branches from origin/*, path checkout (Updated N paths from the index / from a tree id, silent with --, --ours/--theirs).
  • Merges: fast-forward, --no-ff, --ff-only (with git's hints), --squash, three-way merge commits (Merge branch 'x' [into y]), content / add/add / modify/delete conflicts, --abort, --continue, every refusal during a merge; git status during a merge (long form and UU/AA/UD/DU); git add / git rm resolve; git commit concludes.
  • History: git log real format with decorations, --oneline, -n forms, --all, --author, --grep, --stat, -p, ranges, paths, --graph on a linear history; git show (patch, --stat, merges, rev:path, annotated tags); git tag; git reset on the graph; git cherry-pick and git rebase replay commits for real. Rebase -i, cherry-pick/rebase conflicts, detached HEAD and the --graph drawing of forks say "not simulated" instead of inventing output.
  • Comparisons and errors: git diff A B, A..B, A...B (from the merge base) and --stat; git diff --staged during a conflict (* Unmerged path); git tag -n, --contains/--points-at/--merged, -f (Updated tag); git rebase <upstream> <branch>; invalid branch/tag names, unknown options (with the usage text generated from Git 2.56 in commands/gitUsage.ts), switch/checkout argument errors, merge -, merge --abort <arg>, and a refused three-way merge (Merge with strategy ort failed., exit 2).
  • Messages and paragraphs: several -m make paragraphs (commit, tag); a conflicted merge proposes # Conflicts: comments, removed by the editor path (git commit, merge --continue) and kept by --no-edit, as git does. An option git lists in its usage but the simulator does not do now says "not simulated" instead of "unknown option".
  • Lessons: gitRepoWithBranch now has the branch one commit ahead (the merge lesson is a real fast-forward, Updating a3f8c12..b7e2d45); new gitRepoWithConflict gives the conflicts lesson a real conflict on <title>; the rename example in git-branch and the branch comparison in git-diff-gitignore are replayable.
  • Reference replay: the git examples run in a repository with a real graph (main with history, feature/login holding the commits the cherry-pick examples name).

Verification

  • Real git: Git 2.56 in throwaway sandboxes (no network, no editor, no pager); stdout/stderr order checked under a pseudo-terminal (WSL script), since redirected captures reorder lines.
  • src/test/gitBranches.test.ts (56 tests, real values, including ids 52f1600…, merge 6bdf3ce…, tag 6616dc3…); old engine tests that encoded the fake behaviour rewritten.
  • type-check, lint, full suite (2901 pass; the 3 live-Supabase integration tests timed out once under load and passed on two isolated reruns), build; theory gaps 148 → 148, bash-on-Windows 34 → 34.
  • Gates: curriculum-validator (0 CRITICAL), test-runner, terminal-fidelity-auditor (two passes: the first found 14 families of differences, the second 11 more — among them git tag -l -d silently deleting a tag; all fixed, each expected value re-captured from real git), feature-dev:code-reviewer (two passes: git restore on a conflicted file, git show on a merge fixed by hand, switch -f accepted but ignored, options git knows reported as unknown — all fixed).
  • Chrome (local): conflicts lesson desktop 1280 and mobile, no overflow, no console error.

Also fixes the date of the #399 changelog/story entries (29 September, not 30).

Known follow-ups

  • Exercises are still validated on the typed command and auto-advance after 2.5 s: the learner leaves the conflicts lesson before seeing the conflict. Next PR: multi-step exercises validated on the terminal state.
  • git checkout -t origin/<branch> (low reach: remoteRefs only holds origin/<current branch>).
  • git log --graph with --grep/--author (git shifts columns around skipped commits) and for forked histories, cherry-pick/rebase conflict states, detached HEAD, commit --amend.

🤖 Generated with Claude Code

… 2.56

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>

@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

@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 8:42pm UTC

@thierryvm
thierryvm merged commit f9fcf97 into main Sep 29, 2026
4 checks passed
@thierryvm
thierryvm deleted the feature/git-real-branches branch September 29, 2026 20:45
thierryvm added a commit that referenced this pull request Sep 29, 2026
…ach (#401)

* fix(landing): only list commands the terminal runs and the lessons teach

The hero listed, per environment and level, 22 commands the simulator
did not know (systemctl, launchctl, Get-Service, New-PSDrive...) and 4
no lesson taught. Each listed command now runs in that environment and
appears as a word of its own in that environment's lesson code or
exercises; landingTotals.test.ts checks both, and fails on the old list.

- module subtitle: five levels, up to Git and AI (was "two levels")
- module counts from MODULE_PREVIEWS instead of a hardcoded 11
- roadmap: real git branches, the app install guide and the explained
  reference examples are available; in progress now names multi-step
  exercises and the taught commands not simulated yet (find, sort, diff)
- tests 2 700+ -> 2 900+; docs/plan.md banner brought up to #400
- CHANGELOG and STORY

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

* fix(landing): the terminal preview shows what real shells print

ls sorts its names and adds no slash; PowerShell answers Get-Location
with its Path table and Test-Path with True, instead of bash-style
listings. The prompt follows cd (~/projects, C:\Users\user\projects),
blank output lines keep their height, ls keeps its double spaces, and
long commands wrap at the edge like a terminal, not after a hyphen.
Outputs captured from GNU bash and PowerShell 7.

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

---------

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

This branch was successfully deployed

1 active deployment
Preview — 8952857a 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