Gitのコミットストラテジーを再考する

git

梅雨なんて一瞬で過ぎさったかのように明けてしまいまして、毎日暑い日が続きますね。どうもまた僕です、アキです。そしてまたGitの話題です。



以前「Gitにまつわるエトセトラ」ということでGitについていろいろ書きましたがその続きと捕捉のお話になります。



コミットフレンドリー



コミットメッセージには相変わらず悩みますね。前回も触れましたが個人的に以前からcommitizenを導入して使っています。



これはgit commitgit czなどのコマンドに置きかえて、なおかつ対話的にコミットメッセージを作るラッパーライブラリです。もともとAngularJSなどで制定されているGit Commit Guidelinesに沿ったもののようで、Vue.jsでも同様のものが見られます。



これを使いだして以前よりは楽にコミットメッセージが書けるようになったのと、副次効果としてはこのメッセージでコミットの区分分けをすると逆説的にコミットの粒度や範囲もルールにのっかるようになってきます。コミットメッセージと変更内容の整合性が良い感じになって感じはあります。



これは是非他の人にも使ってもらいたいし、仲間に「貴様のコミットメッセージはわけがわからん!」と面と向かって言えないToo Shy Shy boyなので、ツールで誤魔化す作戦にでることにしました。



といっても単純に対話的に作る部分の質問分と選択肢を日本語に翻訳しただけです。せっかくなのでNPMで公開もしてみました。



cz-conventional-changelog-ja - npm


commitzen.png

(実はNPMで公開するのは初なので不備があるかもしれません。自分でも見なおして修正していきたいです。)



使い方はcommitizen - npmを読んでいただきたいんですが、設定を"path": "cz-conventional-changelog-ja"にすれば大丈夫なはずです。



fixなのfeatなの、どっちなの?



実は今まで使ってきて機能追加なのか修正なのか、両方なのか、悩むことがたまにあったんですがこのパッケージをNPMに上げる過程でなんとなくわかってきました。



元であるcz-conventinal-changelogにはsemantic-releaseというライブラリによってリリースバージョンを自動で生成してるんです(便利!)が、仕組みとしてはセマンティックバージョニングに準拠していてfixがあったらpatchfeatがあたらminorのバージョンが上がるようになっています。



これも逆説的に考えると今行なった変更がminorバージョンを上げるような機能の変更(or追加)ならfeatだし、patchレベルであればfixだな、と考えることができるようになりました。万事OKなわけではないですが、悩んだときの一助になって良い感じです。



Pre-commitフックをちゃんとする



前回も言及しましたが、僕は基本的にほとんどのプロジェクトでhuskyでhookしてlint-stagedでコミット対象にLintを噛ませてます。



良く紹介される方法でも十分効果的ではあるんですが、対象がファイル単位になるためhunkに分けたい場合でもファイル単位で上がりなおってしまう、ということがありました。lint-stagedのリポジトリをつぶさに見ていたらhunk対応版の方法があがっていたので共有したいと思います。



package.jsonを以下のようにします。



{
...(中略)
"scripts": {
"cz": "git-cz",
"precommit": "lint-staged",
"stash-unstaged": "git stash save -k 'pre-linting-stash' >> /dev/null",
"lint-staged": "lint-staged || (npm run pop-stash >> /dev/null && exit 1",
"pop-stash": "git stash && git stash pop stash@{1} && git read-tree stash && git stash drop"
},
"pre-commit": [
"stash-unstaged",
"lint-staged",
"pop-stash"
],
"lint-staged": {
"*.{js}": [
"eslint --fix",
"eslint"
]
},
...
}


lint-stagedの前後にgit stashによる退避と戻すのを挟む方法ですね。
この方法を導入してからhunkを多用気味な僕としては心に平穏が訪ずれました。



ちなみに業務ではRubyを、プライベートではVue.jsを良く触りますが、lint-stagedを上手くやってやればTypeScriptでもRuby+Rubocopだろうとどんとこいです。
Rails 5.1以降からYarnが正式に使えるようになったので、嬉しい副次作用です。
また、もちろんESlintにはPrettierも同時にかかるように設定してます。



まとめ



lint-stagedまわりはプロジェクトにNode.js系の要素がないとちょっとツライところですが、最初にご紹介したCommitizenはグローバルインストールでもいけるのでどんな言語のプロジェクトにも対応できますね。



もうちょっと上手く拡張してプロジェクトごとにタイプの設定を載せてルール付けるのもアリかもしれませんね。日本人だけのプロジェクトであればタイプとスコープは英語にして、その後のメッセージは日本語でも良いかもしれません。重要なのはある程度決まった型にそろえる、ということですね。



コード中にしろコード外にしろ、フォーマットをある程度揃えるのは本質じゃないところの統一することでノイズをカットして本質を注視しやすくする。そしていろいろサクサクやっていくぞ! という意気込みです。



この記事へのコメント