わすれっぽいきみえ

みらいのじぶんにやさしくしてやる

git でcommit.template を設定していたときの罠

kimikimi714.com

昔こういう記事を書いて、今も commit.template を使っていたが思わぬ罠を踏んだので共有する。

起こったこと

git のコミットメッセージにテンプレートが適応されるよう以下のように設定していたとする。

$ git config --global core.editor
vim
$ git config --global commit.template
/path/to/emoji.md

このとき、 emoji.md の文字コードは以下のように設定しているとする。

$ file --mime /path/to/emoji.md
emoji.md: text/plain; charset=utf-8

この状態だと UTF-8 以外の文字コードを扱うリポジトリを編集した際、コミットメッセージが文字化けしてしまう。
例えば編集したいファイル(hoge.txtとでもしておく)が EUC-JP で git commit -v を実行すると以下のようになる。

コミットテンプレートが文字化けしている

これは git commit -m 'なんかメッセージ' などでコミットするなら、あまり影響はない(本当か?)。だが、私のようにうっかり変なものをコミットしないか差分を確認してからコミットしたい人間にとっては結構致命的だ。

原因

根本原因は .git/COMMIT_EDITMSG文字コードが判定不能になることだ。 .git/COMMIT_EDITMSG はコミットメッセージ編集時の一時ファイルで、 git の設定で core.editor を設定している場合は、このファイルを開いてコミットメッセージを書こうとする。このとき、 emoji.md は UTF-8hoge.txt (正確にはhoge.txtのパッチファイル)は EUC-JP で、この二つのファイルを組み合わせて .git/COMMIT_EDITMSG を作ろうとするので、文字コードが壊れて以下のようになる。

$ file --mime .git/COMMIT_EDITMSG
.git/COMMIT_EDITMSG: text/plain; charset=unknown-8bit

charset=unknown-8bitググるsjis だよー、とよく出てくるけど違う。 UTF-8EUC-JP を無理やりくっつけたファイルを vim で開いてコミットメッセージを書こうとするから本当にわけわからん文字コードになってる。 charset=unknown-8bitsjis なのではなくて、 file --mime コマンドでは sjis が判定できないから sjis のファイルを開いたときも charset=unknown-8bit になってしまう、というのが正しい。

対策

このような状況で以下のような対策を取った。

  1. ~/.gitconfigcommit.templateコメントアウトする。
  2. vim文字コードを自動判定。

1. ~/.gitconfigcommit.templateコメントアウトする

文字通りコメントアウトする。各人の設定がどうかわからんが、私は以下のようにした。

#[commit]
#       template = /path/to/emoji.md

要するに UTF-8 と他の文字コードが混ざらないようにする。コミットテンプレートが表示されなくなるが、コミットメッセージが文字化け起こすよりは全然いい。

2. vim文字コードを自動判定

手順1でほぼ対応は終わりなんだが、ついでにやっとくと便利。 .vimrc に以下のような設定を追加する。

set fileencodings=utf-8,sjis,euc-jp,iso-2022-jp,latin1

latin1とかいらなそーと思ってるけど、まぁ私はいろいろ扱ってるんですよ…。

これで .git/COMMIT_EDITMSG が文字化けすることはなくなる。

今回のでついでにやっとくと色々便利なこと

git にはページャー設定も入れられるらしく、最終的に以下のような差分を .gitconfig に追加した。

+[pager]
+       log = diff-highlight | nkf -w | more -F -X
+       show = diff-highlight | nkf -w | more -F -X
+       diff = diff-highlight | nkf -w | more -F -X

また .zshrc に moreless コマンドの設定も追加。

+export LESS='-i -M -R'
+export MORE='-i -M -R'

これで git で diff をみたり log をみたりするときに自動的に文字コード判定もしてキレイに表示されるようになった。

参考記事

orebibou.com

qiita.com

tech-broccoli.life

qiita.com

itcweb.cc.affrc.go.jp