TOC
gitシリーズ
本記事の内容
前回の記事ではgitの内部構造に焦点をあてて解説しました。 今回はgitをどのような思想のもと、実際にどのように使うかについてコミットの面から解説します。 これから紹介するのはあくまで私の経験に基づく考え方であり、どの場面でも通用するものではありませんが、ひとつの考え方として覚えておいて損はないと思います。 また前回同様、基本的なコマンドの使い方は既知とします。
コミットの捉え方
まずgitの基本中の基本となるコミットとはなにかを考えます。 コミットとは単なる作業の途中経過の履歴ではなく、動作するプログラムのスナップショットであるべきです。 言い換えれば、コミットしてよいのは、ビルドが通り、実行時エラーも起きずテストもすべてパスする場合のみだということです。
この理由は、プログラム開発を細かいステップに分割し、開発を効率化するためです。 数百行のプログラムでさえ、動作のすべてを脳内で把握するのは難しいことです。 なので、プログラム開発は「ある範囲で完成した」といえる状態を少しずつ拡張していく作業にして、 1ステップでの変更部分をなるべく小さく抑えることが重要となります。 変更が少なければ少ないほど、脳内のワーキングメモリーで記憶しやすくなり、考慮漏れなどのバグが少なくなります。
この「ある範囲で完成した」状態をそのままスナップショットとして保存したのが、コミットになります。 そうすると開発というのは、「ある範囲で完成している」コミットに対して(理想的には)少量の変更を加えて、 「もう少し広い範囲で完成している」コミットを生み出すという作業になります。
自分の例になりますがgitを使い始めた当初は、gitというツールをあまりよく理解していませんでした。 gitとは修正不能なほど破壊的な変更をしてしまったときでもプログラムを途中まで戻せるような履歴の保存ツールだと考えていました。 なので、機能やビルドの通る/通らないにかかわらずこまめなコミットをしたりしていました。 こまめなコミット自体は悪いことではないですが、これだとどのコミットでうまくいったのか、訳が分からなくなってしまいます。 これはそもそもgitはどのようにしてプログラム開発を効率化し、そのためのコミットとはどういうものなのかを理解せずに使っていたのが根本的な原因です。
とはいえ、作業を一時的にコミットとして保存したい場合もあるかと思います。
その場合、私はコミットメッセージの冒頭にWIP (work in progress, 作業中)をつけて区別するようにしています。
また、WIPコミットにさらにコミットするときはgit commit --amend
を用いてコミットを上書きするようにしています。
まだ変更が終わっていない場合は再びWIPコミットを、変更が完了して動作するようになった場合は変更内容をメッセージに記載し、
あとから見るとWIPコミットが残らないようにしています。
間違ってWIPコミットを消し忘れた場合は、git rebase -i
でコミット履歴書き換えてしまいます。
コミット履歴の書き換えはタブーとされることもありますが、フォークしたレポジトリならばありかと思っています。
この辺はチームの方針があれば、それに従ってください。
コミットの粒度
コミットは、局所的にエラーのない状態で行うのはよいとして、どのような粒度でコミットをすればいいのでしょうか。 これは基本的に、「一つのコミットで一つの機能」を目安にするのが良いかと思います。 例えばファイルへの保存機能と追加するのとバグの修正はコミットを分けるとか、リファクタリングは単一のコミットとして行う、という具合です。
個人で開発する場合はあまり厳密にならなくてもよいと思いますし、チームで開発する場合はなるべく厳密に適用したほうが良いかと思います。 特にOSSでの開発では、あるコミットには単一の機能に関する記述のみが含まれるべきであり、無関係な記述は改行一つに至るまで含まれるべきではない、 という思想のもとでレビューが行われることもあります。 もちろんこれはレビュアーの負担を下げるためのルールであり、いじわるをしているなどと受け取らずにレビューを受け取りましょう。
実際にわたしがインターンしていた時に、OSSのコミッターもしているエンジニアのもとでコードを書くことがあり、レビューではそのような指摘をされました。 わたしのコミットには、複数の機能に関する記述や無駄な改行、空白が含まれており、コミット間のdiffが無駄に増えてレビュアーの負担も増えると教わりました。 そのときの経験からgitを理解するうえでの大きな影響を受けました。
まとめ
- コミットはビルドが通り、実行時エラーなどが出なくなった状態で行いましょう。
- テストがあれば、テストが通ったのを確認してからコミットしましょう。
- 一つのコミットにはなるべく一つの機能に関する記述のみが含まれるようにしましょう。
- どのくらい厳密にこれを実行するかはチームのルールや雰囲気に従いましょう。
comments powered by Disqus