Git と Visual Studio 2017 その 16 : 不具合の追跡
前回の記事ではローカルコミットの修正について説明しました。今回は問題が発生した場合に、いつ、だれがどのコードを書いたのかを調べる方法を見ていきます。
一人で開発していると、問題が発生した場合どのあたりで問題が発生したか見当がつきます。しかしチームが大きくなり、また問題の発見が遅くなると、どこで問題が発生したか特定が困難です。どうすれば問題を簡単に特定できるか?もちろんユニットテスト作っておけばいいのですが、それはまた別の機会に。
ファイルの編集者と日時を特定する : Git
今回は ”編集 2” が README.md に追加された日時と作業者を探してみます。
1. ‘type README.md’ と ‘git log --oneline --graph --all’ を実行して現在の状況を確認。
2. コミットコメントが正しく書かれているとこの時点推測可能。‘git diff 7a2aecf 65bf5d5 README.md’ を実行して変更点を確認。これで問題解決とすると記事が終わるので他の方法も検討。
3. ‘git blame README.md’ を実行。blame コマンドはファイルの変更者、日時および変更点を表示。 log コマンドとは異なり、古い順に表示。
4. ‘git blame -L 5, 5 README.md’ を実行。L オプションを付けることで対象の行を指定。この場合 5 行目から 5 行目を指定しているため実質現在の 5 行目がいつ変更されたかを検索。
5. blame コマンドはファイル名が変更された場合も追跡可能。‘git mv README.md Read_Me.md’ を実行してファイルを変更。
6. ‘echo "名前の変更" >> Read_Me.md’ および ‘git commit -am "README.md の名前変更"’ を実行してコミット作成。
7. ‘git blame Read_Me.md’ を実行すると、README.md のときの結果も併せて表示。
8. 削除された結果も追跡できるか検証。‘echo # VS_Git > Read_Me.md’ および ‘echo “編集 1” >> Read_Me.md’ を実行後 ‘git commit -am “Read_Me.md から行を削除”’ でコミット。
9. ‘git blame Read_Me.md’ を実行すると履歴が 2 行に減少。
10. つまりコードが削除された事で問題が出た場合は blame では特定不可能。代わりに ‘git log --oneline -S “編集 2” を実行。追加時だけでなく、削除時も表示可能。
11. ‘git log -p -S “編集 2”’ のように -p オプションを付けると詳細も表示。
ファイルの編集者と日時を特定する : VS
Visual Studio 2017 でも blame コマンドをサポートしています。
1. ソリューションエクスプローラーを開くと、Read_Me.md ではなく README.md のまま。これはソリューションファイルがファイル名変更を追跡していないため。ソリューションを右クリックして、Read_Me.md を追加し、README.md を削除。
2. Read_Me.md を右クリックして、”変更履歴 (注釈)” をクリック。
3. VS は ‘git blame Read_Me.md’ の情報を取得して GUI に表示。行を選択すると、対応するコミットが選択される。
4. 残念ながら log -S に該当する機能がないが、ファイルの比較は可能。”履歴の表示” より特定のコミット右クリックから ”以前と比較” を実行すると、直前のコミットと比較可能。
問題を含むコミットを特定 : Git
blame や log -S を使うと特定ファイルの追跡は容易に行えますが、そもそもどのファイルに問題があるかわからない場合、まずはコミットに問題があるかを特定する方が簡単です。最新のコミットで問題があることは明らかですが、効率よくどのコミットで問題があるかを特定するには、全体の半分のコミットを常に見ていけば影響範囲を半分にしていけます。Git はこの操作を自動でできる bisect コマンドを提供します。早速試してみましょう。
1. ‘git bisect start’ を実行して bisect モードを開始。現在のコミットはすでに問題があるため、‘git bisect bad’ を実行して現在のコミットに問題ありとマーク。
2. 次に問題がないコミットを見つけて ‘git bisect good’ を実行するが、今回はあたりがついていないため、一番はじめのコミットを問題なしとマーク。‘git log --online’ で初めのコミット ID を確認して、‘git bisect good 343a309’ を実行。Git はこの時点で good と bad の中間である c69d3e9 を自動的にチェックアウト。
3. コミット c69d3e9 の時点で問題がないか確認。今回は問題がなかったと想定して、’git bisect good’ を実行。Git は再度 good と bad の中間コミットを自動でチェックアウト。
4. 次は現在のコミットで問題が出たと仮定して、‘git bisect bad’ を実行。Git は最後の good とこのコミットの中間コミットを自動でチェックアウト。
5. 再度このコミットには問題がなかったと仮定して、‘git bisect good’ を実行。Git は再び中間コミットをチェックアウトするが、コメントにある通り (roughly 0 steps)、このコミットが最後に確認するコミット。
6. ここでも問題がなかったと仮定して、’git bisect good’ を実行。すると問題があるコミットの詳細が表示される。
7. 調査完了後、‘git bisect reset’ を実行して最新のコミットに戻る。
初めから問題があるコミットと問題がないコミットが分かっている場合は ‘git bisect HEAD 343a309’ のように問題のあるコミット、問題のないコミットの順番で bisect に渡すことも可能。
問題を含むコミットを特定 : VS
残念ながら Visual Studio 2017 では同様に機能を見つけられませんでしたが、ユニットテストをしっかり書いておけば問題は抑制されますし、Git コマンドは引き続き実行できます。
まとめ
今回紹介した機能はこれまでほぼ使ったことがありませんが、強力な機能であることは間違いありません。
さてこのシリーズは今回で終わりです。次は VSTS/GitHub と Visual Studio 2017 シリーズでも書こうと思っていますが、フィードバックがあれば是非コメント欄にお願いします。
中村 憲一郎