🔨

git rebaseが難しすぎたので、自動化CLI作った

に公開

はじめに

git rebase、怖くないですか?

開発を進めていると、ブランチの歴史をきれいに保つために git rebase を使いたくなる場面がよくあります。フィーチャーブランチを maindevelop の最新状態に追従させたいときなどです。

しかし、git rebase は強力な反面、多くの開発者にとって悩みの種でもあります。

  • 大量のコンフリクト: rebaseを実行したら、大量のコンフリクトが発生してしまい、1つ1つ解決するのが大変...
  • どのコミットで問題が起きたかわからない: 複数のコミットを一度にrebaseすると、どのコミットが原因で問題が起きたのか追うのが難しい
  • マージコミットの存在: rebase中に意図しないマージコミットが含まれていて、歴史が余計に複雑になってしまった
  • そもそもコマンドが難しい: git rebase --interactive, git rebase --continue, git rebase --abort... 状況に応じたコマンドを正しく使い分けるのは、慣れていないと怖い

こうした git rebase の難しさや恐怖心から、結局 git merge を使ってしまい、ブランチの歴史が複雑になってしまう...という経験をした方も多いのではないでしょうか。

そんな悩みを解決するために、git rebase を安全かつ対話的に実行できるCLIツール agrb (auto git rebase) を開発しました。

agrb とは?

agrb は、現在のブランチを別のブランチ(例:main)の最新状態へ安全に載せ替える(rebaseする)ためのCLIツールです。

https://github.com/riya-amemiya/agrb

最大の特徴は、2つのrebase戦略をサポートしている点です。

  1. cherry-pickベースの安全なrebase(デフォルト): マージコミットを無視し、現在のブランチのコミットだけを1つずつ cherry-pick していく方法。コンフリクトが発生したコミットは自動でスキップされるため、安全にrebaseを完了できる
  2. 線形履歴を作る git rebase: 従来の git rebase を使って、きれいな線形の歴史を作る(コンフリクト発生時に自動で解決を試みるオプションもあります)

また、UIライブラリである Ink を採用しており、rebase先のブランチを対話的に選択できるため、ブランチ名を正確に覚えていなくても直感的に操作できます。

インストールと使い方

インストール

npm経由でグローバルにインストールできます。

npm install --global agrb

使い方

基本的な使い方は、rebaseしたいブランチで agrb コマンドを実行するだけです。

agrb

ターゲットブランチを指定しない場合、対話的なブランチ選択画面が表示されます。
矢印キーでrebase先のブランチを選んでEnterキーを押すだけで、安全なrebaseが実行されます。
フィルタリング機能もあるので、ブランチ名を正確に覚えていなくても直感的に操作できます。

もちろん、オプションでターゲットブランチを直接指定可能です。

# mainブランチにrebaseする
agrb --target main

きれいな線形履歴を作りたい場合は、--linear オプションを使います。

# developブランチに対して、線形のgit rebaseを実行
agrb --target develop --linear

# コンフリクトが発生しても、"ours"戦略で自動解決を試みる
agrb --target main --linear --continue-on-conflict

agrb の内部的な仕組み

agrb がどのようにして安全なrebaseを実現しているのか、その心臓部を少しだけご紹介します。

1. 安全なcherry-pickモード(デフォルト)

このモードは、git rebase の複雑さをユーザーから隠蔽し、安全性を最優先に設計されています。

  1. 下準備: まず、ターゲットブランチ(例:main)から temp-rebase-xxx のような一時的なブランチを作成
  2. 差分コミットの特定: git merge-base <ターゲットブランチ> <現在のブランチ> コマンドで2つのブランチの共通の祖先を特定し、その祖先から現在のブランチのHEADまでのコミットリストを取得
  3. コミットの再生: 取得したコミットリストを1つずつ、一時ブランチに対して git cherry-pick
    • このとき、マージコミットは自動的にスキップ。これにより、rebaseの歴史が不必要に複雑になるのを防ぐ
    • cherry-pick 中にコンフリクトが発生したり、コミットが空(empty)になったりした場合、そのコミットは自動的にスキップ
  4. 仕上げ: すべてのコミットの cherry-pick が完了したら、現在のブランチのHEADを一時ブランチのHEADに git reset --hard で移動
  5. 最後に、一時ブランチを削除して完了

この仕組みにより、git rebase のように歴史を書き換える際の危険性を最小限に抑えつつ、ブランチを最新の状態に保つことができます。

2. 線形rebaseモード (--linear)

こちらは、より伝統的な git rebase を使いたいユーザー向けのモードです。内部的には git rebase origin/<ターゲットブランチ> を実行します。

--continue-on-conflict オプションが指定されている場合、コンフリクトが起きても処理を止めず、-X ours 戦略(自分たちの変更を優先する)で自動的にコンフリクトを解決し、git rebase --continue を試みます。

まとめ

git rebase はもう怖くありません。agrb を使えば、日々のブランチ運用がより安全で、より快適になるはずです。

  • コンフリクト解決に疲れた...
  • もっと気軽にブランチを最新にしたい...
  • git の複雑なコマンドを覚えたくない...

そんな方は、ぜひ一度 agrb を試してみてください。

リポジトリはこちらです。IssueやPull Requestも歓迎しています!
コントリビューション方法はCONTRIBUTING.mdをご覧ください。

https://github.com/riya-amemiya/agrb

GitHubで編集を提案

Discussion

Hidden comment