Skip to content

Feature: Branch Diff — compare two branches side by side #25

@zelon

Description

@zelon

Overview

Add a Branch Diff view that lets users select any two branches and see the diverging commits and per-file diffs. Especially useful for reviewing changes before opening a Pull Request.

UX Design

Key Principles

  • File list first, not full diff: clicking a file shows its diff instead of rendering everything at once (avoids performance issues on large branches)
  • "All commits" pinned row: explicit default selection at top of commit list — makes "no individual commit selected" state obvious and intentional
  • Reuse existing Quick Diff panel: file clicks send the diff to the LeftSidebar Quick Diff panel, consistent with PendingTab and HistoryTab behavior

Entry Point

  • [⇄ Compare] button added to the Branches tab header
  • Opens a closeable "Branch Diff" tab in the main tab bar

ASCII Mockups

Default state — "All commits" selected, no file clicked yet

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│  wimygit  [my-project]                                                         [Fetch] [Push]     │
├───────────────┬──────────────────────────────────────────────────────────────────────────────────┤
│               │  Pending Changes │ History │ Branches │ Remotes │ ⇄ Branch Diff  ✕              │
│  [Workspace]  ├──────────────────────────────────────────────────────────────────────────────────┤
│  [Quick Diff] │                                                                                  │
│               │   Base: [ main              ▾ ]   ⇄   Compare: [ feature/login        ▾ ]       │
│               │   ─────────────────────────────────────────────────────────────────────────────  │
│  (empty)      │   3 commits ahead  ·  5 files changed  ·  +120  −34 lines                       │
│               │   ─────────────────────────────────────────────────────────────────────────────  │
│  Click a      ├─────────────────────────────────┬────────────────────────────────────────────────┤
│  file to      │  Commits                        │  Changed Files (5)                             │
│  see its      │  ───────────────────────────────│  ──────────────────────────────────────────── │
│  diff here    │                                 │                                                │
│               │  ┌───────────────────────────┐  │  📄 src/auth/Login.tsx          +80    −0     │
│               │  │  ▶  All  (3 commits)      │  │  📄 src/auth/api.ts             +35   −12     │
│               │  │     +120  −34  ·  5 files │  │  📄 src/auth/types.ts           +15    −0     │
│               │  └───────────────────────────┘  │  📄 tests/auth.test.ts          +28    −0     │
│               │                                 │  📄 src/App.tsx                  +2   −22     │
│               │  ─────────────────────────────  │                                               │
│               │  a1b2c3  Add login UI component  │                                               │
│               │  zelon  ·  2026-05-30  10:22     │                                               │
│               │                                 │                                               │
│               │  d4e5f6  Add auth API endpoints  │                                               │
│               │  zelon  ·  2026-05-29  14:05     │                                               │
│               │                                 │                                               │
│               │  g7h8i9  Add auth unit tests     │                                               │
│               │  zelon  ·  2026-05-28  09:41     │                                               │
└───────────────┴─────────────────────────────────┴────────────────────────────────────────────────┘

