こんにちは、@na4daです。
作業用に切ったブランチで作業している時に、「ここで細かくコミットすると粒度が小さすぎるので、ある程度纏めてコミットしたい」という状況が時々あると思います。今回は、そういった場合にmerge --squash
を用いて、複数のコミットをまとめてコミットする手順をまとめた忘備録的な内容です。
手順
リモートからcheckoutしてきた(もしくはローカルで作成した)ブランチ(例:foo
)から、さらにブランチを切り、チェックアウトします。ブランチ名はfoo-dev
とします。このfoo-dev
ブランチはリモートへpushはせず、ローカルだけで用います。
git checkout -b foo-dev
その後、foo-dev
ブランチでコミットします。後で一つにまとまるため、粒度が小さくなっても気にせずコミットしていきます。
ある程度切りの良いところまでコミットができたら、foo
ブランチに移動し、merge --squash
を行います。
git checkout foo
git merge --squash foo-dev
すると、ブランチを分けた時点からfoo-dev
ブランチの最新コミットまでの差分が一つにまとまり、foo
ブランチにマージされます。
その後、foo
ブランチのコミットを行います。
git commit
squashを行なっているため、git commit
でエディタを開くと、foo-dev
ブランチでコミットした情報が付加されていることが確認できます。そこで、コミットメッセージの追記とともに、あとで確認できるようfoo-dev
ブランチで行なったコミットログの今回分を残して編集を終えます。
その後、foo
ブランチのコミットをリモートへpushします。
git checkout foo
git push origin foo
foo
ブランチにsquashしたコミットを行なった後はfoo-dev
ブランチに戻り、foo
ブランチのコミットをmergeします。
これは、次回merge --squash
を行う際に、前回のcommitと同一の箇所を編集することで発生するconflictを防ぐために行います。ちなみに、この手順のタイミングとしては、リモートにpushする前と後、どちらでも構いません。
git checkout foo-dev
git merge foo
ここまでの一連の流れをシーケンス図で表すと以下のようになります。
この図のように、必ずfoo-bar
を介さずに直接foo
ブランチにコミットし、pushすることもあると思います。その際も、foo-dev
にそのコミットを反映させることでconflictを防ぐことができます。
また、一つにまとめたコミットをfoo
ブランチからgit log
で確認すると、以下のような構成になっています(内容は一例です)。
commit f333c7c62f0a949014346c43fa9dd387367e9056
Author: test user <test@example.jp>
Date: Fri Jun 7 17:13:43 2019 +0900
Fix config files
Squashed commit of the following:
commit 1638a43820192c9a1e73ba630559a37fd38f3832
Author: test user <test@example.jp>
Date: Fri Jun 7 17:12:37 2019 +0900
Fix foo-config.txt
commit 5abe5741b8ab5cf87283b3ff400002015a743855
Author: test user <test@example.jp>
Date: Fri Jun 7 16:34:48 2019 +0900
Fix bar-config.txt
...
commit f1ec251f4eee1c42bce0abaed60da3195ebb2df2
Merge: d53b4ec e1e4093
Author: test user <test@example.jp>
Date: Fri Jun 7 15:34:28 2019 +0900
Merge branch 'foo' into foo-dev
少し手順が多いですが、以上の方法で複数のコミットをまとめて一つのコミットとしてpushすることができます。
終わりに
例えば、masterブランチの変更を反映させるためにfoo
にgit merge master
を行なった場合は、foo-dev
にも同じような操作(git merge foo
)が必要になるため、多少作業量が増えてしまうなどの欠点はあります(confilictが発生する場合は特に)。
個人で作業しているのであればともかく、チームで作業ブランチを共有している場合は他の人が混乱しないように、そして、なるべく内容がまとまっている範囲内でこの方法を使うと良いかなと思います。
少しでも参考になれば幸いです。