Skip to content

fix: split dense hunks when staging non-contiguous replacements - #2

Open
andresespinosapc wants to merge 1 commit into
Omegaice:masterfrom
andresespinosapc:fix/non-contiguous-replacements-dense-hunk
Open

fix: split dense hunks when staging non-contiguous replacements#2
andresespinosapc wants to merge 1 commit into
Omegaice:masterfrom
andresespinosapc:fix/non-contiguous-replacements-dense-hunk

Conversation

@andresespinosapc

Copy link
Copy Markdown

Summary

When the user selects multiple non-contiguous delete+add pairs from a single dense replacement hunk (e.g. file:-2,2,-4,4 against a hunk of -b,-c,-d,+B,+C,+D), the previous implementation collapsed the kept deletions and additions into a single output hunk. git apply rejected the resulting patch with patch does not apply because the deleted lines are not consecutive in HEAD.

Repro

$ printf 'a\nb\nc\nd\ne\n' > dense.txt && git add dense.txt && git commit -m init
$ printf 'a\nB_changed\nC_changed\nD_changed\ne\n' > dense.txt
$ git lines stage dense.txt:-2,2,-4,4
Error: git apply failed: error: patch failed: dense.txt:2
error: dense.txt: patch does not apply

This is the case the existing // Case 3: Mixed ... For now, keep as single hunk - more complex splitting could be added later comment in into_hunks flagged.

Fix

FilteredContent.additions now preserves the new-line position of each addition (Vec<(u32, String)> instead of Vec<String>), letting into_hunks split the mixed (deletions + additions) case into one hunk per contiguous deletion group, paired by index with the corresponding contiguous addition group. The split applies only when group counts match and no no-newline state is involved; asymmetric selections fall back to the previous single-hunk behavior.

After the fix:

$ git lines stage dense.txt:-2,2,-4,4
Staged:
dense.txt:
  -2:	b
  +2:	B_changed

  -4:	d
  +4:	D_changed

$ git diff --cached
@@ -1,5 +1,5 @@
 a
-b
+B_changed
 c
-d
+D_changed
 e

Test plan

  • Adds e2e test replacement::non_contiguous_in_dense_hunk (3.10) covering the bug
  • Updates the unit tests asserting on FilteredContent.additions for the new tuple type
  • Full suite green: 83 lib + 48 e2e + 7 doc-tests = 138 tests, 0 failures
  • Manual smoke test reproducing the original failure now passes

🤖 Generated with Claude Code

When the user selects multiple non-contiguous delete+add pairs from a
single dense replacement hunk (e.g. `file:-2,2,-4,4` against a hunk of
`-b,-c,-d,+B,+C,+D`), the previous implementation collapsed the kept
deletions and additions into a single output hunk. git apply rejected
the resulting patch with `patch does not apply` because the deleted
lines are not consecutive in HEAD.

`FilteredContent.additions` now preserves the new-line position of each
addition, letting `into_hunks` split the mixed (deletions + additions)
case into one hunk per contiguous deletion group, paired by index with
the corresponding contiguous addition group. The split applies only
when group counts match and no no-newline state is involved;
asymmetric selections fall back to the previous single-hunk behavior.

Adds e2e test 3.10 (`non_contiguous_in_dense_hunk`) covering the bug
and updates the unit tests that asserted on the `additions` field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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