まくまくGitノート
別ブランチへの複数のコミットを1つのコミットとしてマージする (squash merge)
2011-05-12

複数のコミットを1コミットにしてマージ

例えば、mytopic ブランチに複数のコミットが入っているとして、この複数のコミットを1つのコミットとして master ブランチにマージするには以下のようにして squash merge(スカッシュマージ、圧縮マージ) を行います。

$ git checkout master
$ git merge --squash mytopic

上記のようにすると、mytopic 上で行われたすべてのコミットの修正内容が、現在チェックアウトしているブランチ上でステージングされた状態になります。 あとは git commit を実行すれば、それらの内容を1つのコミットとして取り込むことができます。 コミット時には、自動的にどのコミットを squash merge したのかを示すコメントが生成されます。

Squashed commit of the following:
...コミット1
...コミット2
...コミット3

squash merge したということは、おそらく1つのコミットとして扱いたかった理由があるのでしょうから、このコメントは適切ではないはずです。 適切にコメントを修正してコミットすれば squash merge の完了です。

squash merge の注意点

squash merge を実行した場合、Git 内部ではブランチ間のマージは行われていない扱いとなります(全然別物の修正がコミットされたかのように扱われる)。 コミット履歴を辿って調査することが困難になるので、日常的な使用はあまりお勧めできません。

取り込み元のブランチ自体はマージされずに残ったままの状態になるので、混乱しないように気を付けてください。 例えば、

$ git merge --squash mytopic

として mytopic 上での修正内容を取り込んだ後で、

$ git merge mytopic

と実行すると、mytopic ブランチで行われた個々のコミットのマージが実行されてしまうことになります(同じ内容をマージしようとする)。 実際には squash merge した時点で変更内容は取り込み済みなので、コードの変更が発生しないマージ用のコミットが作成されるだけなのですが、git log の表示が分かりにくくなるという弊害があります。 後々の混乱を防ぐためにも、squash merge したら、マージ元になったブランチは削除してしまった方がよいでしょう。 逆に、ここで削除できないようなブランチであれば、squash merge による修正の取り込みは避けるべきです。

$ git branch -D mytopic

(注)内部的には mytopic ブランチの内容はマージされていない扱いとなりますので、ここでのブランチ削除には -d でなく -D オプションを指定して強制削除する必要があります。

2011-05-12