はじめに
レビュワーにとってコミット履歴は追いやすさはとても大事だと思う一方で、最初からきれいな履歴を保つのはけっこう難しいです。修正が漏れたり、あとから必要な箇所が分かったりして、コミット履歴が予想より膨らむことも多々あるのが実際の開発です。
あとから履歴を書き換える
そんなときはこのコマンド(git rebase -i
)です。
平たく言うと、コミット履歴の編集、統合、順番の変更などができるコマンドです。
使い方
例えば以下画像のような、「前のコミットで修正漏れてたのでしゃーなしワンモアコミットしちゃった」みたいなケースを考えます。
step1. rebaseを開始したいコミットハッシュを特定する
今回は、hash ddddd
を hash ccccc
に統合したいので、直前のコミットである hash bbbbb
のコミットハッシュを取得します。
$ git log
commit fffff (HEAD -> <branch名>, origin/<branch名>)
Author: _mi
Date: Sun Sep 22 18:38:29 2024 +0900
fix: 可読性の向上のため、テストクラスのリファクタリングをする
commit eeeee
Author: _mi
Date: Sun Sep 22 18:38:09 2024 +0900
fix: テストをpassするようにhogeメソッドを修正
commit ddddd
Author: _mi
Date: Sun Sep 22 18:37:49 2024 +0900
fix: テストメソッド名をtypoしてたので修正
commit ccccc
Author: _mi
Date: Sun Sep 22 18:37:25 2024 +0900
test: hogeメソッドの振る舞いを網羅するため、テストを1つ追加
commit bbbbb
Author: _mi
Date: Sun Sep 22 18:37:02 2024 +0900
add: テストがpassするよう、hogeメソッドを実装
commit aaaaa
Author: _mi
Date: Sun Sep 22 18:36:19 2024 +0900
test: hogeメソッド(未実装)の失敗するテストクラスを作成
:
Step2. rebase を開始する
rebase コマンドを使って、どのコミットから変更を開始するか指定します。
$ git rebase -i <base commit hash>
注意点
git rebase
の実行前にローカルの変更差分を消しておきましょう。
error: cannot rebase: You have unstaged changes.
error: Please commit or stash them.
Step3. コミット履歴を編集する
Git のデフォルトの設定では Vim がノーマルモードで開きます。(git rebase
で hash bbbbb
を指定したので、hash ccccc
から編集できる)
pick ccccccc test: hogeメソッドの振る舞いを網羅するため、テストを1つ追加
pick ddddddd fix: テストメソッド名をtypoしてたので修正
pick eeeeeee fix: テストをpassするようにhogeメソッドを修正
pick fffffff fix: 可読性の向上のため、テストクラスのリファクタリングをする
# Rebase bbbbbbb..fffffff onto bbbbbbb (4 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
:
今回やりたいのは、typoしたコミット(hash ddddd
)をその直前のコミット(hash ccccc
)に統合することです。なので、Vim をインサートモードに切り替え(i
キーなど押下)た後に、pick
の部分を以下のように修正します。
pick ccccccc test: hogeメソッドの振る舞いを網羅するため、テストを1つ追加
squash ddddddd fix: テストメソッド名をtypoしてたので修正
pick eeeeeee fix: テストをpassするようにhogeメソッドを修正
pick fffffff fix: 可読性の向上のため、テストクラスのリファクタリングをする
その後、ノーマルモード(Esc
キー押下)に切り替え、:wq
を押下し保存・終了します。
git rebase -i のコマンド
Vim を開いたときに出てくる Commands:
以下の記載のようにほかにもできる操作がいろいろあるので、興味あれば調べてみてください。
私は基本 squash
(s
) しか使いません!
Step4. コミットメッセージを編集する
:wq
押下後、コミット統合後のコミットメッセージを編集できるようになります。
# This is a combination of 2 commits.
# This is the 1st commit message:
test: hogeメソッドの振る舞いを網羅するため、テストを1つ追加
# This is the commit message #2:
fix: テストメソッド名をtypoしてたので修正
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
~
typo修正時のコミットメッセージは不要になるので、「fix: テストメソッド名をtypoしてたので修正」を dd
を押下し削除した後、:wq
を押下し保存・終了します。
# This is a combination of 2 commits.
# This is the 1st commit message:
test: hogeメソッドの振る舞いを網羅するため、テストを1つ追加
# This is the commit message #2:
(ddでここを消す)
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
~
Step5. force push する
リベースが完了するとローカルのブランチがリモートリポジトリのブランチと異なる歴史を持つため、変更をリモートに反映するためにforce pushする必要があります。
$ git push origin <branch name> --force
あるいは
$ git push origin <branch name> -f
結果
コミットが統合されました。(fix: テストメソッド名をtypoしてたので修正
のコミットが test: hogeメソッドの振る舞いを網羅するため、テストを1つ追加
のコミットに混ぜ込まれている)
注意点
rebase -i
はめちゃくちゃ便利なのですが、 force push
は要注意です。
- リポジトリのブランチ保護を設定する(
Block force pushes
) - 自身にしか影響のないブランチでのみ利用する
など、気を付けて使ってください。
参考