Gitリポジトリ内をgrepする git grep はシンプルで超便利
Gitリポジトリ内を検索する機会はよくあると思います。
- このメソッドって、どこで使われてるんだっけ?
- その定数の定義って、値は何だっけ? どこにあるんだっけ?
- あのURLって、何箇所で使われているんだろう?
git grep
コマンドを使えば、Git管理下のファイルのみを対象としてgrepができます。
シンプルなコマンドですが、利便性はとても高いと思います。
なお、grep対象はカレントブランチのみです。
目次
シンプルな例
シンプルな例ですが、よく使います。
特定ワードを含む箇所を調べたい(大文字小文字を区別する)
一番シンプルな例です。大文字小文字の区別をするので、注意が必要です。
なお、ワードの指定は正規表現(基本)です。正規表現(拡張)を使う場合は、-E
オプションを使います。
$ git grep "lambda" hello_world/slash_command.py:from common_lambda import get_notify_delays, get_message hello_world/slash_command.py:def lambda_handler(event, context) -> dict: template.yaml: Handler: slash_command.lambda_handler tests/unit/test_handler.py: ret = app.lambda_handler(apigw_event, "")
特定ワードを含む箇所を調べたい(大文字小文字を区別しない)
-i
オプションを使います。
$ git grep -i "Lambda" hello_world/slash_command.py:from common_lambda import get_notify_delays, get_message hello_world/slash_command.py:def lambda_handler(event, context) -> dict: template.yaml: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole template.yaml: Handler: slash_command.lambda_handler tests/unit/test_handler.py: ret = app.lambda_handler(apigw_event, "")
行番号を表示したい
-n
オプションを使います。
$ git grep -n "lambda" hello_world/slash_command.py:4:from common_lambda import get_notify_delays, get_message hello_world/slash_command.py:7:def lambda_handler(event, context) -> dict: template.yaml:32: Handler: slash_command.lambda_handler tests/unit/test_handler.py:74: ret = app.lambda_handler(apigw_event, "")
行番号表示は、Gitの設定でデフォルトONにできます。
$ git config --global grep.lineNumber true
正規表現(拡張)で検索したい
-E
オプションを使えば、正規表現(拡張)の表記で検索ができます。
次の例は「数字が2つ並んでいる箇所」です。
$ git grep -E "[0-9]{2}" hello_world/common_lambda.py: if res.status_code == 200: hello_world/requirements.txt:requests==2.20.0 hello_world/slash_command.py: "statusCode": 200, template.yaml:AWSTemplateFormatVersion: '2010-09-09' template.yaml:Transform: AWS::Serverless-2016-10-31 template.yaml: Timeout: 10
単語で検索したい
-w
オプションを使います。
$ git grep -w "Function" template.yaml: Function: template.yaml: Type: AWS::Serverless::Function template.yaml: Type: AWS::Serverless::Function
ちなみに-w
オプションが無い場合は次のような感じです(増えてますね)。
$ git grep "Function" template.yaml: Function: template.yaml: NotifyPeriodicFunction: template.yaml: Type: AWS::Serverless::Function template.yaml: NotifySlashCommandFunction: template.yaml: Type: AWS::Serverless::Function
なお次を単語とみなしているようです。
- 行の先頭で始まる or 頭に単語以外の文字がある
- 行の終わりで終わるか or 単語以外の文字が続く
少し便利な例
ニッチな事例かもしれませんが、たまに役立つかもしれません。
- 特定フォルダのみで検索したい
- 特定フォルダを除外して検索したい
- 複数のワードを調べたい
- 表示時にファイル毎に空行を入れて見やすくする
- 不一致な行を調べたい
- 一致した行の上側を表示したい
- 一致した行の下側を表示したい
- 一致した行の上下を表示したい
- 一致した行を含む関数を表示したい
- ファイル名の一覧を調べたい
- 一致した数を調べたい(ファイル毎)
- 一致した数を調べたい(全体)
- 一致した数を調べたい(ファイル数)
- 複数ファイルの特定文字列を置換する(Git管理ファイルのみ)
特定フォルダのみで検索したい
-- <dir_name>
を使用します。
$ git grep lambda -- hello_world/ hello_world/periodic.py:from common_lambda import get_notify_delays, get_message hello_world/periodic.py:def lambda_handler(event, context) -> None: hello_world/slash_command.py:from common_lambda import get_notify_delays, get_message hello_world/slash_command.py:def lambda_handler(event, context) -> dict:
特定フォルダを除外して検索したい
-- :^<dir_name>
を使用します。:^
がポイントです。
$ git grep lambda -- :^hello_world/ template.yaml: Handler: periodic.lambda_handler template.yaml: Handler: slash_command.lambda_handler tests/unit/test_handler.py:def test_lambda_handler(apigw_event, mocker): tests/unit/test_handler.py: ret = app.lambda_handler(apigw_event, "")
複数のワードを調べたい
--and
と--or
が使えます。ついでに--not
も使えます。パターンは-e
で指定する必要があります。
and
$ git grep -e lambda --and -e app tests/unit/test_handler.py: ret = app.lambda_handler(apigw_event, "")
or
$ git grep -e lambda --or -e app hello_world/common_lambda.py: notify_delays.append(check_item) hello_world/common_lambda.py: details.append(f'・{company}: {name}: <{website}|こちら>') hello_world/periodic.py:from common_lambda import get_notify_delays, get_message hello_world/periodic.py:def lambda_handler(event, context) -> None: hello_world/slash_command.py:from common_lambda import get_notify_delays, get_message hello_world/slash_command.py:def lambda_handler(event, context) -> dict: template.yaml: Handler: periodic.lambda_handler template.yaml: Handler: slash_command.lambda_handler tests/unit/test_handler.py:from hello_world import app tests/unit/test_handler.py:def test_lambda_handler(apigw_event, mocker): tests/unit/test_handler.py: app.requests, 'get', side_effect=requests_response_mock) tests/unit/test_handler.py: ret = app.lambda_handler(apigw_event, "")
表示時にファイル毎に空行を入れて見やすくする
--break
オプションを使います。
$ git grep --break lambda hello_world/periodic.py:from common_lambda import get_notify_delays, get_message hello_world/periodic.py:def lambda_handler(event, context) -> None: hello_world/slash_command.py:from common_lambda import get_notify_delays, get_message hello_world/slash_command.py:def lambda_handler(event, context) -> dict: template.yaml: Handler: periodic.lambda_handler template.yaml: Handler: slash_command.lambda_handler tests/unit/test_handler.py:def test_lambda_handler(apigw_event, mocker): tests/unit/test_handler.py: ret = app.lambda_handler(apigw_event, "")
不一致な行を調べたい
-v
オプションを使います。あまり使いどころはないかもしれませんが……。
$ git grep -v "lambda" ...(略)... template.yaml:Description: Notify Slack Train Delay template.yaml: template.yaml:Globals: template.yaml: Function: template.yaml: Timeout: 10 template.yaml: template.yaml:Resources: template.yaml: template.yaml: NotifyPeriodicFunction: template.yaml: Type: AWS::Serverless::Function ...(略)...
一致した行の上側を表示したい
-B <num>
オプションを使います。<num>
には数値を指定します。
次の例だと、「lambdaがヒットした行と上側の2行」を表示しています。
$ git grep -B 2 lambda template.yaml- Properties: template.yaml- CodeUri: hello_world/ template.yaml: Handler: periodic.lambda_handler -- template.yaml- Properties: template.yaml- CodeUri: hello_world/ template.yaml: Handler: slash_command.lambda_handler -- tests/unit/test_handler.py- tests/unit/test_handler.py- tests/unit/test_handler.py:def test_lambda_handler(apigw_event, mocker):
一致した行の下側を表示したい
-A <num>
オプションを使います。<num>
には数値を指定します。
次の例だと、「lambdaがヒットした行と下側の2行」を表示しています。
$ git grep -A 2 lambda template.yaml: Handler: periodic.lambda_handler template.yaml- Runtime: python3.6 template.yaml- Policies: -- template.yaml: Handler: slash_command.lambda_handler template.yaml- Runtime: python3.6 template.yaml- Events: -- tests/unit/test_handler.py:def test_lambda_handler(apigw_event, mocker): tests/unit/test_handler.py- tests/unit/test_handler.py- requests_response_mock = namedtuple("response", ["text"])
一致した行の上下を表示したい
-C <num>
オプションを使います。<num>
には数値を指定します。
次の例だと、「lambdaがヒットした行と上下の2行」を表示しています。
(「周辺をちょっと見たい」場合に使えそうですが、そのようなケースに遭遇したことはないです……)
$ git grep -C 2 lambda template.yaml- Properties: template.yaml- CodeUri: hello_world/ template.yaml: Handler: periodic.lambda_handler template.yaml- Runtime: python3.6 template.yaml- Policies: -- template.yaml- Properties: template.yaml- CodeUri: hello_world/ template.yaml: Handler: slash_command.lambda_handler template.yaml- Runtime: python3.6 template.yaml- Events: -- tests/unit/test_handler.py- tests/unit/test_handler.py- tests/unit/test_handler.py:def test_lambda_handler(apigw_event, mocker): tests/unit/test_handler.py- tests/unit/test_handler.py- requests_response_mock = namedtuple("response", ["text"])
一致した行を含む関数を表示したい
-W
オプションを使います。
関数の場合は良い感じにしてくれそうですが、YAMLファイルとか単なるTextファイルなどの場合は微妙です……(仕方がない)。
$ git grep -W lambda hello_world/periodic.py:def lambda_handler(event, context) -> None: hello_world/periodic.py- hello_world/periodic.py- notify_delays = get_notify_delays() hello_world/periodic.py- hello_world/periodic.py- if not notify_delays: hello_world/periodic.py- # 遅延が無ければ通知しない hello_world/periodic.py- return hello_world/periodic.py- hello_world/periodic.py- # Slack用のメッセージを作成して投げる hello_world/periodic.py- (title, detail) = get_message(notify_delays) hello_world/periodic.py- post_slack(title, detail) hello_world/periodic.py- hello_world/periodic.py- return
ファイル名の一覧を調べたい
-l
オプションを使います。「xxxメソッドを変更するため、対象ファイルを知りたい」とかで使ってます。
$ git grep -l lambda hello_world/periodic.py hello_world/slash_command.py template.yaml tests/unit/test_handler.py
一致した数を調べたい(ファイル毎)
-c
オプションを使います。
$ git grep -c lambda hello_world/periodic.py:2 hello_world/slash_command.py:2 template.yaml:2 tests/unit/test_handler.py:2
一致した数を調べたい(全体)
wc -l
コマンドと組み合わせて、改行の数をカウントしています。
$ git grep lambda | wc -l 8
一致した数を調べたい(ファイル数)
こちらもwc -l
コマンドと組み合わせます。
$ git grep -l lambda | wc -l 4
複数ファイルの特定文字列を置換する(Git管理ファイルのみ)
ファイル一覧を取得して、後段で1ファイルずつ置換処理させています。
$ git grep -l '検索対象の文字列' | xargs sed -i '' -e 's/置換対象の文字列/置換後の文字列/g'
さいごに
長く書きましたが、次の3つが使えればとりあえず便利です!
git grep xxx
- シンプル版
git grep -i yyy
- 大文字小文字を区別しない版
git grep -E zzz
- 正規表現版
現在の仕事では複数リポジトリを扱っているので、「修正対象はどのリポジトリだっけ?」などを簡単に調査できるため重宝しています。(IDE開いて検索するより簡単)