fix(read): fail when --from and --to share no merge-base #4555 (#4754)
* test: add tests for missing coverage When `--from` is used, there's no check that the history between `--from` and `--to` (implicitly HEAD if not given) is actually walkeable in the git-log (for example a shallow-clone.) Add tests that check that `read` throws an error when the history between `from` and `to` is not wakleable (no merge-base.) Fix follows in subsequent commit. * fix(read): fail when --from and --to share no merge-base When linting a range with `--from A --to B`, we hand the refs to git-raw-commits, which runs `git log A..B`. If A and B share no common ancestor — typically because we're in a shallow clone where the merge-base wasn't fetched — `git log` doesn't fail; it silently emits whatever subset of the range happens to exist locally. We validate that subset and report success, even though we never saw the rest of the range. This bites hardest in CI. `actions/checkout@v4` clones with `fetch-depth: 1` by default, which is fine for validating `HEAD` but inadequate for any comparison against `origin/HEAD`. A branch with six commits ahead of master surfaces only `HEAD`; if `HEAD`'s message is well-formed, the lint passes regardless of what the unfetched commits look like. Verify the two refs share a merge-base before walking the range, and fail with a clear message when they don't. The check runs only when `from` is set — `--last`, `--edit`, and running without `--from`/`--to` all bypass it, since none of them depend on a two-ended range. When `--to` is omitted, mirror what git-raw-commits does and treat it as `HEAD`, so `--from A` alone is covered too. The accompanying tests use `git checkout --orphan` to create two unrelated histories. That produces the exact condition the check enforces — no merge-base — without coupling the test to the specific shallow-clone trigger. A related case, `--from-last-tag` in a shallow clone, can fail the same way: `git describe` falls back to a hash, we turn that into a no-op range, and zero commits get validated. The merge-base check doesn't catch that path (the no-op sets `from = HEAD-hash`, which trivially merge-bases with `HEAD`), and distinguishing "no tag exists upstream" from "tag isn't fetched" requires shallow-clone probing that's better treated separately. Left for follow-up. Refs https://github.com/conventional-changelog/commitlint/issues/4555 Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Erik Cervin-Edin <erik.cervin-edin@einride.tech> --------- Signed-off-by: Erik Cervin-Edin <erik.cervin-edin@einride.tech> Co-authored-by: Claude <noreply@anthropic.com>
E
Erik Cervin Edin committed
e4595eb79e67a3c51960e95b1dcc696754312cdb
Parent: 1af3138
Committed by GitHub <noreply@github.com>
on 5/14/2026, 11:58:38 AM