💡

Gitを使って過去の変更を調査するいくつかのアプローチ

2025/01/07に公開

概要

  • どこかの地点でプログラムにバグが混入した! というケースを考えます
  • git の機能を使ってよくあるケースのバグ調査の方法を記載します

最近の変更でおかしくなったことがわかっている場合

showコマンドを使えば該当コミットの差分を表示できます。コミット差分から調査に取り掛かりましょう。

特定コミットの差分がおかしいとわかっている場合(xxxxxxxxはハッシュ番号)
git show xxxxxxxx

特定ファイルにバグがあるケースで履歴を辿って検索する

バグが混入したコミットを探すために差分を辿っていきましょう。

pオプションを使って変更差分を見ながらlogをたどる
git log -p
特定ファイルに限定することも可能
git log -p --follow  -- foo.txt

followオプションをつけるとネームによるファイル名変更を追跡し、改名前の履歴も併せて表示してくれます。

またblameコマンドを使うと現在ファイルの各行ごとにだれが最終変更かを可視化できます。チーム開発していて担当者にヒアリングする際に使ってみましょう。

ファイルの最終更新者を行ごとに表示する
git blame foo.txt

コミット間の全変更を出してみる

前回のバージョンからアップデートによってバグが出たが、特定箇所がないという場合にはdiffコマンドの出番です。diffはそのままでもテキストファイルに書き出して、慣れているテキストエディタで差分を見てみるのもおすすめです。

差分を出してみる
git diff <commitA> <commitB>
diffファイルに書き出す
git diff <commitA> <commitB> > diff.patch

備考
patch拡張子はdiff特有の拡張子でapplyコマンドに対応しています。

patchファイルは他の環境で適用することができる
git apply diff.patch

バグが混入した箇所を二分木探索する

昔のいつの時点かで混入されたバグでどこから発生したかわからない場合はgit bisectコマンドを使って効率よく混入時点を特定することができます。以下のようにgoodbadを指定しながらどのハッシュ時点でバグが混入したかを特定することができます。

# バイセクション開始
git bisect start

# バグがあるコミットを指定 (例:最新コミット)
git bisect bad HEAD

# バグがないことがわかっている過去のコミットを指定
git bisect good <コミットハッシュ>

# ここで Git が中間のコミットをチェックアウトする
# -> テストやビルドなどで、バグが再現するかを確認

# バグが出た場合
git bisect bad

# (再度中間のコミットをチェックアウトするので、またテストし、good/bad を繰り返す)

# バグが出なかった場合
git bisect good

# これを繰り返すと原因コミットが特定される

# 最後にバイセクションを終了して元のブランチへ戻る
git bisect reset

歴史あるプログラムで昔からのバグが判明したときにコマンドを使うことで、バグに起因する変更をピンポイントであぶり出すことができます。

また自動テスト環境がある場合、不具合を再現できる場合は以下のようにコマンドを指定するのが良いです。

自前のテストスクリプトを実施して自動でバグの箇所を特定する
git bisect run <テストスクリプト>

Discussion