Gitプロジェクトのすべてのブランチで「grep検索」を実行することは可能ですか?


回答:


188

Gitの履歴でコミットされたコードをgrep(検索)する方法は?

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

これにより、すべてのブランチを含むすべてのコミットが検索されます。

別の形式は次のとおりです。

git rev-list --all | (
    while read revision; do
        git grep -F 'yourWord' $revision
    done
)

あなたはこの記事でさらに多くの例を見つけることができます:

gitが引数のサイズについて不平を言うのに十分な大きさの1つのプロジェクトで上記を試したので、この問題が発生した場合は、次のようにします。

git rev-list --all | (while read rev; do git grep -e <regexp> $rev; done)

(下のこの回答の最後のセクションにある代替案を参照してください)

必要に応じて、これらの設定を忘れないでください。

# Allow Extended Regular Expressions
git config --global grep.extendRegexp true
# Always Include Line Numbers
git config --global grep.lineNumber true

このエイリアスも役立ちます:

git config --global alias.g "grep --break --heading --line-number"

注:chernjie 、これgit rev-list --allはやり過ぎだと提案しました。

より洗練されたコマンドは次のとおりです。

git branch -a | tr -d \* | xargs git grep <regexp>

ブランチ(リモートブランチを含む)のみを検索できるようにします

そのためのbash / zshエイリアスを作成することもできます。

alias grep_all="git branch -a | tr -d \* | xargs git grep"
grep_all <regexp>

2016年8月の更新:RMはコメントで推奨しています

バージョンをfatal: bad flag '->' used after filename試すときに「」が表示されましたgit branch。エラーは、HEADエイリアス表記に関連付けられていました。

私は追加することによって、それを解決したsed '/->/d'との間で、パイプにtrしてxargsコマンド。

 git branch -a | tr -d \* | sed '/->/d' | xargs git grep <regexp>

あれは:

alias grep_all="git branch -a | tr -d \* | sed '/->/d' | xargs git grep"
grep_all <regexp>

の出力git branchをtrまたはsed にパイプすることはお勧めできません。git branch人間が消費するための磁器コマンドです。推奨される代替策については、stackoverflow.com / a / 3847586/2562319を参照してください。
jbyler 2017年

@jbyler良い点。皮肉なことに、私はこの回答のずっと前に磁器に回答を投稿しました:stackoverflow.com/a/6978402/6309。そして、私はそれを例えばstackoverflow.com/a/19206916/6309で使用します。
VonC、2017年

うん、いいね。他の回答を調べて、@ errordeveloperの回答が最もきれいだと思います:stackoverflow.com/a/21284342/2562319: "git grep <regexp> $(git for-each-ref --format = '%(refname) 'refs /) "
jbyler

1
検索に一致したブランチの名前を表示する方法はありますか?
フランクサンズ2018年

63

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

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

これらのログコマンドは、特定の検索文字列/正規表現を(一般的に)より新しいものから最初に追加または削除するコミットをリストします。この-pオプションを使用すると、パターンが追加または削除された場所に関連するdiffが表示されるため、コンテキストで確認できます。

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

git branch -a --contains 8beeff00d

22

私はこれが最も便利だと思いました:

git grep -i foo `git for-each-ref --format='%(refname)' refs/`

リモートブランチとローカルブランチのみを確認するかどうかに応じて、最後の引数を調整する必要があります。

  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/remotes)
  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/heads)

作成したエイリアスは次のようになります。

grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'

1
興味深いエイリアス。+1。私の答えよりも正確です。
VonC、2014年

エイリアスをフレーズ検索で機能させるにはどうすればよいですか?「foo bar」をパラメーターとして渡すと、次のエラーメッセージが表示されます。fatal:あいまいな引数 'bar':作業ツリーにない不明なリビジョンまたはパス。'-'を使用してパスをリビジョンから分離します
危険な

スペースをエスケープしてみてください: "foo \ bar"
Garry Gomez

