spice picks

エンジニアをしているspiceが色々書きます

PRを小さく保つための、commit管理3TIPS

Summary

  1. 何となくでも良いのでconventional commitの仕様にしたがってcommitを作る
  2. 変更はPR作る直前までcommitしない 3.レビュー以前の変更はfixupとforce pushで既存のcommitに入れる。追加のcommitは作成しない

解説

1. 「何となくでも良いのでconventional commitの仕様にしたがってcommitを作る」について

conventional commitとは、「人間と機械が読みやすく、意味のあるコミットメッセージにするための仕様」です。(公式から引用https://www.conventionalcommits.org/ja/v1.0.0/ )

この仕様(の特にコミットメッセージのタイトル部分)に従ってコミットを作るようにします。 タイトル部分の仕様はこんな感じです。

 <type>[optional scope]: <description>
 feat(api): メッセージ取得APIの実装
 fix(app): コメント数がおかしかったのを修正
 test(web): 爆発テストを作成
 docs: コンポーネントについてのコード規約を作成

typeにどんな値が推奨されているかは公式ドキュメントを参照してください。 https://www.conventionalcommits.org/ja/v1.0.0/

このconventional commitの仕様を意識すると、commitのメッセージが分かりやすくなるだけではなく、 commitに含まれる差分が整理され、commitの内容自体が疎結合になっていく気がします。

「タイトルが綺麗につけられる=commit内容の意図がはっきりしている」 なので、1つのcommitに複数の意図を持つ差分を含めることがなくなります。 また、そうして作成したcommitは単独で切り出してcherry-pickにより別ブランチに移すことも容易なので、意図せず差分が大きくなったときにPRを分割するのがとても簡単です。

conventional commit自体は、レビュワーや将来commitを見る人がcommitの内容を理解しやすくすることが1番の目的なようですが、 これを意識することでcommit自体を綺麗に整理するクセを自然と身につけられるのが素晴らしいと思っています。

2. 「変更はPR作る直前までcommitしない」について

これはTIPS1を実現するために有用です。 PRにしたい差分が大体揃ってから、ファイルや行ごとにcommitを作ると、タイトルのつけやすいcommitを作成しやすくなります。 ファイルや行ごとのcommitが手間になりそう、と思う方がいるかもしれませんが、VSCodeだとGUIでカンタンにできるので、余計な工数がかかる心配もないです(intelliJでも同じようにできた気がしますが、使ってないエディタなので覚えてない)。 もちろんgit add -pなどを使ってCUIでも行えます。

逆に、PRをレビューに出すまでは適当にcommitしておいて、レビューに出すまえにgit reset --soft hashhashで差分をすべてローカルに戻して綺麗なcommitに整理する、ということ方法でも同じことができます。 個人的にはめんどくさいので、最後までcommitしない方法が好みです。

3.「レビュー以前の変更はfixupとforce pushで既存のcommitに入れる。追加のcommitは作成しない」について

綺麗なcommitを作ってPRを作成してレビューに出す前、 「typo見つけた・・!」 「やっぱり変数名変えたい・・・!」 「テストケースが不十分なので追加しよう・・・!」 といった具合に、変更を追加したいことはよくあります。 そんな時は、追加のcommitを作成するのではなく、既存のcommitに変更を加えて内容を修正することで、 中途半端な内容のcommit作成を防ぐことができます。 余計なcommitを作らないことで、後から一部の変更だけ別PRにしようと思った場合に複数のcommitを頑張ってcherry-pickする必要もなくなります。

自分は git commit --fixup ${変更を加えたいcommit hash} git rebase -i --autosquash ${変更を加えたいcommitの1つ前のcommit hash} で行うことが多いです。 すでにGitHubなどにcommitをpushしている場合は、 git push --force-with-lease でremote-branchをローカルで書き換えます。