過去のコミットに漏れがあった...
着々と機能を実装していたら、過去のコミットに含めるべきだった箇所が見つかった。
とりあえずその箇所をコミットしたが、コミットが分かれてしまいログがきれいじゃない。
↓本当はにんじんの欠片を入れる処理を、cf911d5のコミットに含めたい。
8fccfcb (HEAD -> feature/cooking) にんじんの欠片が残っていたので入れた
051bd0b チョコレートを入れる
bb3eafc じゃがいもを入れる
cf911d5 にんじんを入れる
このように同じ箇所の実装のコミットが分かれていると、他の人がコミットごとにコードを見た時に「実装漏れか?」と思ってしまう。
できれば同じ箇所のコミットは一つにまとめておきたい。
git rebase -iで複数コミットを一つにまとめる
複数のコミットを一つにまとめたいときは、git rebase -i HEAD~{n}を使う。
まずはまとめたいコミットがどこにあるかを確認する。
$git log --oneline #コミットログを確認する
8fccfcb (HEAD -> feature/cooking) にんじんの欠片が残っていたので入れた
051bd0b チョコレートを入れる
bb3eafc じゃがいもを入れる
cf911d5 にんじんを入れる
すると、対象のコミットまで4つのコミットが確認できる。
コミットをまとめる作業に入る。
git rebase -iコマンドを叩くと↓のように出力される。
$git rebase -i HEAD~4
pick cf911d5 にんじんを入れる
pick bb3eafc じゃがいもを入れる
pick 051bd0b チョコレートを入れる
pick 8fccfcb にんじんの欠片が残っていたので入れた
# Rebase 8498aaf..8fccfcb onto 8498aaf (4 commands)
ここで、まとめたいコミット(8fccfcb にんじんの欠片が残っていたので入れた)を、まとめる元のコミット(cf911d5 にんじんを入れる)の下に移動させる
pick cf911d5 にんじんを入れる
pick 8fccfcb にんじんの欠片が残っていたので入れた //移動させた
pick bb3eafc じゃがいもを入れる
pick 051bd0b チョコレートを入れる
# Rebase 8498aaf..8fccfcb onto 8498aaf (4 commands)
まとめるコミットをpickからsquashにする
pick cf911d5 にんじんを入れる
squash 8fccfcb にんじんの欠片が残っていたので入れた
pick bb3eafc じゃがいもを入れる
pick 051bd0b チョコレートを入れる
# Rebase 8498aaf..8fccfcb onto 8498aaf (4 commands)
wq!で保存すると↓のようになる。 ここでコミットメッセージも変更できる。変更しない場合、全てのコミットメッセージが残ったままになる。squash
ではなくfixup
とすると、上のコミットメッセージが残る。
# This is a combination of 2 commits.
# This is the 1st commit message:
にんじんを入れる
# This is the commit message #2:
にんじんの欠片が残っていたので入れた
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
ここもwq!で保存すると、コミットをまとめるのが成功したと表示される。
Successfully rebased and updated refs/heads/feature/cooking.
試しにコミットログを見てみると、無事にんじんの欠片のコミットがまとめられていることが確認できる。
$git log --oneline
0cab8d3 (HEAD -> feature/cooking) チョコレートを入れる
b0e1c98 じゃがいもを入れる
aca094d にんじんを入れる
注意点
以上のように、コミットをまとめることでコミットログをきれいにすることができます。
ただし、git rebaseは過去を書き換えてしまいます。
上記の例でも、git rebase -i
の前後で、コミットのハッシュ値が変わっていることがわかると思います。
コミットログの変更はpush前だと問題ないのですが、すでにpushしてしまっている場合、
git push -f
で強制pushする必要が出てきます。
↓push後のコミットをまとめてpushしようとしたら怒られます。
! [rejected] feature/cooking -> feature/cooking (non-fast-forward)
他の人と共有しているリモートリポジトリの過去を変えるのは、それなりに代償が伴う可能性があるのであまりおすすめはしません。
git rebase -i
をするのはpush前のコミットにとどめとくのがいいのではないでしょうか。