Skip to content

Content update: Git for Advanced 2026 - #170

Draft
mjaehn wants to merge 39 commits into
mainfrom
content-upate-advanced
Draft

Content update: Git for Advanced 2026#170
mjaehn wants to merge 39 commits into
mainfrom
content-upate-advanced

Conversation

@mjaehn

@mjaehn mjaehn commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Restructures the advanced course into two parts, replaces every slide image with a generated diagram, and rewrites the exercises so participants work things out instead of pasting commands.

Closes #147
Closes #155
Closes #156
Closes #162

Part of #165 (that issue also covers the beginner course, so it stays open).

Two-part structure

The old Parts 0–4 + Bonus become:

  • Part 1 · Your Git Toolboxlog/blame/diff/show, submodules, ignoring files, cherry-pick and rebase, stash and worktree, hooks, and git lfs.
  • Part 2 · Working Together on GitHub — why a shared workflow, the C2SM User Landing Page as a live example, issues, forks, pull requests, checks and previews, review, merging, and keeping a fork in sync.

git bisect is dropped (it moves to Expert_Topics.md), git lfs is added, and rebase is promoted from the bonus into Exercise 4 alongside cherry-pick.

Exercises are renumbered to follow the teaching order:

New Was
Exercise_1_examining-history.md Exercise_1_git-log-diff-show.md
Exercise_2_submodules.md Exercise_8_git-submodule.md
Exercise_3_ignoring-files.md Exercise_3_gitignore.md
Exercise_4_cherry-pick-rebase.md Exercise_6_git-cherry-pick.md + Exercise_bonus_rebase.md
Exercise_5_stash-worktree.md Exercise_4_git-stash-worktree.md
Exercise_6_hooks.md Exercise_7_git-hooks.md
Exercise_7_git-lfs.md new
Exercise_8_web-workflow.md Exercise_5_git-workflow.md, rewritten

Diagrams

All 14 third-party raster screenshots are gone. In their place are 13 Mermaid sources in advanced/slides/diagrams/, rendered to SVG by advanced/slides/build.sh, which CI now runs instead of an inline marp command — so a local build and the committed PDF cannot drift apart. The two images with no diagram equivalent (achtung.gif, tweet.png) became a .warning CSS class and a pros/cons list.

build.sh normalises one thing before committing: Mermaid gives a gitGraph cherry-pick commit a random id that lands in a CSS class name, which made cherry-pick.svg differ on every build. Since the workflow commits the rendered SVGs back to the branch, that would have produced a spurious "Update advanced slides diagrams and PDF" commit on every CI run. Two consecutive builds are now byte-identical.

