Skip to content

Commit 0c80ed8

Browse files
committed
Update example in README
1 parent 8dc84c4 commit 0c80ed8

File tree

1 file changed

+55
-36
lines changed

1 file changed

+55
-36
lines changed

README.md

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ rm -rf MyProject/.lake/hopscotch
134134

135135
## Step-by-step example: updating a mathlib downstream
136136

137-
Suppose you maintain `MyProject`, a Lean 4 project that depends on mathlib. mathlib has released a batch of new commits and you want to know which ones your project still builds against — and find the exact commit where it breaks.
137+
Suppose you maintain `MyProject`, a Lean 4 project that depends on mathlib. mathlib has released a batch of new commits and you want to find the exact commit where your project breaks. Because mathlib moves fast — dozens of commits a day — you almost always want bisect: it identifies the first bad commit with roughly log₂(N) probes instead of N.
138138

139139
### 1. Check your downstream's current pin
140140

@@ -148,85 +148,104 @@ git = "https://github.com/leanprover-community/mathlib4"
148148
rev = "a1b2c3d4" # currently pinned here
149149
```
150150

151-
### 2. Run linear mode to walk forward through mathlib commits
151+
### 2. Run bisect to find the breaking commit
152+
153+
Bisect is the default — no `--scan-mode` flag needed:
152154

153155
```bash
154156
hopscotch dep mathlib \
155157
--project-dir ./MyProject \
156158
--from a1b2c3d4 \
157-
--to origin/master \
158-
--scan-mode linear
159+
--to origin/master
159160
```
160161

161-
`hopscotch` fetches the commit range from GitHub (set `GITHUB_TOKEN` to avoid rate limits), then starts probing each commit. Note that `--from` is exclusive — `a1b2c3d4` itself is not tested; probing begins at the next commit after it.
162+
`hopscotch` fetches the commit range from GitHub (set `GITHUB_TOKEN` to avoid rate limits), validates that the last commit in the range actually fails, then binary-searches. Note that `--from` is exclusive — `a1b2c3d4` itself is not tested.
162163

163164
```
164-
[2026-03-31T12:00:00Z] Attempting commit b2c3d4e5 (1/47)
165+
[2026-03-31T12:00:00Z] Validating last commit e5f6a7b8 (47/47) — must fail to proceed
165166
[2026-03-31T12:00:01Z] Running lake update mathlib
166-
[2026-03-31T12:01:30Z] Finished lake update mathlib (log file: .lake/hopscotch/logs/0-b2c3d4e5ab12-bump.log)
167+
[2026-03-31T12:01:30Z] Finished lake update mathlib (log file: .lake/hopscotch/logs/46-e5f6a7b8cd90-bump.log)
167168
[2026-03-31T12:01:30Z] Running lake build
168-
[2026-03-31T12:05:00Z] Finished lake build (log file: .lake/hopscotch/logs/0-b2c3d4e5ab12-build.log)
169+
[2026-03-31T12:05:00Z] Finished lake build (log file: .lake/hopscotch/logs/46-e5f6a7b8cd90-build.log) ← fails ✓
170+
[2026-03-31T12:05:00Z] Probing commit 6c7d8e9f (24/47)
171+
[2026-03-31T12:05:01Z] Running lake update mathlib
172+
173+
[2026-03-31T12:10:00Z] Finished lake build (log file: .lake/hopscotch/logs/23-6c7d8e9fab12-build.log) ← passes
174+
[2026-03-31T12:10:00Z] Probing commit d1e2f3a4 (36/47)
175+
176+
[2026-03-31T12:15:00Z] Finished lake build (log file: …) ← fails
177+
[2026-03-31T12:15:00Z] Probing commit 7b8c9d0e (30/47)
178+
179+
[2026-03-31T12:20:00Z] Finished lake build (log file: …) ← passes
180+
[2026-03-31T12:20:00Z] Probing commit 4f5a6b7c (33/47)
169181
170-
[2026-03-31T12:30:00Z] Attempting commit c3d4e5f6 (3/47)
171-
[2026-03-31T12:30:01Z] Running lake update mathlib
172-
[2026-03-31T12:31:30Z] Finished lake update mathlib (log file: .lake/hopscotch/logs/2-c3d4e5f6a1b2-bump.log)
173-
[2026-03-31T12:31:30Z] Running lake build
174-
[2026-03-31T12:35:00Z] Finished lake build (log file: .lake/hopscotch/logs/2-c3d4e5f6a1b2-build.log)
182+
[2026-03-31T12:25:00Z] Finished lake build (log file: …) ← fails
183+
[2026-03-31T12:25:00Z] Probing commit 9e0f1a2b (32/47)
184+
185+
[2026-03-31T12:30:00Z] Finished lake build (log file: …) ← passes
186+
[2026-03-31T12:30:00Z] knownGood (32) and knownBad (33) are adjacent — boundary found.
175187
```
176188

177-
The run stops. Check the build log for the full output.
189+
Six probes instead of 47.
190+
191+
### 3. Examine the failure boundary
192+
193+
The summary records the exact boundary:
194+
195+
```bash
196+
cat MyProject/.lake/hopscotch/summary.md
197+
# Bisect result
198+
Last known good: 9e0f1a2b (32/47)
199+
First known bad: 4f5a6b7c (33/47)
200+
```
178201

179-
### 3. Examine the failure
202+
Inspect the build log for the bad commit:
180203

181204
```bash
182-
cat MyProject/.lake/hopscotch/logs/2-c3d4e5f6a1b2-build.log
205+
cat MyProject/.lake/hopscotch/logs/32-4f5a6b7cab12-build.log
183206
# MyProject/Foo.lean:12:5: error: unknown identifier 'Mathlib.SomeRenamedLemma'
184207
```
185208

186209
### 4. Fix the issue in your project
187210

188-
Edit `MyProject/Foo.lean` to use the updated API. After fixing:
211+
Edit `MyProject/Foo.lean` to use the updated API. With the lakefile still pinned to `4f5a6b7c` from the last probe, verify the fix locally:
189212

190213
```bash
191-
cd MyProject && lake build # verify the fix works at the failing commit
214+
cd MyProject && lake build
192215
```
193216

194-
### 5. Resume from where you left off
217+
### 5. Commit and start a fresh session
195218

196-
Because `hopscotch` serializes state after each step, you can resume without re-testing commits that already passed:
219+
Bisect's goal is identification, not incremental repair — once it finds the boundary the session is complete. Commit your fix, clear the state, and run again to check whether the rest of the range is clean:
197220

198221
```bash
222+
cd MyProject && git add -p && git commit -m "fix: update to renamed Mathlib.SomeRenamedLemma"
223+
rm -rf MyProject/.lake/hopscotch
224+
199225
hopscotch dep mathlib \
200226
--project-dir ./MyProject \
201227
--from a1b2c3d4 \
202-
--to origin/master \
203-
--allow-dirty-workspace # skip git-cleanliness check since you made edits
228+
--to origin/master
204229
```
205230

206-
`hopscotch` picks up at commit `c3d4e5f6` with your fix applied and continues:
207-
208-
```
209-
[2026-03-31T14:00:00Z] Attempting commit c3d4e5f6 (3/47)
210-
[2026-03-31T14:00:01Z] Running lake update mathlib
211-
212-
[2026-03-31T14:05:00Z] Finished lake build (log file: …) ← now passes
213-
214-
```
231+
If there is only one regression in the range this second run will complete with all commits passing. If there are multiple regressions, bisect will find the next boundary and you repeat.
215232

216-
Repeat steps 3–5 for each failure until the full range passes.
233+
### Aside: Linear mode for incremental iteration
217234

218-
### 6. Pinpoint a breaking commit with bisect
235+
`--scan-mode linear` steps through commits oldest-to-newest and stops at the first failure. It is useful when:
219236

220-
If the commit range is large and you just want to identify the culprit quickly without fixing things incrementally, omit `--scan-mode` (bisect is the default) or pass it explicitly:
237+
- you are testing a single commit (`--from <last-good> --to <candidate>`)
238+
- you prefer to fix each regression before moving to the next, letting you accumulate fixes across a long walk
221239

222240
```bash
223241
hopscotch dep mathlib \
224242
--project-dir ./MyProject \
225243
--from a1b2c3d4 \
226-
--to origin/master
244+
--to origin/master \
245+
--scan-mode linear
227246
```
228247

229-
`hopscotch` binary-searches the range, probing roughly log₂(N) commits instead of all N. The output format is the same per-step timestamped log as linear mode; the summary at `.lake/hopscotch/summary.md` records the last known-good commit and the first known-bad commit.
248+
Because linear mode serializes state after each step, rerunning the same command after a failure resumes from exactly where it stopped. Once the previously-failing commit passes, `hopscotch` checks that the working tree is clean before advancing — ensuring every fix is committed before the session moves on. Pass `--allow-dirty-workspace` to skip this check when you are iterating on a fix across several commits before committing.
230249

231250
### Using a commits file
232251

0 commit comments

Comments
 (0)