Git の履歴を rebase でキレイに保つ
以下の記事で紹介したLinear historyというGitのルールで運用するにあたり必須の操作となるのがrebase です
rebase を覚えるとGitの履歴をキレイに保つことができるのでリポジトリの肥大化を抑止する意味でも覚えておいたほうがいいコマンドになります。
会社では JetBrains IDE を使っている人が多いため、gitコマンドと、JetBrains IDEでの操作をそれぞれまとめておきます。
git rebase でできること
git rebase は、コミット履歴を綺麗に整理できる超便利なコマンドです。ブランチの起点を変えたり、複数のコミットをまとめたり、コミットメッセージを修正したりと、履歴を自在に操れちゃいます。
履歴がスッキリするので、チーム開発でも重宝されるコマンドです。
rebase するならやっておいたほうが良い git の設定
$ git config --global rebase.autosquash true
$ git config --global pull.rebase true
$ git config --global rerere.enabled true
git config --global rebase.autosquash true
これはコミットを自動で整理してくれる設定です。
コミットメッセージに "fixup!" とか "squash!" と書いておくと、自動的にそのコミットを前のコミットにくっつけてくれる便利設定。
git config --global pull.rebase true
プルするときに自動でリベースする設定。
マージコミットを減らして履歴をきれいに保つのに役立ちます。
git config --global rerere.enabled true
マージやリベースなどの操作におけるコンフリクト解消の際、コンフリクトが発生したファイルの内容を記録し、将来同じコンフリクトが発生したときに自動的に解決を試みます。
rebase 中に同じようなコンフリクトが再度発生した場合でも、以前に解消した内容を基に自動で解決を試みてくれる便利設定です。
ブランチの分岐元を変える
git rebase の基本的な使い方です。
例えば、現在のブランチを最新の main ブランチに追従させたいときに使います。

現在のブランチがMR2というブランチの場合、このままmainにマージしてしまうと、Linear historyにはならないため、rebaseを使って分岐元を変更し、mainの最新のコミットを取り込む必要があります。
$ git rebase main
JetBrains IDEでは、メニューのGit->リベースで画面を表示し、rebase対象のブランチ名やhashを入力します。

MR2ブランチのコミットがmainブランチの最新のコミットの後ろに追加されます。

このあと必要に応じてmainブランチにマージすると以下のようにLinear historyになります。

コミットをまとめる
複数のコミットを1つにまとめたいときは、git rebase -i を使います。
$ git rebase -i HEAD~3 # 直近3つのコミットを整理
や
$ git rebase -i <commit_id> # commit_id より後ろのコミットを整理
のように使います。
JetBrains IDEでは、メニューのGit->リベースで画面を表示し、オプションを変更にて、--interactiveを選択して、rebase対象のブランチ名やhashを入力します。

または、JetBrains IDEの左下のGitアイコンから、Git履歴を表示し、リベースを行いたい起点のコミットを選択して右クリック->ここから対話的にリベースでリベースの画面が開きます。

以下のような状態で、現在のブランチがMR1の場合、

$ git rebase -i 1000001
とすることで、MR1ブランチのコミットを整理できます。
エディタが開いたら、まとめたいコミットの行頭を squash や fixup に変更します。
-
squash: コミットメッセージを変更して、直前のコミットにまとめます。 -
fixup: 直前のコミットにまとめます。コミットメッセージは変更できません。
これで複数のコミットを1つにまとめられます。
JetBrains IDEでは以下のような画面が立ち上がり、画面からsquashやfixupを設定できます。
commit 1-2、commit 1-3をsquashやfixupでcommit 1-1にまとめると以下のようになります。

履歴に残す必要のないコミットはこのようにしてまとめることでリポジトリの肥大化を抑止できます。
もっと簡単にコミットをまとめる
JetBrains IDEの場合、左下のGitアイコンから、Git履歴を表示し、まとめたいコミットを選択して右クリック->コミットのスカッシュで一発でスカッシュしてまとめられます。

コミットを削除する
不要なコミットを削除したいときも git rebase -i が使えます。
削除したいコミットの行頭を drop に変更するだけです。簡単ですね。
動作確認のために入れたデバッグコミットなどを削除するのに便利です。
コミットメッセージを書き換える
コミットメッセージを後から修正したいときも git rebase -i で対応できます。
修正したいコミットの行頭を edit に変更します。
その後、git commit --amend でメッセージを修正し、git rebase --continue で rebase を続行します。
rebase後のgit push
rebase で履歴を書き換えた場合、git pushではpushができません。
git push --forceにて強制pushをする必要があります。
git push --forceは危険な操作でもあるので、以下の記事を参考に--force-with-lease --force-if-includesでpushするのが安全です。
JetBrains IDEでは以下のような画面で強制プッシュが可能です。

reflog
git rebase をミスしたときのリカバリー方法として、reflog が使えます。
$ git reflog
このコマンドで、HEAD の移動履歴が見られます。戻りたいポイントの hash を見つけたら、
$ git reset --hard <hash>
で、そのポイントまで戻れます。
rebase で失敗しても、この方法で元に戻せるので安心してrebaseできます。
このように、git rebase は履歴を自在に操れる強力なツールです。
使いこなせば、キレイな履歴を保ちながら効率的に開発できますよ。
Discussion