Course renaming (#162)

"Git for Advanced" implied an expertise gate that does not exist. Under the umbrella name C2SM Git Courses, which is what the landing page already publishes, the two courses are now:

  • Git: First Steps (was Git for Beginners)
  • Git: Next Steps (was Git for Advanced), containing the two Parts above

The advanced/ and beginner/ directories keep their names — renaming them would break the published landing-page links, the check_requirements.sh --beginner flag and every bookmark.

Still to do outside this repo: the landing-page entry docs/events/git_courses.md in C2SM/c2sm.github.io, and the ETH technical training website.

Which folder for which exercise (#156)

Six working directories become four. Dropping bisect removes git-bisect-exercise/, and worktrees are now created as siblings of conference_planning instead of inside a separate conference_worktree/ clone.

advanced/README.md gains a directory map and an exercise → directory table, and every exercise opens with a > [!IMPORTANT] Working directory: box using the same wording helpers.sh prints.

Less guided exercises (#155)

Every exercise is now Goal → Tasks → collapsed Hint → collapsed Solution, with tasks stated as outcomes ("Find all commits that touch helpers.sh") rather than commands. Anything unguessable or destructive stays visible: hook bodies, git lfs track syntax, and every --force-adjacent command. Each exercise ends with a Check yourself list.

The time comes from the ~20 minutes bisect used to take.

Portability (#147)

advanced/helpers.sh used sed -i '/program/a text', which is GNU-only — so init_advanced_repo, the bootstrap five exercises depend on, failed on macOS. It now uses the same portable idiom the beginner course adopted in #140 (no -i, POSIX a\ + newline, write-to-temp-then-move), and exposes it as an insert_after helper the exercises use too.

Also:

  • git stash savegit stash push -m (deprecated since Git 2.16)
  • Python is gone from the advanced course entirely, along with requirements.txt — it existed only for the bisect checker script. This removes the Git Bash blocker raised in Make sure Git course works on Linux and Git Bash terminal #147.
  • pandoc in Exercise 3 replaced with tar, which needs no extra install anywhere
  • CRLF note added to Exercise 6, where it would otherwise make the whitespace hook misfire
  • Root README now leads with Git Bash for Windows, WSL2 as the alternative

New advanced/tests/test_helpers.sh (10 assertions) mirrors the beginner harness, and a new test_helpers.yml workflow runs both suites on ubuntu-latest, macos-latest and windows-latest.

Note

Two pre-existing problems surfaced while wiring that up and are fixed here: neither test script exited non-zero on failure (so a CI job would always have passed), and the beginner script tested get_default_branch_name from outside any repository — it only passed locally because developers happen to have a git repo above their checkout.

Git Bash is genuinely covered, not merely reviewed. windows-latest ships Git for Windows, and a step with shell: bash runs under its Git Bash, so the workflow exercises the exact platform this issue was raised about rather than a stand-in for it. No manual pre-course check is needed.

New: C2SM/c2sm-git-example

Part 2 needs somewhere safe to practise. https://github.com/C2SM/c2sm-git-example is now populated: Markdown pages about C2SM, a CONTRIBUTING.md, issue and pull request templates, and a checks.yml workflow so participants see real status checks.

Two content shapes are deliberate:

  • participants/<handle>.md — every participant's PR touches a unique file, so they never conflict
  • glossary.md — shared and alphabetical, so PRs touching it do conflict, which is the point of the last part of Exercise 8

Verified live: both checks pass on main and on a pull request (smoke-test PR opened, confirmed, then closed).

C2SM/git-workflow-practice is superseded and no longer referenced.

New checks against future drift

This update was needed largely because the slides were migrated to Marp in July and the exercises were never updated to match — and nothing detected that. Two workflows now make the same drift fail a pull request.

content_consistency.yml runs advanced/tests/check_consistency.sh, which verifies that the slides and the exercises reference each other in both directions, that every diagram used has a Mermaid source and no source is orphaned, that no raster images creep back in, that internal links and in-page anchors resolve, that advanced/README.md lists every exercise, and that files have no accidental trailing whitespace and end with a newline. It runs locally too, like build.sh.

The whitespace and newline rules are scoped to advanced/ plus the root files this update owns: the beginner course uses trailing two spaces deliberately for Markdown hard breaks, so a repository-wide rule would misfire on it constantly.

shellcheck.yml lints the shell scripts at severity=warning. beginner/helpers.sh is excluded — it has 16 pre-existing warnings about unquoted variables and unchecked cd, which are a separate cleanup rather than a regression to gate on here.

Also

  • Expert_Topics.md at the repo root — a backlog of what neither course covers (internals, history rewriting, recovery, bisect, large repositories, signing, collaboration at scale), and a syllabus draft should there ever be a Part 3
  • GitHub vs GitLab comparison on a slide and in Exercise 8, since C2SM uses gitlab.ethz.ch too
  • advanced/schedule.md rewritten for the two-part structure with a '26 column
  • Modernised tools slide: gh, lazygit, delta/difftastic, GitHub Desktop, JetBrains
  • Fixed .vscode/settings.json pointing at slides_theme/c2sm.css, which does not exist
  • Fixed the .gitkeep speaker notes, which were a verbatim copy of the .gitignore ones

Verification

  • Slides build to 46 pages; every slide inspected as an image, no overflow, all 13 diagrams legible
  • Exercises 3–7 walked end to end on Linux running every command verbatim; Exercise 1 commands checked against this repository's real history
  • Both helper test suites pass (19 assertions) in an isolated layout with no ancestor git repo, and the consistency script passes all 10 of its checks — both verified against a clean clone of the committed branch, not just the working tree
  • The consistency script and ShellCheck were both confirmed to fail on deliberately broken input, so they are not merely reporting success
  • All internal Markdown links and in-page anchors resolve; no reference to a deleted exercise survives; every referenced SVG has a .mmd source and no .mmd is orphaned
  • All 49 external URLs return OK, except the pr-<number> placeholder (inside backticks, not a link) and the Expert_Topics.md link, which resolves once this merges

@mjaehn mjaehn added advanced Relevant for Advanced course slides Changes to presentation slides labels Aug 18, 2026
@mjaehn
mjaehn marked this pull request as draft August 18, 2026 09:58
mjaehn and others added 13 commits August 18, 2026 14:47
Renumber the exercises to follow the teaching order of the new two-part
structure, and rewrite each one as tasks with optional hints instead of
commands to paste.

Exercises now state a goal and let participants work out the command, with
Hint and Solution in collapsed blocks. Commands that are unguessable or
destructive stay visible: hook bodies, git lfs syntax, anything near --force.
Each exercise opens with a "Working directory" box and closes with a short
"Check yourself" list.

  Exercise_1_git-log-diff-show.md -> Exercise_1_examining-history.md
  Exercise_8_git-submodule.md     -> Exercise_2_submodules.md
  Exercise_3_gitignore.md         -> Exercise_3_ignoring-files.md
  Exercise_6_git-cherry-pick.md   -> Exercise_4_cherry-pick-rebase.md
  Exercise_4_git-stash-worktree.md-> Exercise_5_stash-worktree.md
  Exercise_7_git-hooks.md         -> Exercise_6_hooks.md
  Exercise_5_git-workflow.md      -> Exercise_8_web-workflow.md

Exercise 4 absorbs Exercise_bonus_rebase.md, so merge and rebase are compared
side by side rather than rebase being an optional extra. Exercise 7 on git lfs
is new. Exercise 2 on git bisect is dropped and moves to Expert_Topics.md.

Content fixes along the way:
- git stash save -> git stash push -m (deprecated since Git 2.16)
- hard-coded SHAs replaced with relative refs so Exercise 1 cannot rot
- submodule target moved off a personal account to C2SM/c2sm-git-example
- pandoc dropped from Exercise 3 in favour of tar, which needs no install
- corrected the claim that pre-commit run --all-files only checks staged files
- "master script" renamed to "dispatcher script"

Closes #155
Closes #156
Three additions to the C2SM Marp themes, needed by the restructured slides:

- .warning, an amber callout, replacing the achtung.gif used until now
- .quote, a pull quote with attribution
- table styling, since the themes had no table rule and the inherited Marp
  default is hard to read on the dark background

Both the light and the dark theme get the same set, so a deck can switch
between them without losing styling.
Adds 13 Mermaid diagram sources under advanced/slides/diagrams/, a shared
mermaid-config.json carrying the C2SM palette, and build.sh, which renders
them to SVG and then builds the PDF.

CI now calls build.sh instead of an inline marp command, so a local build and
the committed PDF cannot drift apart, and commits the rendered SVGs alongside
the PDF so the VS Code Marp preview works without a render step.

Note that marp-core's default HTML allow-list has no svg entry, so inline
<svg> would be silently stripped. Referencing external .svg files as ordinary
Markdown images avoids that entirely and needs no --html flag.

Also adds a concurrency group to the build workflow, which previously pushed
to the PR branch with no guard against racing itself.
Replaces the Parts 0-4 plus Bonus structure with a two-way split:

- Part 1, Your Git Toolbox: log/blame/diff/show, submodules, ignoring files,
  cherry-pick and rebase, stash and worktree, hooks, git lfs
- Part 2, Working Together on GitHub: why a shared workflow, the C2SM User
  Landing Page as a live example, issues, forks, pull requests, checks and
  previews, review, merging, keeping a fork in sync

Deletes all 14 third-party raster screenshots, which came from dev.to,
scaler.com, gitkraken.com, dzone.com and a 2019 tweet. They were 1.4 MB, could
not be edited, were off-brand and blurred in the PDF. Twelve are replaced by
the generated diagrams; achtung.gif becomes the .warning class and tweet.png
becomes a pros and cons list.

Every exercise signpost slide now names the working directory, so the
information is in front of participants at the moment they need it.

Also adds a GitHub and GitLab comparison slide, since C2SM works on both
github.com and gitlab.ethz.ch and only the web interface and CI file differ;
modernises the tools slide with gh, lazygit, delta and difftastic; and fixes
the .gitkeep speaker notes, which were a verbatim copy of the .gitignore ones.

The PDF drops from 2.4 MB to 1.7 MB.
init_advanced_repo used sed -i '/program/a text', which is GNU-only. BSD sed
on macOS requires an argument to -i and does not accept that append syntax, so
the helper that five exercises bootstrap from failed outright on a Mac.

Replaces it with the idiom the beginner course adopted in #140: no -i, the
POSIX "a\" plus literal newline form, and write-to-temp-then-move. Exposes it
as an insert_after helper so the exercises can use it too instead of carrying
their own sed one-liners.

Also:
- mkdir -> mkdir -p, since re-running the function used to fail
- git init followed by git branch -m main -> git init -b main
- adds reset_advanced_repo, so participants can start an exercise over; the
  beginner course has had an equivalent for a while

Part of #147
Adds advanced/tests/test_helpers.sh, mirroring the beginner harness, with 10
assertions over insert_after, init_advanced_repo and reset_advanced_repo,
including that the bootstrap is repeatable.

Adds a workflow running both suites on ubuntu-latest, macos-latest and
windows-latest. On Windows the steps use shell: bash, which is the Git Bash
that ships with Git for Windows, so this exercises the platform #147 was
raised about rather than a stand-in for it.

Two pre-existing problems surfaced while wiring this up:

- Neither harness exited non-zero on failure, so a CI job running them would
  have passed unconditionally. Both now propagate a failure.
- The beginner harness tested get_default_branch_name before any repository
  existed, from a directory outside one. It only passed locally because
  developers tend to have a git repository above their checkout; on a clean
  runner the function would exit 1 and take the script with it. Moved to after
  init_simple_repo.

Closes #147
The exercises used to span six working directories with no map anywhere, which
was the most common source of confusion.

Cuts that to four: dropping git bisect removes git-bisect-exercise, and
worktrees are now created as siblings of conference_planning rather than
inside a separate conference_worktree clone.

advanced/README.md gains a directory tree, an exercise-to-directory table, and
a Setup section. Moving the bootstrap here also decouples the exercises from
each other: they used to link to Exercise 3 for it, which forced gitignore to
come before submodules.

schedule.md is rewritten for the two-part structure with a '26 column, plus
notes for the next run: participants need to pair up for Exercise 8, and
should fork c2sm-git-example once at the start rather than twice.

Closes #156
"Git for Advanced" implied an expertise gate that does not exist: the course
needs nothing beyond the everyday basics. The name described a level rather
than a prerequisite, and put people off who were exactly the intended
audience.

  Git for Beginners -> Git: First Steps
  Git for Advanced  -> Git: Next Steps

"Next" states the actual entry requirement, which is having done "First".

The advanced/ and beginner/ directories deliberately keep their names.
Renaming them would break the published landing-page links, the
check_requirements.sh --beginner flag and every bookmark participants hold,
and the issue is about how the courses are advertised rather than how the
repository is laid out.

Still to do outside this repository: the landing page entry in
C2SM/c2sm.github.io, which also still advertises the 2025 slides, and the ETH
technical training catalogue.

Closes #162
A reading list of Git topics neither course covers: internals and the object
model, history rewriting, recovery, debugging with history, merging in depth,
large repositories, signing and automation, collaboration at scale, and
configuration.

Each entry says why it matters and names the commands to look up, rather than
teaching them. It doubles as a syllabus draft should there ever be a third
part.

git bisect lands here, having been dropped from the advanced course.
Python was only ever needed for the git bisect checker script, and that
exercise is gone. Removes requirements.txt, whose jupyterlab and bash_kernel
entries had been stale since the 2025 move from JupyterLab to a plain
terminal, and swaps the Python check in check_requirements.sh for a git lfs
check, which Exercise 7 does need.

This also removes the last obstacle to running the advanced course under Git
Bash, which was getting a Python interpreter working there.

Separately, .vscode/settings.json listed slides_theme/c2sm.css, which has not
existed since the theme was split into light and dark variants during the Marp
migration.
This content update was needed largely because the slides were migrated to
Marp in July and the exercises were never updated to match. Nothing detected
that drift; it was found by reading. These checks make the same drift fail a
pull request instead.

advanced/tests/check_consistency.sh verifies that:

  1-2. the slides and the exercises on disk reference each other, both ways
  3-4. every diagram used has a Mermaid source, and no source is orphaned
  5.   no raster images creep back into the slides
  6-7. internal Markdown links and in-page anchors resolve
  8.   advanced/README.md lists every exercise
  9-10. no accidental trailing whitespace, and files end with a newline

It runs locally as well as in CI, like build.sh.

Checks 9 and 10 are scoped to advanced/ and the root files this update owns.
The beginner course uses trailing two spaces deliberately for Markdown hard
breaks, so a repository-wide rule would misfire on it constantly; the check
allows exactly-two-space breaks and flags everything else.

Adds a ShellCheck workflow at severity=warning. beginner/helpers.sh is
excluded: it has 16 pre-existing warnings about unquoted variables and
unchecked cd, which are a separate cleanup rather than a regression to gate
on here.
mjaehn added a commit to C2SM/c2sm-git-example that referenced this pull request Aug 18, 2026
Matches the naming settled in C2SM/git-course#170 and what the landing page
already publishes.
mjaehn and others added 7 commits August 18, 2026 15:15
Settles the umbrella name over the two courses, and drops the outer numbering
that an earlier draft of the pull request description had used.

  C2SM Git Courses
  |-- Git: First Steps        (beginner/)
  `-- Git: Next Steps         (advanced/)
      |-- Part 1: Your Git Toolbox
      `-- Part 2: Working Together on GitHub

The courses are deliberately not numbered. "First" and "Next" already carry
the sequence, so a "Part 1" and "Part 2" prefix would say it twice, and it
would collide with the two Parts inside the second course, leaving a Part 2
that contains a Part 1 and a Part 2.

It would also work against #162: labelling them Part 1 and Part 2 suggests you
need both, when they are separately attendable courses held months apart, and
making the second one approachable on its own was the point of that issue.

"C2SM Git Courses" also matches what the landing page already publishes.
Mermaid assigns a gitGraph cherry-pick commit a randomly generated id, which
lands in a CSS class name in the SVG. It has no effect on how the diagram
looks, but it made cherry-pick.svg differ on every single build.

Since the build workflow commits the rendered SVGs back to the branch, that
meant every CI run produced a spurious "Update advanced slides diagrams and
PDF" commit for a diagram nobody had touched. Normalising the class name in
build.sh makes two consecutive builds byte-identical.

Uses the write-to-temp-then-move form rather than sed -i, for the same reason
as advanced/helpers.sh: BSD sed on macOS requires an argument to -i, and
build.sh is meant to run locally as well as on a runner.
mjaehn and others added 3 commits August 19, 2026 07:43
Marp stamps CreationDate/ModDate with the current time on every build,
so the PDF differs byte-for-byte even when nothing changed. That made
CI commit a new PDF on every run, retriggering the workflow and
requiring repeated approval. Pin both dates to the epoch after render.
mjaehn and others added 8 commits August 19, 2026 08:22
Extends the half-day format to a 3/4 day (09:30-15:00, lunch 12:30-13:30).
Part 1 keeps its original pacing shifted by 30 minutes; Part 2 is scaled
up 3x to fill the afternoon.
The action's find walks from scandir ".", so generated paths are
prefixed with "./". The exact-match exclude never matched without
that prefix, so beginner/helpers.sh's pre-existing warnings were
still gating the check.
Fork PRs require manual approval for every new commit's workflow
runs; the bot's own PDF/diagram push was re-triggering
content_consistency and itself, forcing repeat approvals.
@mjaehn mjaehn mentioned this pull request Aug 19, 2026
mjaehn and others added 6 commits August 19, 2026 11:23
Add concurrency guard, extract build steps into build.sh with
reproducible PDF output (pinned timestamps), and skip CI on the
auto-commit to avoid re-triggering approval on fork PRs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

advanced Relevant for Advanced course slides Changes to presentation slides

Projects

None yet

2 participants