Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新

Dec 5, 2025 - 日記

git-absorb: 変更を自動的に適切なコミットに吸収する

git-absorb-introduction cover image

プルリクエストでレビューを受けた後、「このtypoを修正してください」「この部分のロジックを改善してください」といった指摘に対応する際、どのコミットに修正を含めるべきか判断に迷うことはありませんか?

従来はgit commit --fixupgit rebase --autosquashを使う方法がありますが、どのコミットに対するfixupなのかを手動で指定する必要があり、複数のコミットにまたがる修正を行う場合は特に手間がかかります。

git-absorbは、この面倒な作業を自動化してくれるツールです。変更内容を解析し、どのコミットを修正するものなのかを自動的に判定して、適切なコミットに変更を吸収(absorb)してくれます。

この記事では、git-absorbの基本的な使い方と、実際の開発フローでの活用方法について解説します。

git-absorbが解決する問題

具体的な例で考えてみましょう。以下のようなコミット履歴があるとします:

commit C: README.mdにドキュメントを追加
commit B: utils.pyにヘルパー関数を追加
commit A: api.pyにエンドポイントを追加

レビューで以下の指摘を受けました:

  • api.pyのtypoを修正してください(commit Aに関連)
  • utils.pyの関数名を変更してください(commit Bに関連)
  • README.mdの説明を追加してください(commit Cに関連)

従来の方法では、これらの修正を反映するために以下のような手順が必要でした:

  1. 各ファイルを修正
  2. 修正ごとにgit commit --fixup=<コミットハッシュ>を実行
  3. git rebase -i --autosquashで履歴を整理

この作業は、どの変更がどのコミットに対応するかを手動で管理する必要があり、特に修正箇所が多い場合は非常に手間がかかります。

git-absorbの仕組み

git-absorbは、この問題を以下のように解決します:

  1. 変更されたファイルの各行を解析
  2. その行が最後に変更されたコミットを特定
  3. 自動的にそのコミットに変更を吸収(absorb)

つまり、変更内容から自動的に適切なコミットを判定してくれるため、手動でコミットハッシュを指定する必要がありません。

git-absorb workflow diagram

主な特徴:

  • 自動マッチング: 変更内容を解析し、どのコミットを修正するものかを自動判定
  • 安全性: --dry-runモードで事前に結果を確認可能
  • 効率化: 複数のコミットにまたがる修正を一度に処理

インストール方法

macOSの場合

Homebrewを使ってインストールできます:

brew install git-absorb

Linuxの場合

Rustの開発環境がある場合は、cargoでインストールできます:

cargo install git-absorb

その他のインストール方法

GitHubリリースページから、各プラットフォーム向けのバイナリをダウンロードすることもできます: https://github.com/tummychow/git-absorb

基本的な使い方

ステップ1: 修正を行う

既存のコミット履歴に対して修正を行います:

# 例:レビュー指摘に基づいて修正
vim src/api.py       # typoを修正
vim src/utils.py     # 関数名を変更
vim README.md        # ドキュメントを追加

ステップ2: 変更をステージング

修正内容をステージングエリアに追加します:

git add -p  # 対話的に選択
# または
git add .   # すべての変更を追加

ステップ3: 動作確認(ドライラン)

まず--dry-runオプションで、どのコミットに変更が吸収されるか確認します:

git absorb --dry-run

以下のような出力が表示されます:

Absorbing changes into 3 commits:
  abc123d api.py: Fix typo in error message
  def456e utils.py: Rename helper function
  ghi789f README.md: Add usage documentation

これにより、各変更がどのコミットに反映されるかを事前に確認できます。

ステップ4: 実際に適用

問題なければ、実際にabsorbを実行します:

git absorb

デフォルトでは、現在のブランチのorigin/main(またはupstream)からの変更に対してabsorbが実行されます。

ステップ5: 結果を確認

git logで、変更が正しく吸収されたか確認します:

git log -p  # 各コミットの変更内容も表示

各コミットに修正が適切に反映されていることを確認してください。

