Show what a force push changed since a review

AL
19m ago
+443-20

Problem and behavior

A reviewer who asks for a rebase or a squash gets a force push back, and --since then records not an ancestor of the head, so the whole diff is reviewed. After this change the bundle says what the author changed:

  • On the same base (a squash, an amend, a reorder), since.diff holds the tree diff of the two heads and the manifest says rewritten. For #585 from d8d4fe8 that is 22 lines instead of 1130.
  • After a rebase, since.range-diff.txt holds git range-diff of the old commits against the new ones and the manifest says rebased. A commit whose only change is its Change-Id reads as unchanged.
  • An old head that cannot be resolved or compared keeps the earlier behavior.

Approach

A tree diff after a rebase also carries what the base brought in: for #584 it is 1754 lines against a whole diff of 1284. So a moved base gets a range-diff, and --since-base names the old base when the old head's merge base with the PR's base is not where it started.

--creation-factor=100 keeps a small commit with a resolved conflict paired with its old version, at the cost of pairing commits that may be unrelated. The pairing is a heuristic and skips merge commits, so SKILL.md and lenses.md say both files only point to what to read first and the whole diff is still reviewed. The comparison also fetches objects the bundle did not need before, by full SHA.

A commit's marker is read only from its header line, so a subject containing ! or a message line shaped like a header cannot mark a changed commit as unchanged.

The semantic comparison jserv raised on #587 is not part of this change.

Validation

  • ./scripts/test.sh all passes except shell-syntax, which reports SC2319 in scripts/git-post-commit.sh; shellcheck gives identical output on main. Removing the new branch fails the new tests.
  • Replayed on #585, #584 and #586: rewritten with 22 lines, rebased with 624 lines of 1284, and rebased with 925 lines of 1200.
  • Four commits of #585 rebased onto e64598e, which touches none of their files, read as = in 4 lines, with or without every Change-Id replaced. One more file added to the second commit marks only that commit !.
  • The fetch path in a clean clone and the cleanup after a failed awk or git were run by hand, with injected failures, and have no test in the tree.

Close #587


Summary by cubic

After a force push, --since compares the old and new heads instead of always reviewing the whole diff: same-base rewrites produce since.diff (rewritten), and rebases produce since.range-diff.txt (rebased). If comparison fails, the bundle keeps the whole-diff behavior.

  • Use --since-base <sha> when the old head’s original base cannot be inferred.
  • These files only point to what to read first; range-diff pairing is heuristic and skips merge commits, and the full diff still needs review.
  • Comparison may fetch missing Git objects; commits changed only by a Change-Id are treated as unchanged.

Closes #587.