これは明らかに受け入れられる答えです;)私はプロジェクトの最新のブランチのみを検索するように拡張しました(500を超えるため、質問せず、各grepに約4秒かかるので、必要も必要もありません)たとえば、100以上の最新のものを検索します)。このために私はで更新しgit for-each-refました--sort=-committerdate --count=100!オリジナルのアイデアをありがとう!
Vser

6

2つの一般的な方法でそれを行うことが可能です:BashまたはGitエイリアス

以下に3つのコマンドを示します。

  1. git grep-branch -ローカルおよびリモートのすべてのブランチで検索
  2. git grep-branch-local -地元の支店のみを検索
  3. git grep-branch-remote -リモートブランチのみ

使い方は同じです git grep

git grep-branch "find my text"
git grep-branch --some-grep-options "find my text"

GREPの使用:Gitエイリアス

ファイル〜/ .gitconfig

追加した複雑なコードを評価してそれを台無しにする~/.gitconfigため、コマンドは手動でファイルに追加する必要がありますgit config --global alias


[alias]
    grep-branch        = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | xargs git grep $@; };f "
    grep-branch-remote = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | grep '^remotes' | xargs git grep $@; };f"
    grep-branch-local  = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' -e '^remotes' | xargs git grep $@;  };f "

注:エイリアスを追加しても実行に失敗する\場合は、バックスラッシュを確認してください。bashコマンド\\と比較して、追加のエスケープが必要になる場合があります。

  • git branch -a -すべてのブランチを表示します。
  • sed -e 's/[ \\*]*//'-トリムスペース(からbranch -a)および*(アクティブなブランチ名にはそれがあります);
  • grep -v -e '\\->'-のような複雑な名前は無視してくださいremotes/origin/HEAD -> origin/master
  • grep '^remotes' -すべてのリモートブランチを取得します。
  • grep -v -e '^remotes'- リモートブランチ以外のブランチ取得します。

git grep-branch-local -n getTastyCookies

-n 一致する行の前に行番号を付けます。

[user@pc project]$ git grep-branch-local -n getTastyCookies

dev:53:modules/factory/getters.php:function getTastyCookies($user);
master:50:modules/factory/getters.php:function getTastyCookies($user)

現在の構造は次のとおりです。

: -セパレーター

  1. ブランチ: dev
  2. 行番号: 53
  3. ファイルパス: modules/factory/getters.php
  4. 一致する行: function getTastyCookies($user)

GREPの使用:BASH

ご存知のとおり:Bashコマンドは.shスクリプトに格納するか、シェルで実行する必要があります。

ローカルブランチのみ

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' -e '^remotes' | xargs git grep "TEXT"

リモートブランチのみ

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | grep '^remotes' | xargs git grep "TEXT"

ローカルおよびリモートのブランチ

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | xargs git grep "TEXT"

git grep-branch "find my text"fatal: ambiguous argument 'client': both revision and filename
良さそうに聞こえ

-aすべてのブランチを表示するを常に使用するのはなぜですか?git branchコマンドのオプションを使用して、ブラケットを分離することをお勧めします。ローカルブランチを見ると、は1つしか*ないため、sedでエスケープする必要はありません。つまりgit branch | sed -e 's/*/ /' | xargs git grep "TEXT"、ローカルブランチのみ、git branch -r | grep -v -- "->" | xargs git grep "TEXT"リモートブランチのみ、およびgit branch -a | grep -v -- "->" | xargs git grep "TEXT"すべてのブランチ
jalanb

4

ここに私がそれをする方法があります:

git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM

2
Windows(Git bash)で私のために機能した唯一のソリューション
Ivan

4

コミットをSHA-1ハッシュ値に与えるgit grepと、作業コピーの代わりにそれらを検索します。

すべてのブランチを検索するには、ですべての木を取得できますgit rev-list --all。全部入れて

git grep "regexp" $(git rev-list --all)

...そして忍耐力があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.