いまどきのWEB開発業務では、逆に採用していない所を探すのが難しいのではないかと思われる程普及してきた感?がある「Git」。
皆さんも多分、このページを閲覧している時点でGitやGitHubを使われていると思われます。
で、今回は「コミットの粒度」についてです。僕が所属しているエンジニアチームで、ある程度のコミット粒度の統一化がなされてきたように思いますので、ここで是非、テキトーにGitコミットをしている方をターゲットに、
「コミットは自由にできるんだけど、何か指針があった方が、まとまりやすいし、後から自分が見直しても、何の作業をしたかが明確にわかるよね」
というような形になれるよう、お伝えできればと思います。
※急ぎの方は、本題の「コミット粒度の指針と考え方」を閲覧ください。
目次
コミット粒度は人それぞれ
ファイルをバージョン管理していても、コミットをどの程度で実行して、プッシュし、開発をすすめていくかは、人それぞれ。(何を隠そう、自分も好き放題でした)
今のエンジニアチームと一緒に仕事をするようになってから、プルリク体制がデフォルト(むしろ今までがおかしい・・)で、そこで始めてレビュワー側を少しずつ意識するようになりました。
(というか、最初は好き放題にコミットし、プルリクを出していました。。大変見にくい中、レビューをしていただいた経緯があります。今思えば、ほんま感謝です。)
コミット粒度はWEB開発業務の中では優先度が低くなりがち
極論ですが、コミット粒度が荒かろうが、細かろうが、成果物は同じです(要件通りにWEBシステムが動くという意味で)。
受託開発や、自分がメンテナンスする必要がない場合の常駐開発など、コミットの粒度なんぞ(納期が最優先で)完全にどうでもよいことになりがちかも。(このあたりはビジネスモデル自体に問題があるかな・・)
自社WEBサービスを運営している企業というのは、長期的なメンテナンスも自社エンジニアが行っていかなければならないケースが多いと思います。
「過去に対する作業履歴(バージョン管理)もしっかり考えていかないといけないよね。後から見直しても、何をやったか明確になれば、何かトラブルがあったり、過去を参考にするタスクがあったりする場合、効率よく作業進めれるよね。」
というのが、正しい体制というか、エンジニアが気持ちよく働いていける一つの要素になるのではないかと思います。
なので、コミットの粒度一つにとっても、後回しせず、意識して業務を進めていくことによって、チーム全体のストレス軽減につながるのでは?と考えています。
プルリク体制がないと、疎かにしがち
そして、人という生き物は「必要性」がないと記憶に残りにくいらしいです。コミットの粒度に必要性を感じていなければ、多分、僕のようにコミットの粒度について考えもしないだろうし、もし、考えたとしても、指針(目的)がないので、「何がゴールなのかわからない」という流れから、途中で「プログラミング書いてる方がいーや」となってしまい、疎か、または気付けばスルーになっていると思います。
コミットの粒度が必要になるのは、「誰かがあなたのコードを読んでくれる時」だと思います。(それはあなた自身かもしれない。)
その必要性のある状況になれば、どういう粒度でコミットすれば、相手に読みやすく、何が変わったのか、何の作業をしたのかを明確に伝えることが可能になります。そうすれば、正しく指摘してもらえる可能性が高まるし、お互いの勉強にもなる。いいことずくしですね。
コミット粒度の指針と考え方
さて、ここからが本題です。
まず、指針がないと何も始まりません。現在のエンジニアチームが一つの指針として掲げているのは、
・feat: 新機能の追加
・fix: 不具合の修正
・docs: ドキュメントのみの変更
・style: コードの処理に影響しない変更(スペースとか、書式設定とか、セミコロンの欠落とかの修正)
・refactor: バグ修正や機能の追加を行わないコードの変更
・perf: パフォーマンス改善を行うためのコードの変更
・test: テストの項目抜けや、既存のテストの修正を行う
・chore: ドキュメントの生成や、ビルドプロセス、ライブラリとツールをなどの変更 新機能の追加
という形でコミットをカテゴリに分けています。
※本家を参考。(でも、ソース忘れたんだ。。ゴメンなさい!!@todo 見つかったらリンク貼ります)
ちなみにコミットメッセージの内容は、例)「 feat: 〇〇機能を追加 」
などと言った風に使用します。
大丈夫です。全てを一気に覚える必要はありません。以下に、よく使うカテゴリを少し詳細に見ていきましょう。
feat
新機能の追加の場合などに使用します。それはメソッドであったり、条件分岐を改良してみたり、ファイルを追加してみたりといったこともfeatに含めて構わないと思います。
fix
バグがあった場合や、手戻りで何かを修正する場合にはfixを使えばよいです。
docs
コメントアウトだけ追加したとか、phpdoc形式でコメントを書いたとか、そのような場合に、使用します。逆に言えば、機能追加(feat)とはコミットを分けてできるという意味でもあります。
phpdocリファレンス
https://zonuexe.github.io/phpDocumentor2-ja/references/phpdoc/index.html
style
主な使い方としては、機能は変わらないけども、スペースの空け方とかを追加した場合に「コードスタイル」という観点でのカテゴリになります。
refactor
styleと変わらないという風な捉え方ができるかもしれませんが、全く違います。リファクタリングなので、例えば、機能が変わらないまま、条件を少なくしたり、SQLを効率よく書いたり、実装そのものを効率化させた時の場合に使用します。
以上、大体、開発を進めていく上では、5つの粒度カテゴリを覚えておけば、円滑に進めることができます。(後の3つはコミット粒度作業に慣れてきたら、追加で覚えればよいだけ。)
どの時点でコミットするか
次は、
「どの時点でコミットをするか」という考え方です。
ここも人それぞれで、一概に正解はないのですが、指針としては「ざっと見で無視してもよい箇所」「しっかり見てもらいたい箇所」「メソッド単位」といった分け方ができると思います。
一番のアンチパターンは、ガリガリプログラムを実装したあとに、「ファイル全体」で一気にコミット。という感じでしょうか?(長さにもよりますけどね・・)このパターンで例えば10以上のメソッドが一気にプルリクに送られてきたら、レビュワーは死にます。見落としが発生する可能性が高くなるし、レビューをする気持ちも萎え、帰宅の用意をするでしょう。
より複雑なコードを書いている場合は、一つの処理のまとまりとして捉えます。
(例えば、SQL文を作ったら、SQLだけを一つのまとまりとして)「feat: 〇〇取得のSQLを追加」として、コミットする。また、条件を追加した時に、「feat: ●●するための条件を追加」としてコミットしておく。
こういった形でコミットしておけば、「何の作業をしたのか」がより明確になります。レビュワーも、「あ、SQLの部分だけ見ればいいんだな」「ここは条件が意図通りかな?」と見やすくなりますね。
もちろん、メソッド単位でも良いと思いますが、処理が多いメソッドではNGだと思います。一つのメソッドをスクロールしなければ終われない場合などは、よりスコープ(範囲)を小さくして、コミットするように意識してみましょう。(小さすぎても、うーんなんですけどね・・)
コミットを意識すると、作業を進めにくい思考が現れる
さて、ここで思考の邪魔になってくるのが、「コミット粒度を強く意識していると、作業自体が捗らなくなる」といった、現象が起きる可能性です。(僕はそうだったので)
ただ、これもある程度の慣れが必要だとはいいつつ、そこで終わってしまうと感覚的な言い回しだけになってしまうので、是非、身に付けてもらいたい一つの方法が「行単位でのコミット」です。幸い、というか、たまたまというか、過去に記事にしたものがありますので、そちらを参考にしてみてください。(VSCodeに限定される部分がありますが・・)
行単位でのコミットを円滑に行えるようになれば、とりあえず、作業を進めてみて、自分の都合の良いタイミングでひとまとまりとして、行単位で「こんな作業をした」「制御をいれた」「コメントを書いた」など、上記でいうカテゴリに分けてコミットをしておけば、かなりまとまってくるかと思います。
最後に(コミットは常にレビュワーを意識しながら)
一人で開発や、受託開発など、納期優先でとりあえず成果物なんじゃ!という場合には、かなり後回しにされがちなコミット粒度ですが、チーム開発を行う場合には、チーム全員が足並みをそろえておくことが大事だと思います。
「常にレビュワー側にたって、作業を行う」
を、強く意識していくのが、肝ですね。自分もまだまだその過程で苦しんでいますが、一緒にバランスの取れたコミットを意識しましょー!