Skip to content

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

Open
0xferrous wants to merge 2 commits into
modem-dev:mainfrom
0xferrous:fix/git-combined-conflict-diff
Open

0xferrous wants to merge 2 commits into
modem-dev:mainfrom
0xferrous:fix/git-combined-conflict-diff

Conversation

@0xferrous

@0xferrous 0xferrous commented Sep 12, 2026 •

Copy link
Copy Markdown

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

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.
@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.

`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

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.

This branch has not been deployed

No deployments
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