慣れてきたらコミットをまとめてPull Requestしよう(git merge –squash)

Git使い始めは、コミットの内容や粒度にまで気が回らない!ですよね。それに、「リポジトリは非公開で見るのは社内のメンバーのみ」といった環境や、厳密な「バージョン管理」が必要ないプロジェクトを扱う場合は、リモートにある統合ブランチ(masterdevelop)のコミットが多少荒れていても気にならない・問題にならない事が多いと思います。

特にGitは慣れるまでに時間がかかるので、最初からルールが厳しいと導入が難しくなることも。グランフェアズでも、コミットのルールは特に決めていませんでした。なので、リポジトリのコミットは荒れ放題です…!(苦)
全社的にGitを本稼働させてから1年半。日常的な操作はだいぶスムーズになったので、そろそろリモートで共有されるコミットの状態を気にしよう、というお話です。

コミットをまとめてPull Requestを送る

グランフェアズでは、開発最新状態を維持する統合ブランチdevelopへのマージは、必ずPull Requestを経由して行います。作業ブランチをリモートにpushし、Pull Requestが承認されればそのままdevelopにマージされる流れなので、次の図のように作業ブランチのコミットがそのまま統合ブランチに取り込まれます。

作業ブランチのコミットがそのまま統合ブランチに取り込まれる

そうすると、作業者のつぶやきのようなコミットもdevelopに反映されてしまうわけで…。もちろんこれらは統合ブランチには不要で、履歴が追いにくくなるため共同開発の場でやると嫌われます。

またPull Requestを受けるレビュワーにとっても、作業者の試行錯誤や統合ブランチを吸収した跡はレビューの邪魔なので、履歴として不要なコミットはレビュワーに対しても優しくないのです。

コミットに対し気を付けたい事
  • 統合ブランチのコミットはプロジェクトの履歴であり、個人の記録ではない。
  • Pull Requestのレビュワーにも、不要なコミットは邪魔になる。

とは言え、コミットの内容や粒度に一々気を遣っていたら効率が悪すぎます。ローカルの作業ブランチでは自由にコミットしたい。そこで、最後にコミットをキレイにする(まとめる)という発想になります。

Pull Requestまでの流れ
  1. ローカルの作業ブランチには自由にコミットする
  2. 作業ブランチのコミットを最後にキレイにする(まとめる)
  3. Pull Requestを送る

コミットをまとめる方法

複数のコミットを編集する・まとめる方法にはgit rebase -igit merge --squashが考えられます。

git rebase -i を使う

git rebase -iを使ってコミットを編集する方法は、次の記事「Gitのコミットメッセージを後から変更する方法をわかりやすく書いてみた」でひさっしーが紹介していますが、この編集コマンドにeditではなくsquashを使えば、複数のコミットを1つにまとめることができます。Pull Requestまでの流れを図示すると次のようなイメージ。

git rebase -iでコミットをまとめてからPull Requestする

作業ブランチのコミットを直接編集できて分かりやすいですが、コミットが多いほどまとめる作業が面倒なので、最終1つのコミットでいい場合は不向きです。

git merge –squash を使う

こちらは、作業ブランチ(例:work/xxx-867)とは別にPull Request用のブランチ(例:work/xxx)を切って、コミットをまとめたうえでPull Requestを送る、という流れになります。

git merge --squashでコミットをまとめてからPull Requestする

コマンドの流れは次のような感じ。

# 作業ブランチをチェックアウト
$ git fetch
$ git checkout -b work/xxx-867 origin/develop
# git add や commit などして作業完了
# Pull Request用ブランチをチェックアウト
$ git fetch
$ git checkout -b work/xxx origin/develop
# 作業ブランチをマージ
$ git merge --squash work/xxx-867
# Pull Requestに出すコミットを作成
$ git commit

最後のコミットで viエディタを開き、一行目に「統合ブランチに反映する代表コミット」を記述。その下には取りまとめられた作業ブランチのコミットが自動で表示されるので、そのまま残しておきます。

git merge --squashのコミット画面

こうしておけば、後から「取りまとめられた中にあるコミット」を対象とした操作をすることが可能です。

コードレビューなどPull Requestの単位が適切であれば、Pull Requestに出すブランチのコミットは1つで十分/適切なことがほとんどなので、Pull Requestの前にはgit merge --squashが便利ですね。

シチュエーションに応じて

「統合ブランチのコミットグラフはキレイでないといけない!」と思いすぎると、「Pull Requestに修正が発生した場合はどうすべきなのか…」と悩んでしまいますが、キレイさを追求することが目的ではないので、あまり神経質になる必要はないと思っています。

例えば出したPull Requestに対して修正が発生した場合は、Pull Request用のブランチをローカルで修正・コミットしてリモートにpushする=Pull Request用のブランチには修正のコミットが含まれる、という形で(グランフェアズでは)問題ありません。

このあたりは、扱うプロジェクトの内容や体制によってルールが異なるところです。厳密なバージョン管理が求められるほど、また共同で開発するメンバーが増えるほど、共有する統合ブランチのコミットの精度が問われます。

いつそのようなプロジェクト・体制の案件にアサインされるか分かりませんし(笑)、レビュワーのことやプロジェクトのことを考えて、日ごろから「リモートで共有されるコミットの状態」を気にしておく、ということが大事なんじゃないかなと思います。