web-dev-qa-db-ja.com

Gitの履歴でコミット済みのコードをgrep(検索)するにはどうすればいいですか?

ファイルまたはファイル内のコードを過去に削除しました。コミットメッセージではなく内容を把握できますか?

非常に悪い解決策はログをgrepすることです:

git log -p | grep <pattern>

しかし、これはコミットハッシュをすぐには返しません。私はgit grepで遊んで役に立ちませんでした。

1251
Ortwin Gentz

Commit content (つまり、コミットメッセージなどとは対照的に、実際のソース行)を検索するには、次のようにします。

git grep <regexp> $(git rev-list --all)

アップデート : "引数リストが長すぎます"エラーが発生した場合はgit rev-list --all | xargs git grep <expression>が機能する

検索をサブツリー(たとえば "lib/util")に限定したい場合は、それをrev-listサブコマンドとgrepにも渡す必要があります。

git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util

これはregexpのための全てのコミットテキストを通り抜けます。

両方のコマンドでパスを渡す理由はrev-listlib/utilへのすべての変更が行われたリビジョンリストを返すが、lib/utilのみを検索するようにgrepに渡す必要があるためです。

次のシナリオを想像してみてください。grepは、<regexp>によって返される同じリビジョンに含まれる他のファイルで同じrev-listを見つけるかもしれません(そのリビジョンでそのファイルに変更がなかったとしても)。

あなたの情報源を検索する他の便利な方法は次のとおりです。

正規表現regexpと一致するテキストをワーキングツリーで検索します。

git grep <regexp>

正規表現regexp1またはregexp2に一致するテキスト行を作業ツリーで検索します。

git grep -e <regexp1> [--or] -e <regexp2>

正規表現regexp1とregexp2に一致するテキスト行をワーキングツリーで検索し、ファイルパスのみを報告します。

git grep -e <regexp1> --and -e <regexp2>

正規表現regexp1に一致するテキスト行と正規表現regexp2に一致するテキスト行があるファイルを作業ツリーで検索します。

git grep -l --all-match -e <regexp1> -e <regexp2>

作業ツリーを検索して、テキスト一致パターンの変更行を探します。

git diff --unified=0 | grep <pattern>

すべてのリビジョンで正規表現regexpに一致するテキストを検索します。

git grep <regexp> $(git rev-list --all)

正規表現regexpに一致するテキストについて、rev1とrev2の間のすべてのリビジョンを検索します。

git grep <regexp> $(git rev-list <rev1>..<rev2>)
1663
Jeet

