背景
仕事でコードレビューをしているときに「あれ、あの処理があったはずだけど消えてるな?どこで消えてるんだろ?」と疑問に思い、その処理の行が削除されたコミットを特定する方法を調べたらgit log -S "文字列"で探すという情報を見つけましたがそれでは探せない例があるとわかったので備忘録です。
git log -Sでは探せない例
例えば、git log -S "function doSomething"というふうにdoSomethingという名前の関数をコミット履歴から探そうとしたときに、1つのコミット内でfunction doSomethingという文字列が同じ回数削除されていて同じ回数追加されていた場合に検知ができません。
git diffで説明をすると、git diffを実行して以下のような結果になるときには実際にfunction doSomethingが削除されているにもかかわらずgit log -S "function doSomething"では検知ができません。
$ git diff <hash>
...
- function doSomething(int a) {
...
+ function doSomethingElse(int b) {
理由
それが仕様だからです。
ドキュメントを見ると以下のように書いてあります。
To illustrate the difference between -S --pickaxe-regex and -G, consider a commit with the following diff in the same file:
+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);While git log -G"frotz(nitfol" will show this commit, git log -S"frotz(nitfol" --pickaxe-regex will not (because the number of occurrences of > that string did not change).
結論
行が削除されたコミットを特定するのにはgit log -Gを使うと漏れがないと思います。
ただ、git log -Gではファイル内で処理を移動するようなリファクタリングのコミットも検知されてしまいます。そのようなリファクタリングの差分を無視したいという場合にはgit log -Sが使えるかもしれません。