Automate git commit message formatting regardless of editor

92 Views Asked by At

I use vim to write my commit messages, which means they get formatted "the right way" automatically. That is, as I write, my messages are formatted more or less as described in the classic article "A Note About Git Commit Messages" (hard wraps at 72 columns, indented list). You'll probably see this referenced as a "good" format for commit messages (together with writing stuff in the imperative mood).

However, I work with people who don't use vim, so I'd like to enforce that their commit messages are "correctly" formatted. In general, I don't want the format of commit messages to depend on what editor you choose to write your commit message in. I also sometimes might want to write commit messages from e.g. Visual Studio Code.

It seems like a smarter idea to just automatically format the commit message (like running prettier on code, but for commit messages).

I've tried to achieve this with a commit-msg hook (managed using lefthook), but I cannot figure out how to write the hook to format the commit message.

My question has 2 parts:

  • What's a good way to enforce a consistent format for commit messages, if not to reformat in a commit-msg hook? Note that I think formatting is preferable to just validating the format.
  • What's a simple, portable way to format a commit message according to this preferred format? Is there e.g. a simple sed script that could be used instead? FWIW, I've also tried prettier, treating the message as Markdown, but that... has other issues.

I've tried to run vim in batch mode, because I figured I'm basically trying to do gqG. This doesn't work as-is, though, because (1) gqG also formats the # lines that are typically part of a commit message and (2) I can't get it to work in Ex mode.

Basically, here's my non-working hook script:

INPUT_FILE=$1

vim --clean -es -c 'set filetype=gitcommit' -c 'g/^#/d' -c '%norm! gqG' -c "write" -c "quit" $INPUT_FILE

This gets rid of the comments (g/^#/d), but %norm! gqG isn't doing what I except. I've also tried g/^/norm gqq, but this creates different results.

Possible alternatives to vim:

  • fmt: With GNU fmt, fmt -t -w 72 gets pretty close, but it doesn't work for list items that aren't paragraphs (so if a list is - item 1\n- item 2 it gets formatted into a single paragraph). Of course, if you're on a Mac, you get BSD fmt by default which behaves differently.
  • fold: Too simple. Doesn't handle lists or trailers correctly.
  • par: I don't know how to configure this correctly.
  • prettier: Does not format git trailers correctly.

A combination of splitting commit messages by paragraph and formatting them individually might work (using sed or awk?).

0

There are 0 best solutions below