Skip to content

fix(pager): render conflicted Git diffs - #1102

Merged
benvinegar merged 3 commits into
modem-dev:mainfrom
0xferrous:fix/git-combined-conflict-diff
Oct 11, 2026
Merged

benvinegar merged 3 commits into
modem-dev:mainfrom
0xferrous:fix/git-combined-conflict-diff

Conversation

@0xferrous

@0xferrous 0xferrous commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

When Git is paused during a conflicted merge or rebase, git diff emits a combined diff using diff --cc/diff --combined headers and @@@ hunk syntax. With core.pager = "hunk pager", Hunk previously treated this input as an empty review:

No files match the current filter.

The pager/difftool configuration was valid; Hunk’s patch sanitizer did not support Git’s combined conflict format.

Fix

Normalize combined Git patches into the existing unified patch format before parsing:

  • Convert combined file and hunk headers to standard diff --git/@@ syntax.
  • Project the result against the first parent.
  • Omit lines deleted only from other parents.
  • Preserve conflict markers and partially resolved changes.
  • Handle binary combined conflicts with no unified hunk.
  • Handle --combined-all-paths by retaining the first parent’s path.
  • Leave ordinary unified patches unchanged.

This keeps the behavior in the shared patch-sanitization layer used by Hunk’s existing consumers.

Reproduction

  1. Configure Hunk as Git’s pager:

    git config --global core.pager "hunk pager"
  2. Start a conflicting merge or rebase.

  3. Run:

    git diff

Before this change, Hunk displayed an empty review. After this change, it displays the conflicted file and its conflict markers.

Validation

  • Focused parser and static pager tests: 42 passed
  • bun run typecheck
  • oxfmt --check
  • git diff --check
  • Pre-commit formatting and lint hooks passed
  • Manual real-PTY reproduction at 120×34 terminal dimensions
  • Added a patch Changeset for hunkdiff

Visual evidence was captured from the real Hunk TUI for the blank before state and rendered after state.

before:
image

after:
image

@vercel

vercel Bot commented Sep 12, 2026

Copy link
Copy Markdown

@0xferrous is attempting to deploy a commit to the Modem Team on Vercel.

A member of the Team first needs to authorize it.

@benvinegar

Copy link
Copy Markdown
Member

Nice. Is this ready? (currently marked as draft)

@0xferrous
0xferrous force-pushed the fix/git-combined-conflict-diff branch from 8211497 to 542303e Compare September 19, 2026 07:09
@0xferrous
0xferrous marked this pull request as ready for review September 19, 2026 07:09
@greptile-apps

greptile-apps Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

PR author is not in the allowed authors list.

0xferrous and others added 3 commits October 11, 2026 16:56
During paused merges and rebases, Git emits merge conflicts as `diff --cc` or
`diff --combined` patches instead of ordinary `diff --git` blocks. Normalize
those combined headers and hunks into a first-parent unified diff so Hunk can
parse and render them.

Add unit and static-renderer coverage for conflicts, binary entries, quoted
paths, and multiple parents.
`git show` puts merge-commit metadata before its combined diff. The metadata
stripper recognized only ordinary patch headers, so it discarded the entire
`diff --cc` or `diff --combined` body and Hunk showed no files.

Recognize combined patch headers as the end of metadata and add regression
coverage for merge-commit output.
@benvinegar

Copy link
Copy Markdown
Member

Rebased onto current main (82642e0b) without conflicts and pushed a review follow-up (bbea1fc4).

Review found combined path normalization could drop a real top-level a/ or b/ directory (binary conflicts and --no-prefix text conflicts) or mishandle mnemonic-prefixed headers. Reproduced with Git, fixed by preserving raw header pairs for the existing sanitizer, and added sanitizer/static-pager regression coverage. Also avoid splitting/rejoining ordinary patches when no combined header exists.

Validation passed:

  • Patch tests: 55 passed
  • Static pager tests: 23 passed
  • bun run test: all shards passed
  • bun run test:integration: 211 passed, 1 platform-specific skip
  • bun run test:tty-smoke: 10 passed
  • bun run typecheck, focused formatting/lint, and git diff --check
  • Real 120×34 PTY smoke using Git-generated --no-prefix text and binary conflicts: exact paths and conflict markers rendered

This comment was generated by Pi using GPT-6.1-sol

@benvinegar
benvinegar force-pushed the fix/git-combined-conflict-diff branch from 542303e to bbea1fc Compare October 11, 2026 21:03
@benvinegar
benvinegar enabled auto-merge (squash) October 11, 2026 21:09
@benvinegar
benvinegar merged commit 0871387 into modem-dev:main Oct 11, 2026
14 of 15 checks passed
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.

2 participants