Webフロントエンドの開発でSquash Mergeを採用している

目次

こんにちは、@Himenonです。Web フロントエンドの開発では Git の Squash Merge を利用してコミットしています。なぜ Squash Merge を利用しているのか紹介していきたいと思います。

Squash Merge とは

Sqash Merge は特定のブランチに含まれる複数のコミットを 1 つのコミットにまとめて、別のブランチにマージすることを意味します。

例えば、次のようにリポジトリの初期化用の Pull Request があるとします。初期化の段階だと、環境構築のためのコミットが大量に発生します。

これを Merge Commit(GitHub のデフォルト設定)でマージした場合、このブランチのコミットが全てマージ先のブランチ(以下 main ブランチ)に含まれます。これを Squash Merge の場合はマージを行う前に、1 つのコミットに集約してマージすることができます。

****

このようにすることで、main ブランチのコミット履歴が Pull Request の単位で作成されていくようになります。

Squash Merge をなぜ利用するのか?

4 つの理由があります。

  1. main ブランチの履歴がきれいになる
  2. revert 時の問題が発生しにくくなる
  3. コンフリクト解消の作業が楽になる
  4. commit メッセージをいちいち気にしなくて良い(Pull Request のタイトルは気にして欲しい)

それぞれ説明していきます。

理由 1: main ブランチの履歴がきれいになる

Pull Request(以下 PR)の変更は関連のある単位で行われるため、複数のファイルが変更されることがほとんどです。すなわち、あるファイルやディレクトリが変更された時、その理由を探すときにそのファイルだけの変更履歴を見るよりも、PR というまとまった単位でその変更の意図を読むことが多いです。

そのため、単体のコミットメッセージだけでなく、PR 番号を探すことも重要になります。これは GitHub のマージ設定(後述します)とも関連するのですが、Squash Merge 時に PR 番号をコミットメッセージに含めることができます(下図)。

これによりコミットメッセージから PR が逆引きできるので、変更の理由を探す時間が短くなります。

また、main ブランチにマージしたときに、コミットは常に一番新しい時刻になるため、コミットとコミットの間にベースブランチのコミットが挿入されることはありません。

理由 2: revert 時の問題が発生しにくくなる

発生しにくくなると書いていますが、実際に発生したことはありません。Squash Merge は Pull Request を新しい commit として再編するため、main ブランチの revert は常に 1 コミットだけが対象となります。

トレードオフとして PR の特定のコミットだけ revert したいというケースには利用に適していないため、Pull Request の単位を明確にしておく必要があります。

理由 3: コンフリクト解消の作業が楽になる

前提として、(自動生成されるファイルを除き)プロダクトのコードを複数人が同じファイルを編集することはほとんどありません。ただ、コンフリクトが発生するのは大抵の場合は親ブランチ(ほとんどのケースで main)です。とはいえコミットの単位やコミット時間が Squash Merge によってすでに整理されているため、コンフリクトするときに考えることが非常に少なくなります。

理由 4: commit メッセージをいちいち気にしなくて良い(Pull Request のタイトルは気にして欲しい)

開発の速度を優先するため 1 つ 1 つのコミットメッセージは気にしていません。とはいえ、Merge Commit でこのまま運用するとコミットメッセージが荒れてしまうので、Squash Merge によって 1 コミットにまとめ、コミットメッセージを考える負荷を下げるようにしています。新しいコミットメッセージは PR のタイトルから抽出されるため、最低限 PR のタイトルだけ考えれば良いような仕組みにできます。

GitHub での設定

設定例を紹介します。リポジトリの Setting ページで、Pull Requests の項目を探します。

Allow squash mergingのみにチェックを入れ、Suqash Merge 時のコミットメッセージを好みに合わせて選択しておきます。新しく作成されるコミットメッセージに集約前のコミットメッセージを含めることもできますが、意味を成さない場合は PR のタイトルだけコミットメッセージに含めると良いでしょう。

Default to request titleを選択すると以下のようなフォーマットでコミットメッセージが作成されます。

PRのタイトル (#PR番号)

他のマージ方法を選択しないことで、Squash Merge を強制することができ、マージ方法を間違えないようにできます。

さいごに:Squash Merge をで開発してみてどうだったか

main ブランチの git の履歴が見やすくなったのは間違いないです。また、計測はしていないものの、revert や conflict が発生した場合の作業が Merge Commit よりも短いと感じています。

コミットメッセージをたくさん考えるのは面倒だけれども、ちゃんと履歴は残したいな、という場合におすすめです。個人的には GitHub Apps で PR の内容から PR タイトルを作成する(AI とかの)Apps とかあれば導入していきたいな〜と思ってます。