実際の利用例

例1: プルリクエストのレビュー対応

以下のようなコミット履歴でプルリクエストを作成したとします:

* commit 3: Add user authentication
* commit 2: Add database models
* commit 1: Add API endpoints

レビューで複数の指摘を受けました:

  • commit 1のapi.pyでエラーハンドリングを追加
  • commit 2のmodels.pyでバリデーションを追加
  • commit 3のauth.pyでセキュリティを強化

従来の方法では、各修正に対してgit commit --fixupを3回実行する必要がありましたが、git-absorbなら一度で完了します:

# 1. すべての指摘箇所を修正
vim src/api.py
vim src/models.py
vim src/auth.py

# 2. 変更をステージング
git add src/

# 3. ドライランで確認
git absorb --dry-run

# 4. 問題なければ実行
git absorb --and-rebase

# 5. プルリクエストを更新
git push --force-with-lease

--and-rebaseオプションを使うと、absorb後に自動的にrebaseが実行され、コミット履歴が整理されます。

例2: typo修正を一括で反映

複数のファイルにまたがるtypoを発見した場合:

# 複数ファイルのtypoを修正
vim src/api.py      # commit Aで追加されたファイル
vim src/utils.py    # commit Bで追加されたファイル
vim README.md       # commit Cで変更されたファイル

# 一度にすべて処理
git add .
git absorb

# → 各ファイルの修正が、それぞれのコミットに自動的に吸収される

新しい「typo修正」コミットを作る必要がなく、元のコミットに直接修正が反映されます。

オプションと設定

よく使うオプション

  • --dry-run または -n: 実際には変更せず、結果のみ表示
  • --and-rebase または -r: absorb後に自動的にrebaseを実行
  • --base <ref>: 基準となるコミットを指定(デフォルトはupstream)
  • --force または -f: 確認なしで実行

使用例

# 特定のコミットを基準にabsorb
git absorb --base HEAD~5

# 強制実行(注意して使用)
git absorb --force --and-rebase

注意点と制約

absorbできないケース

以下のような場合は、git-absorbが自動判定できない可能性があります:

  • 新規行の追加: どのコミットに関連するか判断が難しい場合
  • 大幅なリファクタリング: コンテキストが大きく変わる変更
  • コンフリクト: 複数のコミットで同じ行を変更している場合

このような場合は、従来通りgit commit --fixupや手動でのrebaseを使用する必要があります。

安全な使用のために

  • ドライランを習慣化: まず--dry-runで結果を確認
  • バックアップ: 重要な作業前はgit branch backupなどでバックアップを作成
  • レビュー: absorb後は必ずgit log -pで変更内容を確認

従来の方法との比較

git commit –fixupを使う場合

# 各修正に対して個別にfixupコミットを作成
git add src/api.py
git commit --fixup=abc123d

git add src/utils.py
git commit --fixup=def456e

git add README.md
git commit --fixup=ghi789f

# 最後にrebaseで統合
git rebase -i --autosquash origin/main

git-absorbを使う場合

# すべての修正を一度にステージング
git add .

# 自動的に適切なコミットに振り分け
git absorb --and-rebase

明らかにgit-absorbの方がシンプルで、コミットハッシュを調べる手間も省けます。

まとめ

git-absorbは、コードレビュー後の修正や、複数コミットにまたがる変更を効率的に処理するための強力なツールです。特に以下のような場面で威力を発揮します:

  • プルリクエストのレビュー対応: 複数の指摘を一度に適切なコミットに反映
  • typo修正: 新しいコミットを作らず、元のコミットに直接修正を反映
  • リファクタリング: コミット履歴を綺麗に保ちながら細かい改善を追加

従来のgit commit --fixupgit rebase --autosquashの組み合わせに比べて、大幅に作業効率が向上します。プルリクエスト駆動の開発フローを採用しているプロジェクトでは特に有用です。

ぜひ試してみてください。

さらに詳しい情報は、公式GitHubリポジトリをご覧ください: https://github.com/tummychow/git-absorb