Expand description
Falsification (c): how often does a landed merge remove work that neither side removed?
crate::safety::check answers that question for one merge. This
module points it at a repository’s real merge history so the question
can be answered with a number instead of an argument. The plan it
serves, its kill criterion and the reasoning behind both live outside
the repository; what matters here is that the criterion was fixed
before the number was known, so a near-zero result is an answer and
not a prompt to re-cut the measurement.
§What is compared, and to what
For a merge commit M with first parent T (the target branch, the
side that was being merged onto) and second parent P (the
proposal), with B = merge-base(T, P):
base = B:<path> what the author wrote against
target = T:<path> the state being merged onto
proposed = P:<path> what the author wrote
result = M:<path> what actually landedwhich is exactly crate::safety::check’s signature. A path missing
from a tree reads as empty, so an added file compares as an addition
and a deleted file as a removal, both of which the bag comparison
already handles.
Only paths where M differs from T are examined. A path the merge
left identical to the target has an empty landing delta and therefore
always upholds, so scanning it would cost four blob reads to learn
nothing.
§What a finding is worth, stated before any are counted
A violation here is evidence of a silent revert, not proof of a defect, and the honest reading is bounded on both sides:
- False positives are expected and are the dominant noise. A merge
whose conflicts a human resolved by hand is free to remove lines
neither parent removed, and that is a correct resolution, not a
silent revert. Automatic merges — a merge queue’s,
--no-ffon a clean tree — are where a finding means what it says. The report keeps the two apart only as far as git lets it, which is not far; any non-zero count wants eyes on the individual findings before it is quoted at anybody. - False negatives dominate the other direction. The comparison is
over line bags, so a merge that moves a line, or applies an edit at
the wrong occurrence of a repeated line, is bag-neutral and passes.
That is
crate::safety’s stated positional blindness, inherited here whole.
So the count is a lower bound on a noisy signal. It is worth
having anyway, for the same reason choir-queue’s corpus module
is: it needs nothing but git — no CI history, no issue tracker, no
human labelling — and an unmeasured rate cannot be argued with at
all.
§Shape
Same split as choir-queue::corpus: parsing and scanning are pure
functions over text, and every shell-out is a separate call, so the
tests are hermetic and the expensive part is the caller’s problem.
§Examples
use choir_merge::silent_revert::{scan_merge, Blobs, ScanReport};
// The target added a line after the fork; the proposal touched a
// different one; the landed result dropped the target's line.
let blobs = Blobs {
base: "a\n".into(),
target: "a\nkeep\n".into(),
proposed: "a\nb\n".into(),
result: "a\nb\n".into(),
};
let mut report = ScanReport::default();
scan_merge("deadbeef", &[("src/x.rs".to_string(), blobs)], &mut report);
assert_eq!(report.findings.len(), 1);
assert_eq!(report.findings[0].reverted, vec!["keep".to_string()]);Structs§
- Blobs
- The four texts
crate::safety::checkcompares, for one path. - Finding
- One path in one merge that removed or added lines neither side did.
- Merge
Commit - One merge commit, reduced to what the scan needs.
- Scan
Report - What one repository’s scan counted.
Constants§
- MAX_
BLOB_ BYTES - Blobs larger than this are skipped rather than compared.
- MERGE_
LOG_ FORMAT - The
--formatstringparse_mergesexpects.
Functions§
- changed_
paths - Paths where
todiffers fromfrom. - merge_
base git merge-base a b, orNonewhen they share none.- merge_
log - The merge commits on
repo’s first-parent mainline, newest first. - parse_
batch - Splits
cat-file --batchoutput intocountpositional results. - parse_
merges - Parses
git log --merges MERGE_LOG_FORMAToutput. - scan_
merge - Applies the safety check to every path of one merge, counting into
report. - scan_
repo - Scans one repository’s merge history.