[DIT-13470] collect git file rename data - #158
Merged
Merged
Conversation
laurakoye
approved these changes
Sep 1, 2026
| }); | ||
| return ZGetLastScanShaResponse.parse(response.data).lastScanSha ?? null; | ||
| } catch { | ||
| return null; |
Contributor
There was a problem hiding this comment.
Should we be logging here?
Contributor
Author
There was a problem hiding this comment.
going to skip the logging here, since this is a valid path for initial scans where no existing scan exists yet.
| * keeps its links instead of reading as a delete plus a create. Empty when there is | ||
| * no git context, no earlier scan, or no way to reach the earlier commit. | ||
| */ | ||
| async function readRenamesSinceLastScan(gitContext: GitContext | null) { |
Comment on lines
+140
to
+160
| const out = await git( | ||
| ["diff", "-M", "--name-status", "-z", previousSha, "HEAD"], | ||
| repoRoot | ||
| ); | ||
| if (!out) return []; | ||
|
|
||
| // `-z` gives NUL-separated fields: a status, then one path, or two for a rename or a copy. | ||
| const fields = out.split("\0"); | ||
| const renames: GitRename[] = []; | ||
| for (let i = 0; i < fields.length && fields[i]; ) { | ||
| const status = fields[i][0]; | ||
| if (status === "R" || status === "C") { | ||
| const [from, to] = [fields[i + 1], fields[i + 2]]; | ||
| if (status === "R" && from && to) renames.push({ from, to }); | ||
| i += 3; | ||
| } else { | ||
| i += 2; | ||
| } | ||
| } | ||
| return renames; | ||
| } |
Contributor
There was a problem hiding this comment.
I believe this can be simplified. Adding --diff-filter=R makes git send back only the renames. Every record is then the same shape, so the parser becomes a step by 3 loop.
Worth it mainly for the output size.
Suggested change
| const out = await git( | |
| ["diff", "-M", "--name-status", "-z", previousSha, "HEAD"], | |
| repoRoot | |
| ); | |
| if (!out) return []; | |
| // `-z` gives NUL-separated fields: a status, then one path, or two for a rename or a copy. | |
| const fields = out.split("\0"); | |
| const renames: GitRename[] = []; | |
| for (let i = 0; i < fields.length && fields[i]; ) { | |
| const status = fields[i][0]; | |
| if (status === "R" || status === "C") { | |
| const [from, to] = [fields[i + 1], fields[i + 2]]; | |
| if (status === "R" && from && to) renames.push({ from, to }); | |
| i += 3; | |
| } else { | |
| i += 2; | |
| } | |
| } | |
| return renames; | |
| } | |
| const out = await git( | |
| ["diff", "-M","--diff-filter=R","--name-status","-z",previousSha,"HEAD"], | |
| repoRoot | |
| ); | |
| if (!out) return []; | |
| const fields = out.split("\0").filter(Boolean); | |
| const renames: GitRename[] = []; | |
| for (let i = 0; i + 2 < fields.length; i += 3) { | |
| renames.push({ from: fields[i + 1], to: fields[i + 2] }); | |
| } | |
| return renames; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
CLI half of https://linear.app/dittowords/issue/DIT-13470/rename-pass. Before a scan starts, the CLI asks the server which commit the last scan read. It diffs that commit against
HEADwithgit diff -Mand records what git says was moved or renamed.Something to note is that git's similarity index decides what counts as a rename, not us. A heavily rewritten file is not a rename.
Every failure path returns no renames but never blocks the scan. That covers no git, no earlier scan, a shallow clone, an unreachable server, etc. A move of more than 1000 files is capped..
Context
Merge the ditto-app PR first.
Screenshots
Test Plan