v1.2.0
  1. ds
  2. Operations
  3. Diff

Diff

Unified and split diffs for code and config.

internal/relay/deliver.go+8−2
@@ -41,9 +41,14 @@ func (r *Relay) deliver(ctx context.Context, ev Event) error {
4141 for attempt := 1; ; attempt++ {
4242 err := r.post(ctx, ev)
4343 if err == nil {
4444 return nil
4545 }
46 if attempt == r.maxAttempts {
46 if attempt >= r.maxAttempts {
4747 return fmt.Errorf("giving up after %d attempts: %w", attempt, err)
4848 }
49 time.Sleep(time.Second << attempt)
49 // Full jitter: spread retries so a recovering endpoint is not hit by every worker at once.
50 backoff := min(r.base<<attempt, r.maxBackoff)
51 select {
52 case <-time.After(rand.N(backoff)):
53 case <-ctx.Done():
54 return ctx.Err()
55 }
5056 }
Show code
<div class="diff">
  <div class="diff-file"><span class="path">internal/relay/deliver.go</span><span class="diff-n"><span class="add">+8</span><span class="del">−2</span></span><button class="btn xs ghost">View file</button></div>
  <div class="diff-scroll"><table>
    <tr class="hunk"><td colspan="3">@@ -41,9 +41,14 @@ func (r *Relay) deliver(ctx context.Context, ev Event) error {</td></tr>
    <tr><td class="ln">41</td><td class="ln">41</td><td class="cd">	for attempt := 1; ; attempt++ {</td></tr>
    <tr><td class="ln">42</td><td class="ln">42</td><td class="cd">		err := r.post(ctx, ev)</td></tr>
    <tr><td class="ln">43</td><td class="ln">43</td><td class="cd">		if err == nil {</td></tr>
    <tr><td class="ln">44</td><td class="ln">44</td><td class="cd">			return nil</td></tr>
    <tr><td class="ln">45</td><td class="ln">45</td><td class="cd">		}</td></tr>
    <tr class="del"><td class="ln">46</td><td class="ln"></td><td class="cd">		if attempt == r.maxAttempts {</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">46</td><td class="cd">		if attempt >= r.maxAttempts {</td></tr>
    <tr><td class="ln">47</td><td class="ln">47</td><td class="cd">			return fmt.Errorf("giving up after %d attempts: %w", attempt, err)</td></tr>
    <tr><td class="ln">48</td><td class="ln">48</td><td class="cd">		}</td></tr>
    <tr class="del"><td class="ln">49</td><td class="ln"></td><td class="cd">		time.Sleep(time.Second &lt;&lt; attempt)</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">49</td><td class="cd">		// Full jitter: spread retries so a recovering endpoint is not hit by every worker at once.</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">50</td><td class="cd">		backoff := min(r.base&lt;&lt;attempt, r.maxBackoff)</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">51</td><td class="cd">		select {</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">52</td><td class="cd">		case &lt;-time.After(rand.N(backoff)):</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">53</td><td class="cd">		case &lt;-ctx.Done():</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">54</td><td class="cd">			return ctx.Err()</td></tr>
    <tr class="add"><td class="ln"></td><td class="ln">55</td><td class="cd">		}</td></tr>
    <tr><td class="ln">50</td><td class="ln">56</td><td class="cd">	}</td></tr>
  </table></div>
</div>

A unified diff is a table: old line number, new line number, the line. Added lines get a green wash, removed ones a red wash, and the gutter of each takes a stronger tint so changes can be found by scanning the edge. The + and − come from CSS, so selecting and copying the code gives clean lines. Hunk headers sit on a faint blue band with the function they are in.

Split

deploy/checkout-api/values.yaml+4−2
12resources:12resources:
13 requests:13 requests:
14 cpu: 250m14 cpu: 500m
15 memory: 512Mi15 memory: 512Mi
16 limits:16 limits:
17 memory: 512Mi17 memory: 1Gi
18readinessProbe:
19 httpGet: { path: /healthz, port: 8080 }
18replicas: 620replicas: 6
Show code
<div class="diff split">
  <div class="diff-file"><span class="path">deploy/checkout-api/values.yaml</span><span class="diff-n"><span class="add">+4</span><span class="del">−2</span></span></div>
  <div class="diff-scroll"><table>
    <tr><td class="ln">12</td><td class="cd">resources:</td><td class="ln">12</td><td class="cd">resources:</td></tr>
    <tr><td class="ln">13</td><td class="cd">  requests:</td><td class="ln">13</td><td class="cd">  requests:</td></tr>
    <tr><td class="ln del">14</td><td class="cd del">    cpu: <del>250m</del></td><td class="ln add">14</td><td class="cd add">    cpu: <ins>500m</ins></td></tr>
    <tr><td class="ln">15</td><td class="cd">    memory: 512Mi</td><td class="ln">15</td><td class="cd">    memory: 512Mi</td></tr>
    <tr><td class="ln">16</td><td class="cd">  limits:</td><td class="ln">16</td><td class="cd">  limits:</td></tr>
    <tr><td class="ln del">17</td><td class="cd del">    memory: <del>512Mi</del></td><td class="ln add">17</td><td class="cd add">    memory: <ins>1Gi</ins></td></tr>
    <tr><td class="ln"></td><td class="cd none"></td><td class="ln add">18</td><td class="cd add">readinessProbe:</td></tr>
    <tr><td class="ln"></td><td class="cd none"></td><td class="ln add">19</td><td class="cd add">  httpGet: { path: /healthz, port: 8080 }</td></tr>
    <tr><td class="ln">18</td><td class="cd">replicas: 6</td><td class="ln">20</td><td class="cd">replicas: 6</td></tr>
  </table></div>
</div>

Old on the left, new on the right, for config and short files where the before matters as much as the after. A side with no line is hatched. Inside a changed line, <del> and <ins> mark the words that changed, which in YAML is usually the only thing worth reading.

ClassOnWhat it does
.diffdivThe frame. .split for side by side.
.diff-filedivFile header: .path, .diff-n counts, actions.
.diff-scrolldivSideways scroll for long lines; code never wraps.
tr.add / tr.deltrA whole added or removed line (unified).
td.ln / td.cdtdLine number and code. In split view, put .add, .del or .none on the cells.
tr.hunktrThe @@ header, one cell spanning the row.
tr.foldtrCollapsed unchanged lines: "38 lines hidden".
ins / deltd.cdThe changed words inside a line.
Do
  • Word-level marks for one-token changes; without them the reader diffs the two lines by eye.
  • Three lines of context around each change, and a fold for the rest.
  • The counts in the file header, so a 400-line change is obvious before it is opened.
Don't
  • Wrapping code lines. Scroll sideways instead.
  • Green and red text on top of green and red washes.
  • Hiding whitespace changes without saying so.

Accessibility

  • Colour is not the only signal: a changed line has a sign before its code and only one line number. Add a visually hidden "added" or "removed" in each changed row for screen readers.
  • Keep the table semantics; a diff read row by row is still a diff.