こんにちは!ブロックチェーンチームでエンジニアをしているid:dorapon2000 です。最近買ってよかったものは「潮の華 あおさといわしふりかけ」です。
今回は Git の Squash マージについての知見を共有したいと思います。端的に言うと、 チーム開発で Non Fast-Forward マージをやめて Squash マージを採用し、再び Non Fast-Forward マージに戻した経緯の説明です。Squash マージを運用に導入するか考えたことがある方の参考になればと思います。
マージには 3 種類ありますね。みなさんはトピックブランチを main へマージする際にどのマージ方法を利用していますか?
GitHub 上のマージボタンではそれぞれ
に対応します。今回注目する Squash マージは、複数コミットを単一のコミットにまとめてしまうマージ方法です。これらを説明するわかりやすい記事は多くあるため、そちらに説明を譲ります。
それぞれのマージ方法にはメリット・デメリットがあります。私達が利用していた Non Fast-Forward マージと Squash マージであげると以下のとおりです。
私達のチームで利用していた Non Fast-Forward マージでも開発において不都合はありませんでした。しかし、マージコミットが大量に発生する点が気になっていました。実際に Non Fast-Forward マージで運用している現在の main ブランチの様子です。マージコミットだらけです。
メリットの中で最も重要な点は「緊急時に Revert しやすい」です。それは Squash マージにもあります。そして Non Fast-Forward マージのデメリットが目についたとき、Squash マージが魅力的に映りました。
それから私達のチームは Squash マージを採用しました。具体的には、main → feature は従来どおり Non Fast-Forward マージで、feature → main へのマージが Squash マージです。
Squash マージは 3 ヶ月間運用しました。しかし、運用の中で Non Fast-Forward マージのときには想像していなかったコンフリクトの問題が大量に現れました。
Squash マージのデメリットである「詳細なコミット履歴が失われる」がコンフリクトという形で問題になりました。この状況によるコンフリクトを Squash コンフリクトと命名して説明を続けます。
コンフリクトが辛かったため、チームで相談して対応を 4 つ考えました。
本記事のタイトルにもある通り、採用したのは ④ の Squash マージをやめることです。つまり、従来の Non Fast-Forward マージの運用に戻しました。
①〜③ を採用しなかった理由をそれぞれ説明します。
① は現実的でないと判断されました。もしロックファイル(pnpm-lock.yml など)でコンフリクトが起きてしまったときにあまりに悲惨です。
② は運用でカバーする方法です。しかし、本来であれば認識する必要のない自身の子ブランチに合わせて 2 種類のマージを使い分ける必要があります。また、運用していると Non Fast-Forward マージすべきところをうっかり Squash マージしてしまったというミスが起きてしまいそうです。議論の余地なく不採用でした。
③ も運用でカバーする方法です。Squash コンフリクトが起きる状況を作らないように、feature/A を feature/B より先にマージしなければいいのです。しかし、feature/A に依存する子ブランチが多いと、あるいは他の子ブランチがマージされるのを待っているうちに新しい子ブランチができるなど、いつまで経っても feature/A を main にマージできません。そして、十分にその状況がありえます。
④ はもともと運用していた方法であり懸念はありません。
当時のチームは新規プロダクトの開発初期段階にあり、 feature/B (孫ブランチ) のようなブランチがよく作成されていました。そのため Squash マージとの相性が良くなかったのだと考えられます。feature/B があまり発生しない状況や環境であれば Squash マージもよい選択肢になるかと思います。
記事を読んでいただきありがとうございます。最後にまとめます。
Squash コンフリクトの例中で以下のように説明した箇所があります。
A と B はコンフリクトの関係にある
適切な用語を思いつかなかったためこのような説明になっていますが、内容はシンプルです。Squash コンフリクトの例を引き継いで、コードで説明します。
コミット A
import bisect+ import collections
コミット B
import bisectimport collections+ import math
Squash マージコミット C は
import bisect+ import collections
のようになり、コミット A+B とコミット C が Squash コンフリクトを起こす、ということです。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。