DEV Community

Henry Godnick
Henry Godnick

Posted on Edited on

How to write good commit messages and PR descriptions fast on a Mac

Most of us know what a good commit message looks like. We just don't write one at 6 PM when the tests finally pass. The fix isn't more willpower. It's setting up your Mac and Git so the good version is the easy one: a template that asks the right questions, an editor that opens instantly, your diff right in front of you while you write, and a pull request description that mostly fills itself in. Here's the setup I use, step by step. Everything below uses stock Git, the GitHub CLI, and tools that ship with macOS.

1. Stop using -m for anything that matters

git commit -m "fix stuff" is fast because it skips the editor, and that's the problem: a one-liner is the only thing it encourages. Keep -m for truly trivial commits (a typo, a version bump) and let Git open an editor for everything else. That's where the next few steps pay off.

2. Pick an editor that opens fast and blocks properly

Git opens whatever core.editor is set to and waits until that editor closes the file. If you've never set it, you're probably getting Vim, which is fine if you know Vim and miserable if you don't.

For VS Code (after running Shell Command: Install 'code' command in PATH from the Command Palette):

git config --global core.editor "code --wait"
Enter fullscreen mode Exit fullscreen mode

The --wait flag matters. Without it, code returns right away and Git sees an empty message and aborts the commit.

If you'd rather stay in the terminal, nano ships with macOS and needs no setup:

git config --global core.editor "nano"
Enter fullscreen mode Exit fullscreen mode

Write the message, press Control-O to save, Control-X to exit, and the commit goes through.

3. Add a commit template that asks the right questions

A template is a plain text file Git pre-fills into the editor every time you commit without -m. Lines starting with # are comments and get stripped automatically, so you can leave yourself prompts that never end up in history.

Create ~/.gitmessage:


# Subject: imperative, ~50 chars, no period
#   e.g. "Fix race in session refresh"
#
# Body (wrap at 72): WHY this change, not what the diff shows.
#   - What was wrong or missing?
#   - Why this approach over the obvious alternative?
#   - Anything a reviewer or future you should watch for?
#
# Trailers (optional):
#   Refs: #123
#   Co-authored-by: Name <email>
Enter fullscreen mode Exit fullscreen mode

Then point Git at it:

git config --global commit.template ~/.gitmessage
Enter fullscreen mode Exit fullscreen mode

The empty first line is deliberate: your cursor lands where the subject goes. The prompts do the real work. When you're tired, "why this approach over the obvious alternative?" is the question you'd skip, and it's usually the one a reviewer most wants answered.

If a repo has its own conventions (say, Conventional Commits like feat: and fix:), set a repo-level template that overrides the global one:

git config commit.template .gitmessage
Enter fullscreen mode Exit fullscreen mode

4. Write with the diff on screen

Half the effort of a commit message is remembering what you actually changed. Let Git show you:

git config --global commit.verbose true
Enter fullscreen mode Exit fullscreen mode

Now every commit editor includes the full staged diff below the message, under a "scissors" line. Everything from that line down is removed before the commit is saved, so it's there for reference only. You can scroll down, see exactly what's staged, and describe it accurately instead of from memory.

Two more commands worth running before you write:

git diff --staged --stat   # which files, how much
git log --oneline -10      # how this repo usually phrases subjects
Enter fullscreen mode Exit fullscreen mode

The second one is the fastest way to match a team's style without reading a contributing guide.

5. Commit in smaller pieces so each message is easy

A message is hard to write when the commit does four things. git add -p walks through your changes hunk by hunk and asks whether to stage each one (y, n, s to split a hunk, q to quit). Stage one logical change, commit it, and repeat. Each message then has a single subject that's obvious.

For follow-up fixes to an earlier commit on your branch, skip the message entirely:

git commit --fixup=<sha>
git rebase -i --autosquash main
Enter fullscreen mode Exit fullscreen mode

--fixup creates a commit titled fixup! <original subject>, and --autosquash folds it into the original during the rebase. Your branch ends up with clean commits and no "address review comments" noise.

And if you notice a bad message right after committing, git commit --amend reopens the last message in your editor (only do this before you've pushed, or be ready to force-push your own branch).

6. Add trailers without typing them

Recent versions of Git have a --trailer flag that appends a properly formatted trailer to the message:

git commit --trailer "Co-authored-by: Sam Lee <sam@example.com>"
Enter fullscreen mode Exit fullscreen mode

If you pair with the same people often, turn it into a Git alias in ~/.gitconfig:

[alias]
    cosam = commit --trailer "Co-authored-by: Sam Lee <sam@example.com>"
Enter fullscreen mode Exit fullscreen mode

Now git cosam opens your normal template with the trailer already added.

7. Give the repo a pull request template

GitHub pre-fills new pull requests with the contents of .github/pull_request_template.md if it exists on the default branch. A short one works better than a long one, because people actually fill it in:

## What
<!-- One or two sentences. -->

## Why
<!-- The problem, link to the issue. -->

## How to test
1.

## Notes for reviewers
<!-- Risky parts, follow-ups, anything you're unsure about. -->
Enter fullscreen mode Exit fullscreen mode

HTML comments are hidden when the description is rendered, so the prompts don't clutter the final PR.

8. Draft the PR from the terminal with gh

If you've written good commits, most of the PR description already exists. The GitHub CLI (brew install gh, then gh auth login) can reuse it:

gh pr create --fill
Enter fullscreen mode Exit fullscreen mode

--fill uses your commit info for the title and body. For a single-commit branch, that's often the whole PR. For bigger branches, build a body from your commit subjects and copy it to the clipboard with macOS's built-in pbcopy:

git log --reverse --format='- %s' main..HEAD | pbcopy
Enter fullscreen mode Exit fullscreen mode

Paste that into the "What" section as a starting changelog, then spend your effort on "Why" and "Notes for reviewers," which no tool can write for you.

Other flags worth knowing:

  • gh pr create --draft opens it as a draft so CI can run before reviewers get pinged.
  • gh pr create --body-file pr.md uses a file you wrote in your editor.
  • gh pr create --web opens the browser form with your branch selected, if you prefer to finish there.

9. Keep short review phrases one keystroke away

For the bits you type over and over in PR descriptions and review comments ("How to test," "nit:", "LGTM once CI passes"), macOS Text Replacements work in Safari and most native text fields. Add them under System Settings > Keyboard > Text Replacements, and they sync across your Apple devices. Browser-based editors and Electron apps don't always honor them, so test in the places you actually write.

A five-minute setup checklist

  1. Set core.editor to something with a proper --wait.
  2. Create ~/.gitmessage and set commit.template.
  3. Turn on commit.verbose.
  4. Get in the habit of git add -p and git commit --fixup.
  5. Add .github/pull_request_template.md to your repos.
  6. Install gh and try gh pr create --fill on your next branch.

None of this writes your messages for you. It removes the friction around writing, so the thirty seconds you spend explaining why goes into the message instead of fighting your tools.

One more tool, if you want it

Disclosure: I built DraftKey, a Mac app that adds private, on-device AI autocomplete and rewriting to every Mac app, which helps when you're drafting PR descriptions and review comments. Nothing you type leaves your Mac. It's $5 lifetime and needs macOS 14 or later on Apple Silicon: getdraftkey.com. The setup above works perfectly well without it.

Top comments (0)