After clicking a file — Quick Diff panel auto-activates

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│  wimygit  [my-project]                                                         [Fetch] [Push]     │
├───────────────┬──────────────────────────────────────────────────────────────────────────────────┤
│               │  Pending Changes │ History │ Branches │ Remotes │ ⇄ Branch Diff  ✕              │
│  [Workspace]  ├──────────────────────────────────────────────────────────────────────────────────┤
│ ▶[Quick Diff] │                                                                                  │
│  ───────────  │   Base: [ main              ▾ ]   ⇄   Compare: [ feature/login        ▾ ]       │
│               │   ─────────────────────────────────────────────────────────────────────────────  │
│  src/auth/    │   3 commits ahead  ·  5 files changed  ·  +120  −34 lines                       │
│  api.ts       │   ─────────────────────────────────────────────────────────────────────────────  │
│  ───────────  │                                                                                  │
│  @@ -12,6     ├─────────────────────────────────┬────────────────────────────────────────────────┤
│  +12,40 @@    │  Commits                        │  Changed Files (5)                             │
│               │  ───────────────────────────────│  ──────────────────────────────────────────── │
│   export      │                                 │                                                │
│   const       │  ┌───────────────────────────┐  │  📄 src/auth/Login.tsx          +80    −0     │
│   authApi={   │  │  ▶  All  (3 commits)      │  │ ▶ src/auth/api.ts               +35   −12  ◀─┤
│  +  login:    │  │     +120  −34  ·  5 files │  │  📄 src/auth/types.ts           +15    −0    │
│  +    async   │  └───────────────────────────┘  │  📄 tests/auth.test.ts          +28    −0     │
│  +    (e, p)  │                                 │  📄 src/App.tsx                  +2   −22     │
│  +    => {    │  ─────────────────────────────  │                                               │
│  +    ...     │  a1b2c3  Add login UI component  │                                               │
│  +  },        │  zelon  ·  2026-05-30  10:22     │                                               │
│  +  logout:   │                                 │                                               │
│  +    async   │  d4e5f6  Add auth API endpoints  │                                               │
│  +    () =>   │  zelon  ·  2026-05-29  14:05     │                                               │
│  +    { ...   │                                 │                                               │
│  ...          │  g7h8i9  Add auth unit tests     │                                               │
│               │  zelon  ·  2026-05-28  09:41     │                                               │
└───────────────┴─────────────────────────────────┴────────────────────────────────────────────────┘

Individual commit selected — file list narrows to that commit

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│  wimygit  [my-project]                                                         [Fetch] [Push]     │
├───────────────┬──────────────────────────────────────────────────────────────────────────────────┤
│               │  Pending Changes │ History │ Branches │ Remotes │ ⇄ Branch Diff  ✕              │
│  [Workspace]  ├──────────────────────────────────────────────────────────────────────────────────┤
│ ▶[Quick Diff] │                                                                                  │
│  ───────────  │   Base: [ main              ▾ ]   ⇄   Compare: [ feature/login        ▾ ]       │
│               │   ─────────────────────────────────────────────────────────────────────────────  │
│  src/auth/    │   3 commits ahead  ·  5 files changed  ·  +120  −34 lines                       │
│  Login.tsx    │   ─────────────────────────────────────────────────────────────────────────────  │
│  ───────────  │                                                                                  │
│  @@ -0,0      ├─────────────────────────────────┬────────────────────────────────────────────────┤
│  +1,80 @@     │  Commits                        │  Files in a1b2c3  (2 files)                   │
│               │  ───────────────────────────────│  ──────────────────────────────────────────── │
│  + import     │                                 │                                                │
│  + React      │  ┌───────────────────────────┐  │ ▶ src/auth/Login.tsx            +80    −0  ◀─ │
│  + from       │  │     All  (3 commits)      │  │  📄 src/auth/types.ts           +15    −0     │
│  + 'react'    │  └───────────────────────────┘  │                                               │
│  +            │                                 │                                               │
│  + export     │  ─────────────────────────────  │                                               │
│  + function   │                                 │                                               │
│  + Login() {  │ ▶ a1b2c3  Add login UI component│  ← selected commit (highlighted)              │
│  +   const    │  zelon  ·  2026-05-30  10:22     │                                               │
│  +   [email,  │                                 │                                               │
│  +   setEmail]│  d4e5f6  Add auth API endpoints  │                                               │
│  +   =        │  zelon  ·  2026-05-29  14:05     │                                               │
│  +   useState │                                 │                                               │
│  +   ('');    │  g7h8i9  Add auth unit tests     │                                               │
│  ...          │  zelon  ·  2026-05-28  09:41     │                                               │
└───────────────┴─────────────────────────────────┴────────────────────────────────────────────────┘

Expected UX Flow

Branches tab → [⇄ Compare] button
  → "Branch Diff" tab opens
  → Base = main, Compare = current branch (defaults)
  → Left panel: "All (N commits)" row selected by default + individual commits below
  → Right panel: list of all changed files (with +/- stats)
  → Click a file → Quick Diff panel in LeftSidebar auto-activates and shows diff
  → Click a commit → right panel narrows to files changed in that commit only
  → Click a file under a commit → Quick Diff shows that commit's file diff
  → Click "All" row again → back to combined file list
  → Click ✕ on tab → tab closes, Quick Diff clears

Implementation Notes

  • Entry point: [⇄ Compare] button in BranchTab.tsx opens BranchDiffTab as a closeable dynamic tab
  • No embedded diff viewer: diff is shown in the existing SidebarQuickDiff in LeftSidebar — file click triggers auto-switch to Quick Diff tab (same pattern as HistoryTab and PendingTab)
  • Backend (TypeScript only, no new Rust needed):
    • git log base..compare --format=... — diverging commit list
    • git diff --numstat base...compare — file list with line counts
    • git diff base...compare -- <file> — single file diff
  • Reuse existing components:
    • SidebarQuickDiff.tsx — add branchFileDiff prop (new mode alongside existing selectedDiff / pendingFilePreview)
    • getBranches() / getCurrentBranch() — branch selector dropdowns
    • getCommitFiles() — file list when individual commit selected
    • runGitSimple() — raw git invocations for new functions
  • Related files:
    • src/components/tabs/BranchTab.tsx
    • src/components/tabs/BranchDiffTab.tsx ← new
    • src/components/layout/SidebarQuickDiff.tsx
    • src/components/layout/LeftSidebar.tsx
    • src/lib/git-api.ts
    • src/lib/git-types.ts
    • src/App.tsx

Related Features

  • Natural stepping stone toward GitHub PR creation integration
  • Pairs well with the planned Interactive Rebase UI

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions