Skip to content

Commit e8385a8

Browse files
schaconcursoragent
andauthored
Add progress.asc task checklist and a blog progress page (#9)
* Add progress.asc task checklist and a blog progress page that renders it Co-authored-by: Scott Chacon <schacon@gmail.com> * Add blog post introducing the progress page Co-authored-by: Scott Chacon <schacon@gmail.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 4a47283 commit e8385a8

5 files changed

Lines changed: 487 additions & 0 deletions

File tree

progress.asc

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
= Pro Git, 3rd Edition — Progress
2+
:toc:
3+
4+
Working task list for the third edition, derived from the chapter-by-chapter
5+
inventory in `REVISION_PLAN.md`. This file is edited by hand: mark a task done by
6+
changing `[ ]` to `[x]`, and add new tasks — or whole new sections — as they come
7+
up. The site's progress page renders this file directly, so keep the format:
8+
`== Section title` headings with `* [ ]` checklist items under them.
9+
10+
== Project setup
11+
12+
* [x] Import the 2nd-edition sources as the starting point
13+
* [x] Write the revision plan (`REVISION_PLAN.md`)
14+
* [x] Build the line-level `master` -> `main` inventory (`book_master_to_main_inventory.md`)
15+
* [x] Launch the project site — book reader, blog, history
16+
* [x] Set up the cloud build/test environment for agents
17+
18+
== Policy decisions
19+
20+
These gate the cross-cutting sweeps; decide them first.
21+
22+
* [ ] Decide the `master` -> `main` rename policy (gates X1, ~602 renames)
23+
* [ ] Decide how to represent example hashes: regenerate everything at SHA-256, or keep labeled SHA-1 legacy examples (gates X2)
24+
25+
== Cross-cutting sweeps
26+
27+
* [ ] X1 — `master` -> `main` across the book (see the inventory for the per-line breakdown)
28+
* [ ] X1 — regenerate diagrams and screenshots that show a `master` branch
29+
* [ ] X2 — SHA-1 -> SHA-256 default-hash pass (~31 files reference hashes)
30+
* [ ] X3 — version framing: bump "written using Git version 2" to 3.x; reframe "since Git 2.23/2.27/2.28" notes as baseline behavior
31+
* [ ] X4 — cover the `safe.bareRepository` and `safe.directory` security defaults
32+
* [ ] X5 — forge/IDE screenshot refresh (Ch 4, Ch 6, Appendix A)
33+
34+
== Chapter 1 — Getting Started
35+
36+
* [ ] Update the headline SHA-1 passage in `what-is-git.asc` (X2)
37+
* [ ] Refresh per-platform install steps in `installing.asc`
38+
* [ ] Add the Rust toolchain requirement to "compile from source"
39+
* [ ] Rewrite the default-branch subsection of `first-time-setup.asc` for a main-default world
40+
* [ ] Note Git's maturation and the 3.0 transition in the history section
41+
42+
== Chapter 2 — Git Basics
43+
44+
* [ ] Normalize `restore`/`switch` as standard commands (drop the "new in 2.23" framing)
45+
* [ ] Decide whether to teach `restore`/`switch` before `checkout`/`reset`
46+
* [ ] Update the `pull.rebase` warning framing in `remotes.asc`
47+
* [ ] Regenerate example hashes per the X2 policy
48+
* [ ] Note the `main` and reftable defaults in `getting-a-repository.asc`
49+
50+
== Chapter 3 — Git Branching
51+
52+
* [ ] X1 sweep (101 renames — the heaviest concentration)
53+
* [ ] Regenerate the branch diagrams in `diagram-source/`
54+
* [ ] Revisit the branch-renaming discussion in `branch-management.asc` for a main-default world
55+
56+
== Chapter 4 — Git on the Server
57+
58+
* [ ] Demote Gitweb and `git daemon`; lead with modern self-hosting
59+
* [ ] Add Gitea/Forgejo coverage
60+
* [ ] Cover protocol v2; retire dumb HTTP
61+
* [ ] Recommend Ed25519 keys in `generating-ssh-key.asc`
62+
* [ ] Add a sidebar on reftable and SHA-256 hosting/interop implications
63+
* [ ] Refresh screenshots (X5)
64+
65+
== Chapter 5 — Distributed Git
66+
67+
* [ ] X1 sweep (`contributing` 48 renames, `maintaining` 39)
68+
* [ ] Contextualize the email-based workflow against PR-based norms
69+
70+
== Chapter 6 — GitHub
71+
72+
* [ ] Re-capture all screenshots (X5)
73+
* [ ] Text pass for the current PR review UI, org settings, and account setup flows
74+
* [ ] Scope decision on Actions, Codespaces, and the current review experience
75+
* [ ] Default-branch language in examples (26 renames in `2-contributing`)
76+
77+
== Chapter 7 — Git Tools
78+
79+
* [ ] Add SSH commit/tag signing to `signing.asc` (plus `gpgsm` for X.509)
80+
* [ ] Rework `replace.asc` — grafts are removed in 3.0
81+
* [ ] Add the new `git history` command to `rewriting-history.asc`
82+
* [ ] Lead `rewriting-history.asc` with `git filter-repo`; mark `filter-branch` deprecated
83+
* [ ] Update `credentials.asc` for Git Credential Manager
84+
* [ ] Add `git worktree` coverage
85+
* [ ] Add `git sparse-checkout` coverage
86+
* [ ] Evaluate `git range-diff`, `git replay`, `git bugreport`, `git diagnose` for coverage
87+
* [ ] X1 sweep (147 renames — the highest chapter total)
88+
89+
== Chapter 8 — Customizing Git
90+
91+
* [ ] Add `safe.bareRepository` and `safe.directory` to `config.asc` (X4)
92+
* [ ] Rewrite `init.defaultBranch` as default-is-main
93+
* [ ] Note `--object-format` (SHA-256) and `extensions.refStorage` (reftable)
94+
* [ ] Note removed config: `core.commentString=auto`, `core.preferSymlinkRefs=true`
95+
* [ ] Consider `git for-each-repo` in the scripting material
96+
* [ ] X1 sweep (`policy.asc` enforced-workflow example, 8 renames)
97+
98+
== Chapter 9 — Git and Other Systems
99+
100+
* [ ] Trim `git svn` coverage
101+
* [ ] Demote the Mercurial and Perforce bridges to a short "bridges exist" section
102+
* [ ] Verify the bridge tooling runs on modern Python
103+
* [ ] X1 sweep (23+ renames in the Hg sections, 37 in `git-p4`)
104+
105+
== Chapter 10 — Git Internals
106+
107+
* [ ] Rewrite `objects`/`packfiles` with the object-format framing and the SHA-256 interop story
108+
* [ ] Add reftable to `refs.asc` — the new default, and the why (case-collision, performance)
109+
* [ ] Fold protocol v2 into `transfer-protocols.asc`
110+
* [ ] Verify `maintenance.asc` against current `git maintenance`
111+
* [ ] Add `commit-graph` and `multi-pack-index` to the performance story
112+
* [ ] X1 sweep (70 renames)
113+
114+
== Appendices
115+
116+
* [ ] Appendix A: version/screenshot refresh for Sublime Text, Visual Studio, VS Code, JetBrains IDEs
117+
* [ ] Appendix A: version-check the shell completion sections
118+
* [ ] Appendix B: refresh binding versions (`libgit2`, `jgit`, `go-git`, `dulwich`)
119+
* [ ] Appendix B: promote `go-git`; add per-library SHA-256 support notes
120+
* [ ] Appendix C: add post-2.1 commands to the command index; note the 3.0 removals
121+
122+
== New material
123+
124+
* [ ] Dedicated "Git 3.0 / migrating to SHA-256" section
125+
* [ ] Reftable explainer (pairs with the Ch 10 refs rewrite)
126+
* [ ] Monorepo-scale material: sparse-checkout, partial clone, `scalar`, `git backfill`
127+
* [ ] `git maintenance` + commit-graph as a first-class performance story
128+
129+
== Publication
130+
131+
* [ ] Redo the contributors list and dedication
132+
* [ ] Final pass on the appendices (fastest to rot; do near publication)
133+
* [ ] Watch for the LTS tag (the last 2.x before 3.0) and time the release to it
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: 'A progress page for the third edition'
3+
description: 'Every task the third edition needs, tracked in one hand-edited file and rendered as a live progress page on this site.'
4+
date: 2026-08-02
5+
---
6+
7+
The third edition now has a **[progress page](../../blog/progress/)** — one place
8+
to see everything the revision needs and how much of it is done, section by
9+
section, with progress bars to match.
10+
11+
Behind it is a single file:
12+
[`progress.asc`](https://github.com/progit/progit3/blob/main/progress.asc), a
13+
plain AsciiDoc checklist at the root of the repository. It distills the
14+
chapter-by-chapter inventory from
15+
[`REVISION_PLAN.md`](https://github.com/progit/progit3/blob/main/REVISION_PLAN.md)
16+
into concrete tasks: the policy decisions that gate everything else, the
17+
book-wide sweeps like `master``main` and SHA-256, a section for every chapter
18+
and appendix, and the brand-new material Git 3.0 calls for.
19+
20+
The file is the source of truth, and it is edited by hand. Checking a task off
21+
means changing `[ ]` to `[x]`; adding a task means adding a line. When new work
22+
turns up — and it will — it gets a new line or a new section, and the page picks
23+
it up on the next build. Because it is standard AsciiDoc checklist syntax, the
24+
same file renders as tick-boxes right in the repository on GitHub.
25+
26+
At the time of writing the counter sits at **5 of 75 tasks** — the project
27+
scaffolding is done, and the writing is about to begin. Watch the bars fill in
28+
on the [progress page](../../blog/progress/), and if you spot work that belongs
29+
on the list, [`progress.asc`](https://github.com/progit/progit3/blob/main/progress.asc)
30+
is one pull request away.

site/src/lib/progress.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Parse the repo-root progress.asc — a hand-edited AsciiDoc checklist — into
2+
// structured data for the progress page. The file's contract is simple:
3+
// `== Section title` headings with `* [ ]` / `* [x]` checklist items below.
4+
// Anything else (the doc title, paragraphs, comments) is ignored.
5+
6+
import progressSrc from '../../../progress.asc?raw';
7+
8+
export interface Task {
9+
text: string;
10+
done: boolean;
11+
/** 0 for `*` items, 1 for `**`, … */
12+
depth: number;
13+
}
14+
15+
export interface Section {
16+
title: string;
17+
tasks: Task[];
18+
done: number;
19+
total: number;
20+
}
21+
22+
export interface Progress {
23+
sections: Section[];
24+
done: number;
25+
total: number;
26+
percent: number;
27+
}
28+
29+
export function parseProgress(src: string): Progress {
30+
const sections: Section[] = [];
31+
let current: Section | null = null;
32+
33+
for (const line of src.split(/\r?\n/)) {
34+
const heading = line.match(/^={2,3} +(.+?)\s*$/);
35+
if (heading) {
36+
current = { title: heading[1], tasks: [], done: 0, total: 0 };
37+
sections.push(current);
38+
continue;
39+
}
40+
41+
const task = line.match(/^(\*+) +\[([ xX*])\] +(.+?)\s*$/);
42+
if (task && current) {
43+
const done = task[2] !== ' ';
44+
current.tasks.push({ text: task[3], done, depth: task[1].length - 1 });
45+
current.total += 1;
46+
if (done) current.done += 1;
47+
}
48+
}
49+
50+
const kept = sections.filter((s) => s.total > 0);
51+
const done = kept.reduce((n, s) => n + s.done, 0);
52+
const total = kept.reduce((n, s) => n + s.total, 0);
53+
return {
54+
sections: kept,
55+
done,
56+
total,
57+
percent: total === 0 ? 0 : Math.round((done / total) * 100),
58+
};
59+
}
60+
61+
/** Render a task's text as HTML: escape, then apply `backtick code` and `->` arrows. */
62+
export function renderInline(text: string): string {
63+
return text
64+
.replaceAll('&', '&amp;')
65+
.replaceAll('<', '&lt;')
66+
.replaceAll('>', '&gt;')
67+
.replace(/`([^`]+)`/g, '<code>$1</code>')
68+
.replaceAll('-&gt;', '\u2192');
69+
}
70+
71+
export const progress = parseProgress(progressSrc);

site/src/pages/blog/index.astro

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { getCollection } from 'astro:content';
33
import Base from '../../layouts/Base.astro';
44
import { url } from '../../lib/url';
5+
import { progress } from '../../lib/progress';
56
67
const posts = (await getCollection('blog')).sort(
78
(a, b) => b.data.date.valueOf() - a.data.date.valueOf(),
@@ -15,6 +16,17 @@ const dateFmt = new Intl.DateTimeFormat('en', { dateStyle: 'long' });
1516
<h1 class="page-title">Blog</h1>
1617
<p class="page-lede">Updates and progress on the third edition of <em>Pro Git</em>.</p>
1718

19+
<a class="card progress-card" href={url('/blog/progress/')}>
20+
<div class="progress-head">
21+
<span class="progress-title">Third edition progress</span>
22+
<span class="progress-counts">{progress.done} of {progress.total} tasks · {progress.percent}%</span>
23+
</div>
24+
<div class="progress-bar">
25+
<div class="progress-fill" style={`width: ${progress.percent}%`}></div>
26+
</div>
27+
<span class="progress-cta">See every task →</span>
28+
</a>
29+
1830
<ul class="post-list">
1931
{posts.map((post) => (
2032
<li>
@@ -33,6 +45,60 @@ const dateFmt = new Intl.DateTimeFormat('en', { dateStyle: 'long' });
3345
</Base>
3446

3547
<style>
48+
.progress-card {
49+
display: block;
50+
margin-bottom: 2rem;
51+
text-decoration: none;
52+
color: var(--text);
53+
}
54+
55+
.progress-card:hover {
56+
border-color: var(--accent);
57+
color: var(--text);
58+
}
59+
60+
.progress-head {
61+
display: flex;
62+
align-items: baseline;
63+
justify-content: space-between;
64+
gap: 1rem;
65+
margin-bottom: 0.7rem;
66+
}
67+
68+
.progress-title {
69+
font-family: var(--serif);
70+
font-size: 1.2rem;
71+
font-weight: 700;
72+
}
73+
74+
.progress-counts {
75+
font-family: var(--mono);
76+
font-size: 0.82rem;
77+
color: var(--muted);
78+
white-space: nowrap;
79+
}
80+
81+
.progress-bar {
82+
background: var(--bg-inset);
83+
border-radius: 999px;
84+
height: 0.55rem;
85+
overflow: hidden;
86+
}
87+
88+
.progress-fill {
89+
background: var(--accent);
90+
height: 100%;
91+
border-radius: 999px;
92+
}
93+
94+
.progress-cta {
95+
display: inline-block;
96+
margin-top: 0.8rem;
97+
font-size: 0.9rem;
98+
font-weight: 600;
99+
color: var(--accent);
100+
}
101+
36102
.post-list {
37103
list-style: none;
38104
margin: 0;

0 commit comments

Comments
 (0)