The Best Way to Put Em Dashes in a Git Commit Message

Posted:
Tags:

“They” say that em dashes are a sign of AI writing. Well, “they” can pry my em dashes from my cold, dead fingers.

If you’ve read literally any other post on this blog before, you’ve probably noticed that I use em dashes a lot. Maybe too much. It’s something I’m working on.

And it’s not just on my blog: I use them when writing emails, social media posts, even text messages.1 The one place where I haven’t been using them — until recently — is Git commit messages; and let me tell you, it’s felt like the rhetorical equivalent of having one hand tied behind my back.

The problem with the em dash in this context is that commit messages are often written and read in a terminal window, and consequently rendered with a monospaced font. When every character is bound to a single fixed-width cell, an em dash is nearly indistinguishable from a hyphen. Compare:

monospace — that is, fixed-width

vs.

monospace—that is, fixed-width

Depending on the specific font your browser chose2 to render the above <code> element, you may or may not be able to tell the difference between the two marks; but I’ll bet it’s much less apparent than with the proportional text above it. This lack of distinction really hampers readability — it forces me to pause, just for a fraction of a second, to make sense of it; it throws off the flow, like traversing a staircase where two or three of the steps, entirely at random, are a different height than the rest.

Lesser workarounds

So, what to do? One obvious solution is to put spaces on either side: a — b. This looks fine in the terminal, and is certainly much more readable. But while commits are often read in a terminal, they aren’t always: plenty of code editors, software forges, etc. render them with a proportional font, and surrounding a proper em dash with full spaces (a — b) just isn’t right.

You could use spaces with an en dash instead: a – b. This looks better on the proportional side (a – b), and indeed is standard usage in the U.K. I really prefer a real em dash, though; and to me, the monospaced en dash looks a bit anemic.

You could use either two hyphens with spaces, or three without: a -- b, a---b. These were established conventions for typewriters and for pure-ASCII contexts, and they look all right even when typeset proportionally (a -- b, a---b). They have the added benefit of being easier to type, given that neither the en nor the em dash has a dedicated key on most keyboards. If your viewing software interprets commit text as Markdown, then they might even be automatically converted to real en and em dashes, respectively.

But not every proportional-font commit viewer interprets them as Markdown, and not every implementation of Markdown performs those particular conversions. And, damn it, we’re not using typewriters or ASCII anymore; we’re using computers and Unicode and we should be able to have nice typography.

(If you couldn’t tell: for someone who isn’t a type designer, I care an awful lot about typography. Maybe too much. But that’s not something I’m working on, nor is it something I have any intention of working on, because the desktop publishing revolution started before I was born and I shouldn’t have to.)

Enter U+200A, the hair space

It turns out that traditional (i.e., pre-digital) typography used a whole range of spaces of various widths, from em and en spaces on the wider end to “thin” and “hair” spaces on the narrower end. It was common practice, though perhaps not universal, to place hair spaces on either side of a dash for a cleaner look: compare an em dash with hair spaces (a — b) vs. without (a—b). It’s a subtle difference; but having learned of it, I promptly inserted a pair of &hairsp;es around every &mdash; and &ndash; in my site’s markup. They’re also nice for clarifying nested quotations: “ ‘a’ ” vs. “‘a’”.

In a monospaced font, of course, a hair space is exactly the same width as a regular space. The following lines are exactly the same sequence of characters, set first with a proportional font and then with a monospaced one:

monospace — that is, fixed-width

vs.

monospace — that is, fixed-width

Ahhhhh. So much better.

Actually typing the dang thing

Of course, now we’ve gone from needing one character that’s not on the keyboard to needing three for every em dash we type. Linux has a… let’s call it convenient shortcut for entering arbitrary Unicode characters, provided you know the code point: press Ctrl+Shift+U, then type the four-digit code point, then press Space. Windows has something similar.

So, you could type an em dash and two hair spaces as follows: Ctrl+Shift+U, 2, 0, 0, A, Space, Ctrl+Shift+U, 2, 0, 1, 4, Space, Ctrl+Shift+U, 2, 0, 0, A, Space. But that would be, obviously, a massive pain.

(Well, okay, with enough practice it might not be that bad. But still, we can do better.)

Far more convenient — provided your editor supports it — is to configure a substitution.3 In my case, that editor is Vim; and the substitution looks like this:4

inoremap <Leader>md <Char-0x200a>—<Char-0x200a>

(Where, yes, I typed the dash itself with the whole Ctrl+Shift+U thing. You could put <Char-0x2014> instead if you wanted, but I think this version is more clear when re-reading my .vimrc.)

My <Leader> key is the default, \. So, while in insert mode, as I’m typing, I can hit \, m, d in quick succession to produce a nice space-dash-space sequence with ease.

The really nice thing about this approach is that it translates well to other contexts:

augroup html
    autocmd!

    autocmd FileType html inoremap <buffer> <Leader>md &hairsp;&mdash;&hairsp;

    " ... other HTML-specific substitutions ...

augroup END

I won’t go into detail about Vim autocommands in this post — I’m pretty new to them myself — but suffice it to say this makes it so that when I’m editing an HTML file (e.g., this very blog post), the exact same keystrokes, \, m, d, produce &hairsp;&mdash;&hairsp; instead of the literal characters. Same convenience; same muscle memory; equivalent, context-specific result.

Footnotes

  1. That is, SMS/RCS. I am given to understand that the use of terms like “text message” or “texting” for these services is mostly a U.S. regionalism. ↩︎

  2. I’m not overly concerned with the exact appearance of this website, so long as it looks close enough everywhere. So, rather than force you(r browser) to (silently) download web fonts — with the exception of Font Awesome for the icons on my About page, which dependency I mean to address one of these days — my current design lists a series of fallback fonts for each style, at least one of which is likely to be installed on each of the major platforms. ↩︎

  3. Or, if not, you could look into system-wide “text expander” software, such as AutoHotkey. ↩︎

  4. Aside from insert-mode mappings like this, Vim has another, separate as-you-type substitution feature called abbreviations. These are useful for things like automatically correcting common typos or expanding a handful of characters into a longer string. On the face of it, abbreviations seem like a more natural fit for this kind of typographical assistance; but Vim’s abbreviations are intentionally sensitive to word boundaries, including punctuation, in a way that makes them less suitable than I would have liked for inserting punctuation. ↩︎