スプーキーズのちょっとTech。

SPOOKIES社内のより技工的な、専門的なブログページです。

Gitのコミットメッセージを複数行にする

zeosuttです。

この前 git commit のドキュメントを読んでいて知ったんですが、
-m 自体の機能でメッセージを複数行(というより複数段落)にすることが可能なんですね。

Git - git-commit Documentation

-m <msg>
--message=<msg>
Use the given <msg> as the commit message. If multiple -m options are given, their values are concatenated as separate paragraphs.

試してみると、

$ git commit -q -m hoge -m piyo -m fuga
$ git show -s --format=format:%B
hoge

piyo

fuga
$

おー、ちゃんとできています。

ソースコードはこれですね。

git/commit.c at master · git/git · GitHub

151: static int opt_parse_m(const struct option *opt, const char *arg, int unset)
152: {
153:   struct strbuf *buf = opt->value;
...
159:       if (buf->len)
160:           strbuf_addch(buf, '\n');
161:       strbuf_addstr(buf, arg);
162:       strbuf_complete_line(buf);

162行目でメッセージ末尾に(なければ)改行を追加し、
159、160行目で2つ目以降のメッセージ先頭に改行を追加。
これで間に空行が入る実装となっています。

その他の方法

-m 自体の機能でできたんだ!」という感動が執筆のきっかけなので、
これで私にとってのメインの内容は終わりなんですが、
一応他の方法も紹介しておきます(タイトルも -m に限定していないですしね)。

エディタ

最も一般的なのは、 -m 等を指定せず、エディタを起動する方法でしょう。
わざわざ言及するまでもないかもしれません。

なお、デフォルトでは先頭が # の行はコメント行として削除されますが、
先頭の文字は configで core.commentChar を設定すれば変更可能です。

Git - git-config Documentation

core.commentChar
Commands such as commit and tag that let you edit messages consider a line that begins with this character commented, and removes them after the editor returns (default #).

If set to "auto", git-commit would select a character that is not the beginning character of any line in existing commit messages.

-m + クォート

複数の -m を指定して-m 自体の機能を利用する代わりに、
単一の -m と、シェルの機能であるクォートを組み合わせる方法もあります。

$ git commit -q -m "hoge
>
> piyo"
$ git show -s --format=format:%B
hoge

piyo
$ git reset --soft @~
$ git commit -q -m 'hoge
>
> piyo'
$ git show -s --format=format:%B
hoge

piyo
$ git reset --soft @~
$ git commit -q -m $'hoge\n\npiyo'
$ git show -s --format=format:%B
hoge

piyo
$

-F

-F <file> でファイルの内容をそのままメッセージに利用できます。
また、他の多くのコマンドと同様、ファイル名に - を指定することで標準入力を表せます。

Git - git-commit Documentation

-F <file>
--file=<file>
Take the commit message from the given file. Use - to read the message from the standard input.

$ cat message
hoge

piyo
$ git commit -q -F message
$ git show -s --format=format:%B
hoge

piyo
$ git reset --soft @~
$ git commit -q -F -
(reading log message from standard input)
hoge

piyo
$ git show -s --format=format:%B
hoge

piyo
$

シェルの機能であるヒアドキュメントを組み合わせるのもアリですね。
あと、どうしても - を指定したくなければ、代わりに(あれば) /dev/stdin 等の標準入力を表すファイルを指定することもできます。

$ git commit -q -F - <<EOT
> hoge
>
> piyo
> EOT
$ git show -s --format=format:%B
hoge

piyo
$ git reset --soft @~
$ git commit -q -F /dev/stdin
hoge

piyo
$ git show -s --format=format:%B
hoge

piyo
$

余談

最初に引用した -m に関する記述に concatenate が出てきていますね。
concatenate といえば cat ですが、かわいそうなことに、ほとんど単一ファイルの内容確認にしか使われていない気がします( -F の例でもしれっとその用途で使っています)。
略し過ぎで、元の語が分かり辛いのかもしれないですねー。
cat + revtac とか、もはや concatenate を思い浮かべるなんて不可能な域です...

ちなみに、 tiggit + rev ではなく text-mode interface for Git の略なので、
git の出力が逆順になったりはしません。
04/01限定バージョンとして公開されたりしませんかねw