複数コミットを一つにまとめてマージする

目的

git merge --squashは、フィーチャーブランチ上にある複数のコミットを単一のコミットに集約し、マージ先のブランチ(例: main)に適用するためのコマンドである。

これにより、mainブランチのコミット履歴が、細かな作業履歴("WIP", "fix"など)で汚れるのを防ぎ、機能単位のクリーンな履歴を維持できる。

ワークフロー

feature-branchmainブランチにスカッシュマージする手順である。

Step 1: マージ先ブランチへ移動

git checkout main

Step 2: --squashオプション付きでマージ実行

この時点ではコミットは生成されず、feature-branchの全変更内容がステージングエリアに展開される。

git merge --squash feature-branch

Step 3: 状態確認

git statusで、変更がステージングされていることを確認する。

$ git status
On branch main
Changes to be committed:
  (use "git restore --staged ..." to unstage)
        new file:   new-feature.txt
        modified:   existing-file.txt

Step 4: コミット作成

ステージングされた変更を、一つのコミットとして記録する。コミットメッセージには、ブランチでの変更内容を要約して記述する。

git commit -m "feat: ユーザー認証機能を追加"

通常マージとの比較

下の図は、左側が通常のgit merge、右側がgit merge --squashを行った後のコミット履歴を表している。

通常マージとスカッシュマージの比較図 通常マージ (git merge) main C1 C2 feature F1 F2 M1 featureの履歴が残り、マージコミットが作られる スカッシュマージ (--squash) main C1 C2 feature (参考) F1 F2 S1 featureの変更が1つのコミットにまとまる

ユースケースと注意点

主なユースケース

  • クリーンな履歴の維持: メインブランチの履歴を機能単位で管理したい場合。
  • リバートの容易化: 機能追加に問題があった際、対象のスカッシュコミットをリバートするだけで対応が完了する。
  • プルリクエストのマージ: GitHub等のプルリクエストをマージする際のオプションとして利用されることが多い。

注意点

  • 詳細履歴の消失: フィーチャーブランチでの開発過程(個々のコミット)はマージ先のブランチには残らない。
  • コンテキストの喪失: なぜその変更に至ったかの詳細な文脈が失われるため、後からの調査が困難になる場合がある。
  • マージ済みブランチの再利用: スカッシュマージ後、元のフィーチャーブランチをさらに更新して再度マージしようとすると、コンフリクトの原因になりやすい。マージ後はブランチを削除するのが基本である。

結論

git merge --squashは、メインブランチの履歴汚染を防ぐための有効な戦略である。開発過程の記録よりも履歴の可読性を重視する場合に特に有用であり、プロジェクトの運用ルールに応じて、通常のmergerebaseとの使い分けが求められる。