最近思ったこと
Git を知らないと「コミットをまとめる」という操作は破壊的な操作のように聞こえる。
実際に起こっていることはそうでもない。
以前の commit が破壊的にまとめられるのではなく、新しい commit が作られる。
というか Git の設計として、コミット自体が不可逆的に破壊されにくいようになっている。
しかし、 Git をたくさん使っていれば、コミットをまとめる系の操作で手痛いミスを犯したことがきっとあるはず。
最近分かったのは、まとめ先にはちゃんと新しい名前をつければ、起こったことの before, after がわかるし、
万が一ミスしても大きな混乱は起きない。
もしパニックになっても、その新しい名前のブランチだけをまるごと削除してしまえばいい。
GitHub Flow での例
GitFlow では WIP の Pull Request と master 向けの Pull Request がある。
- WIP の紆余曲折と被レビューの履歴はすべて保存されていて欲しい
- 作業単位のコミットを保存する
- レビューを受けた状態のコミットを保存する
- master の履歴はクリーンであって欲しい
- master はリリースなのでどの時点の Commit もクリーンであって欲しい。
- git bisect で特定可能
なので、 master 向けの Pull Request を用意するときに WIP のブランチをそのまま merge するのではなく、
Pull Request 用にさらに新しくブランチを切りたい。
ということは、その新しいブランチは、 WIP のブランチのコミットを単にまとめたものになる。
なので git merge --squash
がそのまま使える。
操作の例
- some-wip-feature .. WIP 。 レビュー用 Pull Request で使うブランチ
- some-clean-feature .. master に merge されるブランチ。 some-wip-feature をまとめたもの
$ git init
$ git commit --allow-empty -m 'Initial commit'
$ git checkout -B some-wip-feature
$ touch a
$ git add a
$ git commit -m 'Add a'
$ touch b
$ git add b
$ git commit -m 'Add b'
$ git checkout master
$ git checkout -B some-clean-feature
$ git merge --squash some-wip-feature
$ git commit -m 'Add some feature'
名前を 1 つで頑張るよりも、とても挙動がわかりやすいと思う。
1 つ実行して動かしてツリー表示すれば、起きていることがきっと理解しやすい。
免責
この記事は勢い良く書いたので、ところどころ用語がおかしいかも。