-Spickaxe(git log オプションを使うべきです

Fooを検索するには:

git log -SFoo -- path_containing_change 
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change

詳しくは Gitの歴史 - キーワードで行を探す をご覧ください。


As JakubNarębski さんがコメントしました:

  • this<string>のインスタンスを導入または削除する違いを探します。
    それは通常「あなたが「Foo」で行を追加または削除したリビジョン」を意味します。

  • --pickaxe-regexオプションを使用すると、文字列を検索する代わりに拡張POSIX正規表現を使用できます。


Rob がコメントしたように、この検索で​​は大文字と小文字が区別されます - 彼は大文字と小文字を区別しないで検索する方法について フォローアップ質問 を開きました。

476
VonC

私のお気に入りのやり方はgit log-Gオプション(バージョン1.7.4で追加された)を使うことです。

-G<regex>
       Look for differences whose added or removed line matches the given <regex>.

-G-Sオプションがコミットが一致するかどうかを決定する方法には微妙な違いがあります。

  • -Sオプションは基本的に、コミット前後のファイル内で検索が一致した回数をカウントします。変更前と変更後のカウントが異なる場合は、コミットがログに表示されます。これは、たとえば、検索に一致する行が移動された場所にコミットを表示することはできません。
  • -Gオプションを使用すると、検索が追加、削除、または変更されたいずれかの行に一致すると、コミットがログに表示されます。

例としてこのコミットを取ります。

diff --git a/test b/test
index dddc242..60a8ba6 100644
--- a/test
+++ b/test
@@ -1 +1 @@
-hello hello
+hello goodbye hello

ファイル内の "hello"の出現回数は、このコミットの前後で同じであるため、-Shelloを使用しても一致しません。ただし、helloに一致する行が変更されたため、コミットは-Ghelloを使用して表示されます。

222
Tyler Holien

コードの変更を閲覧したい場合(歴史全体の中で、与えられたWordで実際に何が変更されたかを見てください) - patchモードに行ってください - 私はすることの非常に有用な組み合わせを見つけました:

git log -p
# hit '/' for search mode
# type in the Word you are searching
# if the first search is not relevant hit 'n' for next (like in vim ;) )
43
Bartek Skwira

私は @ Jeetの答え を受け取り、それをWindowsに採用しました( この答え のおかげで):

FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt

私にとっては、何らかの理由で、この正規表現を削除した実際のコミットがコマンドの出力に表示されず、その前に1回コミットされたことに注意してください。

24
ripper234

git logは、すべてのブランチにまたがってテキストを検索するためのより効果的な方法です。特に多くの一致があり、より最近の(関連する)変更を最初に見たい場合は特にそうです。

git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'

これらのlogコマンドは与えられた検索文字列/ regexを追加または削除するコミットをリストします。 -pオプションを使用すると、パターンが追加または削除された場所に関連する差分が表示されるため、状況に応じて確認できます。

探しているテキストを追加する適切なコミット(例えば8beeff00d)を見つけたら、そのコミットを含むブランチを見つけます。

git branch -a --contains 8beeff00d
19
Edward Anderson

任意のリビジョン、すべてのファイル :を検索

git rev-list --all | xargs git grep <regexp>

example xmlファイルについては、特定のファイルでのみ検索します。

git rev-list --all | xargs -I{} git grep <regexp> {} -- "*.xml"

結果行は、次のようになります。6988bec26b1503d45eb0b2e8a4364afb87dde7af:bla.xml:見つかった行のテキスト...

Git showを使用して、作成者、日付、差分などの詳細情報を取得できます。

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af
17

SourceTreeでこれを行おうとしている他の人にとっては、UIに直接のコマンドはありません(バージョン1.6.21.0以降)。ただし、ターミナルウィンドウ(メインツールバーにあるボタン)を開いて、そこにコピー/ペーストすることで、受け入れられた回答で指定されているコマンドを使用できます。

注:SourceTreeのSearchビューでは、部分的にテキスト検索を実行できます。押す Ctrl + 3 検索ビューに移動します(または下部にある[検索]タブをクリックします)。一番右から、[検索の種類]を[File Changes]に設定してから、検索する文字列を入力します。この方法には、上記のコマンドと比較して以下の制限があります。

  1. SourceTreeは、変更されたファイルの1つに検索ワードを含むコミットのみを表示します。検索テキストを含む正確なファイルを見つけることは、やはり手動の作業です。
  2. RegExはサポートされていません。
6
dotNET

わかりやすくするために、GUIを使用することをお勧めします。 gitk - Gitリポジトリブラウザ

  1. コードを検索する: enter image description here
  2. ファイルを検索する: enter image description here
  3. それはまた正規表現をサポートしています: enter image description here

上下の矢印を使用して結果をナビゲートできます

5
watashiSHUN

@ Jeetの答えはPowerShellで機能します。

git grep -n <regex> $(git rev-list --all)

以下は、コミット中のpasswordを含むすべてのファイルを表示します。

# store intermediate result
$result = git grep -n "password" $(git rev-list --all)

# display unique file names
$result | select -unique { $_ -replace "(^.*?:)|(:.*)", "" }
2
Shaun Luttin

それで、あなたは、何かが最後に存在する場所を探すために、コードの古いバージョンを調べようとしていますか?

私がこれをしていたら、私はおそらく git bisect を使用するでしょう。 bisectを使用すると、既知の良好なバージョン、既知の不適切なバージョン、およびバージョンが適切かどうかを確認する単純なスクリプト(この場合、探しているコードが存在するかどうかを確認するgrep)を指定できます。 )これを実行すると、コードがいつ削除されたかがわかります。

2
Rob Di Marco
git rev-list --all | xargs -n 5 git grep EXPRESSION

@ Jeetの解決策を微調整したもので、検索時に検索結果が表示され、最後に表示されるだけではありません(大規模なリポジトリでは長時間かかることがあります)。

1
laktak

私の場合、私はショートコミットを検索する必要があり、リストされた解決策は残念ながらうまくいきませんでした。

私はそれをすることができた:( _ regex _ トークンを置き換えなさい)

for commit in $(git rev-list --all --abbrev-commit)
do
    if [[ $commit =~ __REGEX__ ]]; then 
        git --no-pager show -s --format='%h %an - %s' $commit
    fi
done
0
xyz

シナリオ:IDEを使用してコードを大幅に整理しました。問題:IDEはそれ以上にクリーンアップされているため、コードはコンパイルされません(リソースが不足しているなど)。

解決策:

git grep --cached "text_to_find"

それは "text_to_find"が変更されたファイルを見つけるでしょう。

これで、この変更を元に戻してコードをコンパイルできます。

0
Garytech

あなたの場所にいるときはいつでも。次のコマンドラインを使用します。

git log -S "<words/phrases i am trying to find>" --all --oneline  --graph 

説明:

  1. git log-ここにさらに書き込む必要があります。ログは時系列で表示されます。
  2. -S "<words/phrases i am trying to find>"-'<>'記号なしで検索しようとしている単語/フレーズがファイル(追加/変更/削除)に含まれるすべてのgitコミットを表示します。
  3. --all-すべてのブランチにわたって強制および検索します。
  4. --oneline-gitログを1行で圧縮します。
  5. --graph-時系列順にコミットのグラフを作成します。
0
psyco