Skip to content

A deleted re-export is not a deleted file - #27

Merged
melbinjp merged 1 commit into
mainfrom
shim-move
Aug 19, 2026
Merged

A deleted re-export is not a deleted file#27
melbinjp merged 1 commit into
mainfrom
shim-move

Conversation

@melbinjp

@melbinjp melbinjp commented Aug 19, 2026

Copy link
Copy Markdown
Owner

moved_to asks what the deleting commit renamed, and the commonest large refactor there is defeats it. A split copies a file to its new home and leaves a one-line re-export at the old path so nothing breaks; a later tidy-up deletes the re-export. Git records that second commit as a plain D, correctly - a one-line stub resembles nothing - so the finding reads "deleted and never restored", which is true of the path and false of the content.

Found on zhukunpenglinyutong/desktop-cc-gui:

b66a616b3  "Split app-shell.tsx"    C099  app-shell-parts/modelSelection.ts
                                          -> app-shell/domains/modelSelection.ts
772b6c681  "Clean up useless code"    D   app-shell-parts/modelSelection.ts  (1 line)

Its onboarding guide - status: active in its own frontmatter, calibrated to the current release - lists the old path among the files you must edit to add an engine. The function is at line 112 of the new one. Six of that project's eleven findings are that one commit pair, and a patch saying "deleted" would have been wrong on all six.

Lineage is proved, never guessed

The obvious version looks for a same-basename file at HEAD. That is the rule BARE-FILENAME-VERDICT.md rejected wearing a different hat. Measured on the 160 corpus findings that say "never restored", 25 have a same-basename file and no lineage, and reading them settles it:

says a namesake at HEAD
sdk/package.json package.json
pkg/registry/types.go pkg/git/types.go
config/prod.exs test_integrations/phoenix_app/config/prod.exs
website/content/getting-started.md third-party/vendor/logos-0.14.4/book/src/getting-started.md

So basename is how candidates are found; git log --follow --find-copies from the candidate is the only thing that accepts one.

And the source must not have grown after the copy

Ten findings had proven lineage and one was plainly wrong:

bytebase  docs/adding-new-object-to-sdl-mode.md:492
          says    backend/plugin/schema/pg/generate_migration.go
          C077 in 044c898364  "feat: implement oracle generate migration (#16546)"

Somebody copied the Postgres implementation to start the Oracle one. Nothing moved - there are four generate_migration.go at that HEAD, one per dialect. Dropping --find-copies and taking only R removes it and also removes desktop-cc-gui, which git records as C099. Size at deletion does not separate them: the true group runs from 1 line to 252 and cherry-studio sits at 0.979 of its destination.

What separates them is the source after the copy landed. A file on its way out is frozen; a forked sibling keeps being developed.

source at copy → at deletion commits between
desktop-cc-gui ×6 1 → 1 0 move
bytebase directiveUtils.ts 252 → 252 0 move
cherry-studio useToolApproval.ts 143 → 143 0 move
sentry-rn build.gradle 42 → 22 4 move (shrank)
bytebase generate_migration.go 1583 → 5192 44 fork

Nine of ten survive; the tenth is the fork.

Honest limits

Recall is 9 of 160 findings, 5.6%, and six of the nine are one commit pair in one project. This pattern is concentrated rather than common - which is also why it matters: a project that does one split-with-shims gets every finding mis-explained at once, and that is exactly the project most likely to reject the patch. The growth rule is fitted against a single negative case, and the docstring says so rather than implying a corpus behind it.

Validated by someone else

getsentry/sentry-react-native made this exact edit unprompted in fd677570 ("docs: update CONTRIBUTING paths for the monorepo layout", #6594, 2026-08-18), replacing sample/android/build.gradle with samples/react-native/android/build.gradle - the destination this computes.

The verdict never changes

The path really is gone and the document really is stale. This only decides whether the reader is told where to look. Verified end to end against the real desktop-cc-gui clone: still 13 broken, six now naming the destination, the two genuine renames still handled by moved_to, the five genuine deletions unchanged. And against the real bytebase clone: the Oracle fork refused, the directiveUtils.ts move named.

208 tests, five of them new - two positive, three negative, and the negatives were probed to confirm they refuse for the stated reason rather than passing on an empty candidate list.

`moved_to` asks what the deleting commit renamed, and the commonest large
refactor there defeats it. A split copies a file to its new home and leaves a
one-line re-export at the old path; a later tidy-up deletes the re-export. Git
records that second commit as a plain `D`, correctly - a one-line stub resembles
nothing - so the finding says "deleted and never restored", which is true of the
path and false of the content.

`zhukunpenglinyutong/desktop-cc-gui`:

    b66a616b3  "Split app-shell.tsx"    C099  app-shell-parts/modelSelection.ts
                                              -> app-shell/domains/modelSelection.ts
    772b6c681  "Clean up useless code"    D   app-shell-parts/modelSelection.ts  (1 line)

Its onboarding guide - `status: active`, calibrated to the current release -
lists the old path among the files you must edit to add an engine. The function
is at line 112 of the new one. Six of that project's eleven findings are that
one commit pair.

Lineage is proved, never guessed. Of the 160 corpus findings that say "never
restored", 25 have a same-basename file at HEAD and no lineage, and reading them
is enough: `sdk/package.json` -> `package.json`, `pkg/registry/types.go` ->
`pkg/git/types.go`, `website/content/getting-started.md` -> a vendored copy
under `third-party/`. Basename finds candidates; only `log --follow
--find-copies` accepts one.

And the source must not have grown after the copy. Ten had proven lineage and
one was plainly wrong - bytebase's `feat: implement oracle generate migration`
copied the Postgres generator to start the Oracle one, and both went on living.
Taking only `R` would also lose desktop-cc-gui, which git records as `C099`;
size at deletion does not separate them either. What does is the source after
the copy: frozen for a move, developed for a fork.

Recall is 9 of 160, 5.6%, six of them one commit pair - concentrated rather than
common, which is also why it matters. The growth rule is fitted against a single
negative case and the docstring says so.

`getsentry/sentry-react-native` made this exact edit unprompted in `fd677570`
(#6594, 2026-08-18), arriving at the destination this computes.

The verdict never changes. This only decides whether the reader is told where to
look.
@melbinjp
melbinjp merged commit b364bcd into main Aug 19, 2026
21 checks passed
@melbinjp
melbinjp deleted the shim-move branch August 19, 2026 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant