🧼

Git の履歴を rebase でキレイに保つ

2024/10/09に公開

以下の記事で紹介したLinear historyというGitのルールで運用するにあたり必須の操作となるのがrebase です

https://zenn.dev/owayo/articles/2469f323fd0470

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を入力します。

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

$ git rebase -i 1000001

とすることで、MR1ブランチのコミットを整理できます。
エディタが開いたら、まとめたいコミットの行頭を squashfixup に変更します。

  • squash: コミットメッセージを変更して、直前のコミットにまとめます。
  • fixup: 直前のコミットにまとめます。コミットメッセージは変更できません。
    これで複数のコミットを1つにまとめられます。
    JetBrains IDEでは以下のような画面が立ち上がり、画面からsquashfixup を設定できます。

commit 1-2commit 1-3squashfixupcommit 1-1にまとめると以下のようになります。

履歴に残す必要のないコミットはこのようにしてまとめることでリポジトリの肥大化を抑止できます。

コミットを削除する

不要なコミットを削除したいときも 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するのが安全です。

https://zenn.dev/mary_pp/articles/eaac544eaf600a

JetBrains IDEでは以下のような画面で強制プッシュが可能です。

reflog

git rebase をミスしたときのリカバリー方法として、reflog が使えます。

$ git reflog

このコマンドで、HEAD の移動履歴が見られます。戻りたいポイントの hash を見つけたら、

$ git reset --hard <hash>

で、そのポイントまで戻れます。
rebase で失敗しても、この方法で元に戻せるので安心してrebaseできます。

このように、git rebase は履歴を自在に操れる強力なツールです。
使いこなせば、キレイな履歴を保ちながら効率的に開発できますよ。

Discussion