Skip to main content

The Merge Line Problem

In a Git graph visualization, branches are represented as colored lines. When two branches merge, what color should the merge line be?
┌────────────────────────────────────────────────────────────────────────────────┐
│                    GIT GRAPH VISUALIZATION PROBLEM                             │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   Simple Approach: Use target branch color                                     │
│   ═════════════════════════════════════════                                    │
│                                                                                │
│          main (blue)          feature (orange)                                 │
│              │                     │                                           │
│              │                     │                                           │
│              │    merge commit     │                                           │
│              │<────────────────────┘                                           │
│              │         ^                                                       │
│              │         │                                                       │
│              │    What color?                                                  │
│              v                                                                 │
│                                                                                │
│   If we use blue (main's color):                                               │
│   - The merge line looks like a normal main commit                             │
│   - We lose the visual connection to feature branch                            │
│                                                                                │
│   If we use orange (feature's color):                                          │
│   - Inconsistent with main's visual identity                                   │
│   - Confusing: is this main or feature?                                        │
│                                                                                │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   Better Approach: Interpolate between both colors                             │
│   ═════════════════════════════════════════════════                            │
│                                                                                │
│          main (blue)          feature (orange)                                 │
│              │                     │                                           │
│              │                     │                                           │
│              │<───────BLEND────────┘                                           │
│              │     (50% mix)                                                   │
│              │                                                                 │
│                                                                                │
│   The merge line should visually represent BOTH parents.                       │
│   Using color interpolation creates this effect.                               │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

sRGB vs OKLAB for Merge Lines

┌────────────────────────────────────────────────────────────────────────────────┐
│                    sRGB MERGE LINE: MUDDY RESULT                               │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   main: rgb(38, 136, 199)   -- Blue (#2688C7)                                  │
│   feature: rgb(199, 136, 38) -- Orange (#C78826)                               │
│                                                                                │
│   sRGB midpoint:                                                               │
│   R = (38 + 199) / 2 = 118.5                                                   │
│   G = (136 + 136) / 2 = 136                                                    │
│   B = (199 + 38) / 2 = 118.5                                                   │
│                                                                                │
│   Result: rgb(119, 136, 119) -- Grayish-green                                  │
│                                                                                │
│              main                   feature                                    │
│           (vibrant)               (vibrant)                                    │
│              │                         │                                       │
│              │    ┌───────────┐       │                                        │
│              │<───│ MUDDY MIX │───────┘                                        │
│              │    │ (dull)    │                                                │
│              │    └───────────┘                                                │
│              v                                                                 │
│                                                                                │
│   The merge line looks "sick" or "faded" compared to vibrant branches.         │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────┐
│                    OKLAB MERGE LINE: CLEAN RESULT                              │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   main: oklch(55% 0.15 230)   -- Blue                                          │
│   feature: oklch(55% 0.15 50) -- Orange                                        │
│                                                                                │
│   Blue and Orange are OPPOSITE on the color wheel (180 apart).                 │
│   Their true midpoint IS neutral. This is mathematically correct.              │
│                                                                                │
│   The DIFFERENCE from sRGB:                                                    │
│   - sRGB gray: Muddy, brownish-green, inconsistent lightness                   │
│   - OKLAB gray: Clean neutral gray, consistent lightness                       │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

Non-Opposite Colors: Where OKLAB Shines

Most branch combinations are NOT opposite colors, and this is where OKLAB really demonstrates its value.
┌────────────────────────────────────────────────────────────────────────────────┐
│                    NON-OPPOSITE COLORS: OKLAB ADVANTAGE                        │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   main: oklch(55% 0.15 230)    -- Blue                                         │
│   hotfix: oklch(55% 0.15 25)   -- Red                                          │
│                                                                                │
│   Hue difference: 230 - 25 = 205 degrees (not opposite!)                       │
│                                                                                │
│   OKLAB interpolation:                                                         │
│   main:   L=0.55, a=-0.10, b=-0.11                                             │
│   hotfix: L=0.55, a=0.13, b=0.07                                               │
│                                                                                │
│   Midpoint:                                                                    │
│   L = 0.55                                                                     │
│   a = (-0.10 + 0.13) / 2 = 0.015                                               │
│   b = (-0.11 + 0.07) / 2 = -0.02                                               │
│                                                                                │
│   Result: A desaturated purple-ish color (not gray!)                           │
│   The hue is approximately 307deg with low chroma.                             │
│                                                                                │
│   Compare to sRGB:                                                             │
│   sRGB midpoint would be muddy brown-gray.                                     │
│   OKLAB midpoint is a recognizable (if muted) purple.                          │
│                                                                                │
│              main (blue)       hotfix (red)                                    │
│                  │                 │                                           │
│                  │                 │                                           │
│                  │<───purple-ish───┘                                           │
│                  │     (clean)                                                 │
│                  v                                                             │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

Branch Color Distribution with Golden Angle

For maximum distinction between branches, use the full Golden Angle (137.5 degrees).
┌────────────────────────────────────────────────────────────────────────────────┐
│                    BRANCH COLOR DISTRIBUTION                                   │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   Using Golden Angle (137.5 degrees) for maximum distinction:                  │
│                                                                                │
│   Branch      Index    Hue Calculation         Result                          │
│   ──────      ─────    ───────────────         ──────                          │
│   main        0        0 + 0*137.5 = 0         0deg (Red)                      │
│   develop     1        0 + 1*137.5 = 137.5     137.5deg (Yellow-Green)         │
│   feature-1   2        0 + 2*137.5 = 275       275deg (Blue-Purple)            │
│   feature-2   3        0 + 3*137.5 = 52.5      52.5deg (Yellow-Orange)         │
│   hotfix      4        0 + 4*137.5 = 190       190deg (Cyan)                   │
│   release     5        0 + 5*137.5 = 327.5     327.5deg (Pink-Red)             │
│                                                                                │
│   No matter how many branches, they never cluster together.                    │
│                                                                                │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   Color Wheel with Branch Distribution:                                        │
│                                                                                │
│                          0deg (main)                                           │
│                              *                                                 │
│                         /         \                                            │
│                        /           \                                           │
│                   5 *               * 3 (feature-2)                            │
│               (release)         52.5deg                                        │
│                      /               \                                         │
│                     /                 \                                        │
│     270deg ────────┼───────────────────┼──────── 90deg                         │
│                     \                 /                                        │
│                      \               /                                         │
│                   2 *               * 4 (hotfix)                               │
│              (feature-1)        190deg                                         │
│               275deg    \       /                                              │
│                          \     /                                               │
│                           \   /                                                │
│                              *                                                 │
│                          1 (develop)                                           │
│                          137.5deg                                              │
│                                                                                │
│   Maximum separation between any two branches.                                 │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

Merge Scenarios

Feature into Main

┌────────────────────────────────────────────────────────────────────────────────┐
│                    SCENARIO: FEATURE -> MAIN                                   │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   main:    oklch(55% 0.15 0)     -- Red (H=0)                                  │
│   feature: oklch(55% 0.15 275)   -- Blue-Purple (H=275)                        │
│                                                                                │
│   Hue difference: 275 - 0 = 275 degrees                                        │
│   (Or shorter path: 360 - 275 = 85 degrees)                                    │
│                                                                                │
│   OKLAB interpolation will find geometric midpoint:                            │
│   Result: approximately H=320 (Pink-Magenta area)                              │
│                                                                                │
│        main (red)                                                              │
│            *                                                                   │
│            │                                                                   │
│            │<───── merge line (pink-ish) ─────* feature (purple)               │
│            │                                                                   │
│            v                                                                   │
│                                                                                │
│   The merge line is visually between both colors.                              │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

Hotfix into Main

┌────────────────────────────────────────────────────────────────────────────────┐
│                    SCENARIO: HOTFIX -> MAIN                                    │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   main:   oklch(55% 0.15 0)      -- Red (H=0)                                  │
│   hotfix: oklch(55% 0.15 190)    -- Cyan (H=190)                               │
│                                                                                │
│   Hue difference: 190 degrees (close to opposite!)                             │
│                                                                                │
│   OKLAB interpolation:                                                         │
│   Result: Low chroma, approximately neutral                                    │
│                                                                                │
│        main (red)                                                              │
│            *                                                                   │
│            │                                                                   │
│            │<───── merge line (grayish) ─────* hotfix (cyan)                   │
│            │                                                                   │
│            v                                                                   │
│                                                                                │
│   Near-opposite colors produce near-neutral merge.                             │
│   This is mathematically correct and perceptually appropriate.                 │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

Merge Commit vs Merge Line

┌────────────────────────────────────────────────────────────────────────────────┐
│                    MERGE COMMIT vs MERGE LINE                                  │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   Distinction:                                                                 │
│   - Merge LINE: The arrow/line connecting parent to merge commit               │
│   - Merge COMMIT: The node representing the merge itself                       │
│                                                                                │
│              parent1                parent2                                    │
│                  *                       *                                     │
│                   \                     /                                      │
│                    \  <- MERGE LINE -> /                                       │
│                     \   (interpolated)/                                        │
│                      \               /                                         │
│                       \             /                                          │
│                        \           /                                           │
│                         ┌────*────┐                                            │
│                              ^                                                 │
│                              │                                                 │
│                         MERGE COMMIT                                           │
│                    (target branch color)                                       │
│                                                                                │
│   Color assignments:                                                           │
│   - Merge LINE from parent1: color-mix(in oklab, parent1, target 50%)          │
│   - Merge LINE from parent2: color-mix(in oklab, parent2, target 50%)          │
│   - Merge COMMIT: target branch color (pure)                                   │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

CSS Implementation

/* Branch Core Colors (OKLCH) */
:root {
  --branch-main: oklch(55% 0.15 0);
  --branch-develop: oklch(55% 0.15 137.5);
  --branch-feature-1: oklch(55% 0.15 275);
  --branch-feature-2: oklch(55% 0.15 52.5);
  --branch-hotfix: oklch(55% 0.18 190);
  --branch-release: oklch(55% 0.15 327.5);
}

/* Merge Line Colors via color-mix (Flow) */
.git-graph .merge-line {
  --merge-color: color-mix(
    in oklab,
    var(--parent-1-color) 50%,
    var(--parent-2-color)
  );
  background: var(--merge-color);
}

/* Specific merge scenarios */
.merge-line[data-from="feature"][data-to="main"] {
  --merge-color: color-mix(
    in oklab,
    var(--branch-main) 50%,
    var(--branch-feature-1)
  );
}

.merge-line[data-from="hotfix"][data-to="main"] {
  --merge-color: color-mix(
    in oklab,
    var(--branch-main) 50%,
    var(--branch-hotfix)
  );
}

Hierarchical Coloring for Many Branches

┌────────────────────────────────────────────────────────────────────────────────┐
│                    HIERARCHICAL BRANCH COLORING                                │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   Number of branches    Strategy                                               │
│   ──────────────────    ────────                                               │
│                                                                                │
│   2-6 branches          Golden angle works perfectly                           │
│                         All colors clearly distinct                            │
│                                                                                │
│   7-12 branches         Golden angle still works                               │
│                         Some colors may feel similar                           │
│                         Consider varying lightness/chroma                      │
│                                                                                │
│   13-20 branches        Colors start to repeat visually                        │
│                         Use groups (same hue, different chroma)                │
│                                                                                │
│   20+ branches          Color alone is insufficient                            │
│                         Add secondary indicators (patterns, icons)             │
│                                                                                │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│   Group by type, vary within groups:                                           │
│                                                                                │
│   Tier 1: Branch Type (Hue)                                                    │
│   ─────────────────────────                                                    │
│   main/master:     Red area (0-30)                                             │
│   develop:         Green area (100-160)                                        │
│   feature/*:       Blue area (200-260)                                         │
│   hotfix/*:        Orange area (30-60)                                         │
│   release/*:       Purple area (270-330)                                       │
│                                                                                │
│   Tier 2: Within Group (Chroma/Lightness)                                      │
│   ───────────────────────────────────────                                      │
│   feature/auth:    oklch(55% 0.15 220)                                         │
│   feature/ui:      oklch(55% 0.12 230)  <- lower chroma                        │
│   feature/api:     oklch(60% 0.15 240)  <- higher lightness                    │
│   feature/db:      oklch(50% 0.15 250)  <- lower lightness                     │
│                                                                                │
└────────────────────────────────────────────────────────────────────────────────┘

Branch Status Colors

/* Branch Status Colors */
.git-branch[data-status="active"] {
  /* Active branch (checked out) */
  --branch-glow: color-mix(in oklab, var(--branch-color), transparent 70%);
  box-shadow: 0 0 8px var(--branch-glow);
}

.git-branch[data-status="stale"] {
  /* Stale branch (no recent commits) */
  --branch-color-muted: color-mix(in oklab, var(--branch-color), gray 50%);
  color: var(--branch-color-muted);
}

.git-branch[data-status="merged"] {
  /* Already merged branch */
  --branch-color-faded: color-mix(in oklab, var(--branch-color), transparent 60%);
  color: var(--branch-color-faded);
  text-decoration: line-through;
}

THE CENTER

Merge Lines as Relationship Indicators

In a Git graph, merge lines are the visual representation of code integration. The color of a merge line should communicate “this brings together branch A and branch B.” OKLAB interpolation achieves this by producing a clean, predictable intermediate color.
Connection to Core-Flow:
├── Branch colors are Core (identity via OKLCH)
├── Merge colors are Flow (relationship via OKLAB mixing)
├── Golden Angle ensures maximum branch distinction
└── Clean merge colors = clear visualization of history
When two branches merge, their colors should blend - not clash. OKLAB interpolation ensures that the merge line visually represents both parents without becoming muddy or confusing.

Dynamic Generation

Runtime gradient generation with OKLCH/OKLAB