git grepとは、Gitが管理しているファイルの中身から文字列を探すコマンドです。「いまのファイルを探す」なら git grep、「いつ・どのコミットで増えたり消えたりしたかを履歴から探す」なら git log -S / -G / --grep を使います。 この2系統を目的で使い分けられると、リポジトリの中の探しものがぐっと速くなります。

この記事では、小さな検証用リポジトリを作り、git 2.43.0 で実際に動かした出力をそのまま載せています。特に -S と -G で結果が変わる例、全ブランチ・全コミットをまとめて検索する書き方、通常の grep や ripgrep との違いは、手元で再現できる形にしました。コマンドはすべてコピーして使えます。

git grepとgit logの検索の早見表

まずは「何を探したいか」から引ける表です。上の5行が「今のファイル」、下の5行が「履歴」を探すコマンドです。

やりたいこと コマンド 探す対象
今のファイルから文字列を探す git grep -n 語 追跡中のファイル(作業ツリー)
ファイル名だけ知りたい git grep -l 語 同上
特定の拡張子・フォルダだけ探す git grep -n 語 -- '*.js' パスで絞った範囲
別ブランチ・過去の時点の中身を探す git grep -n 語 ブランチ名 指定したコミットのスナップショット
全ブランチ・全コミットの中身を探す git grep -n 語 $(git rev-list --all) すべてのコミットのスナップショット
その語が増えた/減ったコミットを探す git log -S 語 --oneline 差分(出現回数の変化)
その語を含む行が変更されたコミットを探す git log -G 正規表現 --oneline 差分(追加・削除された行)
コミットメッセージから探す git log --grep 語 --oneline コミットメッセージ
全ブランチの履歴から探す git log --all -S 語 --oneline すべてのブランチの差分
関数の変更履歴を追う git log -L '/開始/,/終了/:ファイル' 指定した行範囲の履歴

よく使うオプションだけを抜き出すと次のとおりです。

オプション 意味 例
-n 行番号を付ける git grep -n TAX_RATE
-l / -L 一致したファイル名だけ/一致しなかったファイル名だけ git grep -l calcTotal
-c ファイルごとの一致行数 git grep -c TAX_RATE
-i 大文字と小文字を区別しない git grep -n -i todo
-w 単語として一致するものだけ git grep -n -w item
-e パターンを明示する(複数指定で「または」) git grep -e TODO -e FIXME
--and / --or / --not 同じ行の中での条件の組み合わせ git grep -e A --and -e B
--all-match 複数の -e を全部含むファイルに絞る git grep -l --all-match -e A -e B
-p 一致した行が属する関数名も表示 git grep -n -p TAX_RATE
-W 一致した行を含む関数全体を表示 git grep -W withTax
-C 数 前後の行も表示(-A 後ろ、-B 前) git grep -n -C1 findUser
-E / -F / -P 拡張正規表現/固定文字列/Perl互換正規表現 git grep -n -F '(1 + TAX_RATE)'
-o 一致した部分だけ表示 git grep -n -o 'TAX_[A-Z]*'
--untracked 未追跡ファイルも対象にする git grep -n --untracked 語
--no-index Git管理外のフォルダでも使う git grep -n --no-index 語

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「git grepの使い方一覧|過去コミットの文字列検索はlog -S」

検証に使ったリポジトリ(コピペで再現できます)

この記事の実行結果は、次のスクリプトで作った小さなリポジトリで取りました。6つのコミットと2つのブランチがあり、「値を書き換えたコミット」「行を移動しただけのコミット」「ファイルを消したコミット」が含まれています。-S と -G の違いを見るのにちょうどよい形です。

  • 環境:git version 2.43.0(Linux)、比較用に GNU grep と ripgrep 14.1.0
  • コミットのハッシュ(e8bca0f など)は、作成者名や日時で変わります。お手元では別の値になりますので、読み替えてください。
mkdir demo && cd demo
git init -q -b main .
git config user.name taro
git config user.email taro@example.com
mkdir -p src docs

cat > src/cart.js <<'EOF'
const TAX_RATE = 0.08;

function calcTotal(items) {
  let total = 0;
  for (const item of items) {
    total += item.price * item.qty;
  }
  return Math.floor(total * (1 + TAX_RATE));
}

module.exports = { calcTotal };
EOF

cat > src/user.js <<'EOF'
function findUser(id) {
  // TODO: キャッシュを入れる
  return db.users.find((u) => u.id === id);
}

module.exports = { findUser };
EOF

cat > docs/memo.md <<'EOF'
# メモ

- calcTotal は税込の合計を返す
- todo: 送料の計算を足す
EOF

git add . && git commit -qm "カートの合計計算を追加"

# 2つ目:値だけ書き換える(TAX_RATE の出現回数は変わらない)
sed -i 's/0.08/0.10/' src/cart.js
git commit -qam "TAX_RATE を 0.10 に変更"

# 3つ目:TAX_RATE を使う行を別の関数へ移動する(出現回数は変わらない)
cat > src/cart.js <<'EOF'
const TAX_RATE = 0.10;

function withTax(amount) {
  return Math.floor(amount * (1 + TAX_RATE));
}

function calcTotal(items) {
  let total = 0;
  for (const item of items) {
    total += item.price * item.qty;
  }
  return withTax(total);
}

module.exports = { calcTotal };
EOF
git commit -qam "税込計算を withTax に切り出す"

# 4つ目・5つ目:ファイルを足して、あとで消す
cat > src/legacy.js <<'EOF'
function applyCoupon(total, code) {
  if (code === "WELCOME") return total - 500;
  return total;
}
module.exports = { applyCoupon };
EOF
git add . && git commit -qm "クーポン適用を追加"
git rm -q src/legacy.js && git commit -qm "クーポン機能をいったん外す"

# 6つ目:別ブランチにだけあるファイル
git checkout -q -b feature/shipping
cat > src/shipping.js <<'EOF'
const FREE_SHIPPING_MIN = 5000;

function shippingFee(total) {
  return total >= FREE_SHIPPING_MIN ? 0 : 600;
}
module.exports = { shippingFee };
EOF
git add . && git commit -qm "送料計算を追加 (fix #12)"
git checkout -q main

# まだ git add していないファイル(未追跡)
echo 'const DRAFT_FLAG = true; // TODO: 後で消す' > scratch.js

できあがった履歴は次のとおりです(git log --oneline --all に日付を足した表示)。

2a89d3c 2026-09-20 送料計算を追加 (fix #12) (feature/shipping)
c3a74ca 2026-09-15 クーポン機能をいったん外す (HEAD -> main)
94ec4ed 2026-09-12 クーポン適用を追加
2bcc451 2026-09-10 税込計算を withTax に切り出す
de620ee 2026-09-05 TAX_RATE を 0.10 に変更
e8bca0f 2026-09-01 カートの合計計算を追加

※ 検証ではコミットの日付を GIT_AUTHOR_DATE と GIT_COMMITTER_DATE で指定しました。上のスクリプトをそのまま流すと日付は実行した日になります。

今のファイルから探す:git grepの基本

文字列を探す(行番号つき)

まず覚えるのは git grep -n 語 です。 -n を付けると「ファイル名:行番号:内容」の形で出ます。

$ git grep TAX_RATE
src/cart.js:const TAX_RATE = 0.10;
src/cart.js:  return Math.floor(amount * (1 + TAX_RATE));

$ git grep -n TAX_RATE
src/cart.js:1:const TAX_RATE = 0.10;
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

毎回 -n を打つのが手間なら、設定で既定にできます。

git config --global grep.lineNumber true

ファイル名だけ・件数だけ知りたい

-l はファイル名だけ、-c はファイルごとの一致行数、-L は「含まないファイル」です。

$ git grep -l calcTotal
docs/memo.md
src/cart.js

$ git grep -c TAX_RATE
src/cart.js:2

$ git grep -L TAX_RATE
docs/memo.md
src/user.js

-l の結果をほかのコマンドへ渡すときは、-z と xargs -0 を組み合わせると、空白を含むファイル名でも安心です。

$ git grep -z -l calcTotal | xargs -0 wc -l
  4 docs/memo.md
 15 src/cart.js
 19 total

大文字小文字を区別しない・単語単位で探す

-i は大文字と小文字を同じものとして扱い、-w は単語として一致したものだけを拾います。

$ git grep -n todo
docs/memo.md:4:- todo: 送料の計算を足す

$ git grep -n -i todo
docs/memo.md:4:- todo: 送料の計算を足す
src/user.js:2:  // TODO: キャッシュを入れる

-w の効果は、item と items のように「別の語の一部として含まれる」場合に出ます。

$ git grep -n item
src/cart.js:7:function calcTotal(items) {
src/cart.js:9:  for (const item of items) {
src/cart.js:10:    total += item.price * item.qty;

$ git grep -n -w item
src/cart.js:9:  for (const item of items) {
src/cart.js:10:    total += item.price * item.qty;

7行目は items しか含まないので、-w を付けると外れます。変数名を探すときは -w を付けると、似た名前の行が混ざらなくなります。

一致した部分だけ・見出しつきで見やすく表示する

-o は一致した部分だけ、-h はファイル名を省いて表示します。組み合わせると「定義されている関数名の一覧」のような集計に使えます。

$ git grep -n -o 'TAX_[A-Z]*'
src/cart.js:1:TAX_RATE
src/cart.js:4:TAX_RATE

$ git grep -h -o -E 'function [a-zA-Z]+' | sort
function calcTotal
function findUser
function withTax

件数が多いときは --heading --break を付けると、ファイルごとにまとまって読みやすくなります。

$ git grep -n --heading --break calcTotal
docs/memo.md
3:- calcTotal は税込の合計を返す

src/cart.js
7:function calcTotal(items) {
15:module.exports = { calcTotal };

複数の条件で探す:-e・--and・--or・--not・--all-match

AまたはB(-e を並べる)

-e を複数並べると「どれかを含む行」になります。 --or を書いても同じ意味です。

$ git grep -n -e TODO -e calcTotal
docs/memo.md:3:- calcTotal は税込の合計を返す
src/cart.js:7:function calcTotal(items) {
src/cart.js:15:module.exports = { calcTotal };
src/user.js:2:  // TODO: キャッシュを入れる

$ git grep -n -e TODO --or -e findUser
src/user.js:1:function findUser(id) {
src/user.js:2:  // TODO: キャッシュを入れる
src/user.js:6:module.exports = { findUser };

AかつB(同じ行に両方ある)

--and は「同じ行に両方ある」、--not は「その語を含まない」です。

$ git grep -n -e TAX_RATE --and -e floor
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

$ git grep -n -e TAX_RATE --and --not -e const
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

2つ目は「TAX_RATE を使っている行のうち、定義(const)の行は除く」という探し方です。使っている場所だけを見たいときに便利です。

かっこでまとめることもできます。シェルに解釈されないよう、かっこは \( \) と書きます。

$ git grep -n -e total --and \( -e let --or -e return \)
src/cart.js:8:  let total = 0;
src/cart.js:12:  return withTax(total);

AもBも含むファイル(行は別でもよい)

--all-match は「行は別々でもよいので、すべての語を含むファイル」に絞ります。 --and との違いは、判定の単位が行かファイルかという点です。

$ git grep -l --all-match -e TAX_RATE -e calcTotal
src/cart.js

docs/memo.md は calcTotal を含みますが TAX_RATE を含まないので、結果から外れています。

書き方 判定の単位 意味
-e A -e B 行 AまたはBを含む行
-e A --and -e B 行 AとBを両方含む行
-e A --and --not -e B 行 Aを含み、Bを含まない行
--all-match -e A -e B ファイル AとBの両方がどこかにあるファイルの、AまたはBを含む行

前後の行や関数ごと表示する:-C・-p・-W

一致した行だけでは文脈がわからないときに使います。

-C1 は前後1行ずつ(-A は後ろだけ、-B は前だけ)を添えます。

$ git grep -n -C1 findUser
src/user.js:1:function findUser(id) {
src/user.js-2-  // TODO: キャッシュを入れる
--
src/user.js-5-
src/user.js:6:module.exports = { findUser };

-p(--show-function)は、一致した行がどの関数の中にあるかを = 付きの行で教えてくれます。

$ git grep -n -p TAX_RATE -- src/cart.js
src/cart.js:1:const TAX_RATE = 0.10;
src/cart.js=3=function withTax(amount) {
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

4行目の一致が withTax 関数の中だとわかります。区切りが : の行が一致した行、= の行が関数の見出し、- の行が前後の文脈です。

-W(--function-context)は、一致した行を含む関数をまるごと表示します。

$ git grep -W withTax -- src/cart.js
src/cart.js:function withTax(amount) {
src/cart.js-  return Math.floor(amount * (1 + TAX_RATE));
src/cart.js-}
--
src/cart.js=function calcTotal(items) {
src/cart.js-  let total = 0;
src/cart.js-  for (const item of items) {
src/cart.js-    total += item.price * item.qty;
src/cart.js-  }
src/cart.js:  return withTax(total);
src/cart.js-}

「この関数はどこから呼ばれていて、呼び出し側は何をしているか」を一度に読めるので、コードを読む時間の短縮になります。

探す場所を絞る:パス指定と除外

パスは -- のあとに書きます。 -- は「ここから先はパスです」という区切りで、ブランチ名とファイル名がまぎれるのを防ぎます。

$ git grep -n calcTotal -- '*.js'
src/cart.js:7:function calcTotal(items) {
src/cart.js:15:module.exports = { calcTotal };

$ git grep -n calcTotal -- docs/
docs/memo.md:3:- calcTotal は税込の合計を返す

$ git grep -n calcTotal -- ':!docs'
src/cart.js:7:function calcTotal(items) {
src/cart.js:15:module.exports = { calcTotal };
書き方 意味
-- src/ src フォルダの下だけ
-- '*.js' 拡張子が js のファイルだけ(引用符で囲み、シェルに展開させない)
-- ':!docs' docs を除外(:(exclude)docs と同じ意味)
-- '*.js' ':!*.test.js' js のうちテストファイルを除く(組み合わせ。この行は未実行)
--max-depth 0 サブフォルダに入らず、今いる階層だけ

ポイントは、'*.js' を引用符で囲むことです。 囲まないと、シェルがカレントフォルダのファイル名に展開してから git に渡すため、サブフォルダが対象から外れることがあります。

正規表現で探す:-E・-F・-P

git grep の既定は基本正規表現です。| や + をそのまま使いたいときは -E、記号を含む文字列をそのまま探したいときは -F が便利です。

$ git grep -n -E 'calc[A-Z][a-z]+\('
src/cart.js:7:function calcTotal(items) {

$ git grep -n -E -e 'TODO|todo'
docs/memo.md:4:- todo: 送料の計算を足す
src/user.js:2:  // TODO: キャッシュを入れる

$ git grep -n -F '(1 + TAX_RATE)'
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

$ git grep -n -P '\bqty\b'
src/cart.js:10:    total += item.price * item.qty;
オプション 種類 向いている場面
(なし)/ -G 基本正規表現 単純な語の検索
-E 拡張正規表現 A|B、+、?、( ) をそのまま書きたいとき
-F 固定文字列 かっこ・ドット・$ などを含む文字列をそのまま探すとき
-P Perl互換正規表現 \b、\d、先読みなどを使いたいとき(git のビルド設定によっては使えない場合があります)

いつも拡張正規表現にしたい場合は、設定で切り替えられます。設定後は -E なしで | が使えることを確認しました。

$ git config grep.patternType extended
$ git grep 'TODO|todo'
docs/memo.md:4:- todo: 送料の計算を足す
src/user.js:2:  // TODO: キャッシュを入れる

別ブランチ・過去の時点・全コミットの中身を探す

ブランチやコミットを指定する

git grep は、パターンのあとにブランチ名やコミットを書くと「その時点のファイル」を検索します。 チェックアウトし直す必要はありません。

$ git grep -n FREE_SHIPPING
(何も表示されない。終了コードは 1)

$ git grep -n FREE_SHIPPING feature/shipping
feature/shipping:src/shipping.js:1:const FREE_SHIPPING_MIN = 5000;
feature/shipping:src/shipping.js:4:  return total >= FREE_SHIPPING_MIN ? 0 : 600;

main には無い FREE_SHIPPING が、feature/shipping ブランチでは見つかりました。出力の先頭に「どのブランチ(コミット)の結果か」が付きます。

過去のコミットも同じ書き方です。複数並べれば見比べられます。

$ git grep -n TAX_RATE de620ee e8bca0f
de620ee:src/cart.js:1:const TAX_RATE = 0.10;
de620ee:src/cart.js:8:  return Math.floor(total * (1 + TAX_RATE));
e8bca0f:src/cart.js:1:const TAX_RATE = 0.08;
e8bca0f:src/cart.js:8:  return Math.floor(total * (1 + TAX_RATE));

HEAD~3(3つ前)のような相対指定や、パスの絞り込みも併用できます。

$ git grep -n TAX_RATE HEAD~3 -- src/
HEAD~3:src/cart.js:1:const TAX_RATE = 0.10;
HEAD~3:src/cart.js:8:  return Math.floor(total * (1 + TAX_RATE));

全ブランチの最新をまとめて探す

ブランチ名の一覧を作って git grep に渡します。

$ git branch -a --format='%(refname:short)' | xargs git grep -n FREE_SHIPPING
feature/shipping:src/shipping.js:1:const FREE_SHIPPING_MIN = 5000;
feature/shipping:src/shipping.js:4:  return total >= FREE_SHIPPING_MIN ? 0 : 600;

-a を付けているので、リモート追跡ブランチ(origin/〜)がある場合はそれも対象になります(今回の検証リポジトリにはリモートがないため、ローカルブランチだけで確認しています)。

全コミットの中身を探す(消えたコードも見つかる)

git rev-list --all はすべてのコミットのハッシュを出力します。これを git grep に渡すと、過去のどこかに存在したコードまで探せます。

$ git grep -n FREE_SHIPPING $(git rev-list --all)
2a89d3ccd9790ea2274d332c8845a981f74c4997:src/shipping.js:1:const FREE_SHIPPING_MIN = 5000;
2a89d3ccd9790ea2274d332c8845a981f74c4997:src/shipping.js:4:  return total >= FREE_SHIPPING_MIN ? 0 : 600;

$ git grep -l applyCoupon $(git rev-list --all)
94ec4ed6a48893fcf83a710309855015741c7f55:src/legacy.js

applyCoupon は、すでに削除した src/legacy.js にあった関数です。今のファイルにはありませんが、コミット 94ec4ed の時点には存在していたことがわかります。見つかったら、次のようにその時点の中身を取り出せます。

$ git show 94ec4ed:src/legacy.js
function applyCoupon(total, code) {
  if (code === "WELCOME") return total - 500;
  return total;
}
module.exports = { applyCoupon };

この方法は「各コミットのファイル全体」を調べるので、同じ行がコミットの数だけ繰り返し出ます。

$ git grep -c TAX_RATE $(git rev-list --all)
2a89d3ccd9790ea2274d332c8845a981f74c4997:src/cart.js:2
c3a74caa4402563aae52cf1dfe6f1393b8941b97:src/cart.js:2
94ec4ed6a48893fcf83a710309855015741c7f55:src/cart.js:2
2bcc451a95b3889766a6d3b2bdb316be00bc5aac:src/cart.js:2
de620ee750463995ff8ac266cc4017dec25a66b0:src/cart.js:2
e8bca0fc182307ed790adf17afd9d15bbb702658:src/cart.js:2

6コミットすべてで同じ結果が出ています。「どのコミットで変わったか」を知りたいときは、次の章の git log -S / -G のほうが向いています。

コミット数がとても多いリポジトリでは、$(git rev-list --all) の展開結果が長くなりすぎて、シェルが引数として渡せなくなることがあります(この状態の再現は未実行です)。その場合は xargs に分割を任せる書き方が使えます。こちらは同じ結果になることを確認しました。

$ git rev-list --all | xargs git grep -l applyCoupon
94ec4ed6a48893fcf83a710309855015741c7f55:src/legacy.js

まだコミットしていないファイルも探す

git grep が既定で探すのは「追跡中のファイル」だけです。 git add していない新規ファイルは対象外になります。

$ git grep -n DRAFT_FLAG
(何も表示されない。終了コードは 1)

$ git grep -n --untracked DRAFT_FLAG
scratch.js:1:const DRAFT_FLAG = true; // TODO: 後で消す
オプション 対象
(なし) 追跡中のファイルの、作業ツリー上の内容
--cached ステージ(インデックス)に入っている内容
--untracked 追跡中+未追跡のファイル(.gitignore の対象は除く)
--untracked --no-exclude-standard .gitignore で除外しているファイルも含める
--no-index Git管理外のフォルダでも使える(カレントフォルダ以下のファイルを検索)

.gitignore に node_modules/ を書いた状態で確かめると、--untracked だけでは node_modules は対象外のままで、--no-exclude-standard を足したときに初めて対象に入りました。

$ git grep -n --untracked TAX_RATE
src/cart.js:1:const TAX_RATE = 0.10;
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

$ git grep -n --untracked --no-exclude-standard TAX_RATE
node_modules/x/i.js:1:const TAX_RATE=1
src/cart.js:1:const TAX_RATE = 0.10;
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

履歴から探す:git log -S・-G・--grepの違い

ここからは「いつ変わったか」を探すコマンドです。git log の3つのオプションは、探す場所がそれぞれ違います。

オプション 探す場所 拾うコミット 引数
-S 語 差分 その語の出現回数が増減したコミット 既定は固定文字列(--pickaxe-regex で正規表現)
-G 正規表現 差分 追加または削除された行にパターンが一致するコミット 正規表現
--grep 語 コミットメッセージ メッセージにその語を含むコミット 正規表現

-S は「つるはし(pickaxe)」とも呼ばれるオプションです。

同じ語で結果が変わる例

検証用リポジトリで TAX_RATE を3通りに探します。

$ git log --oneline -S TAX_RATE
e8bca0f カートの合計計算を追加

$ git log --oneline -G TAX_RATE
2bcc451 税込計算を withTax に切り出す
de620ee TAX_RATE を 0.10 に変更
e8bca0f カートの合計計算を追加

$ git log --oneline --grep 'TAX_RATE'
de620ee TAX_RATE を 0.10 に変更

同じ語なのに、1件・3件・1件と結果が分かれました。 理由をコミットごとに整理します。

コミット 何をしたか TAX_RATE の回数 -S -G --grep
e8bca0f ファイルを新規追加 0 → 2 拾う 拾う -
de620ee 値を 0.08 → 0.10 に書き換え 2 → 2 - 拾う 拾う(メッセージに語がある)
2bcc451 TAX_RATE を使う行を別の関数へ移動 2 → 2 - 拾う -
  • -S は回数の変化だけを見ます。 値を書き換えても、行を移動しても、TAX_RATE という語の数が 2 のままなら拾いません。「この語が初めて入ったのはいつか」「いつ消えたか」を探すのに向いています。
  • -G は差分の行そのものを見ます。 追加(+)や削除(-)の行に TAX_RATE があれば拾うので、値の書き換えも行の移動も見つかります。
  • --grep はコードを見ません。 コミットメッセージだけが対象です。

値の変更を -S で探したいときは、変わった値そのものを指定します。

$ git log --oneline -S '0.08'
de620ee TAX_RATE を 0.10 に変更
e8bca0f カートの合計計算を追加

「0.08」は e8bca0f で 0 → 1、de620ee で 1 → 0 と回数が変わったため、両方が出ました。上が「消えたコミット」、下が「入ったコミット」です。

もうひとつ、Math.floor でも同じ違いが出ます。行を移動しただけの 2bcc451 は、-G だけが拾います。

$ git log --oneline -S 'Math.floor'
e8bca0f カートの合計計算を追加

$ git log --oneline -G 'Math\.floor'
2bcc451 税込計算を withTax に切り出す
e8bca0f カートの合計計算を追加

-G の引数は正規表現なので、ドットは \. と書きました。-S は既定で固定文字列として扱われるため、そのまま書けます。

差分も一緒に見る(-p)

-p を足すと、見つかったコミットの差分がその場で読めます。

$ git log -p -S '0.08' --format='%h %s'
de620ee TAX_RATE を 0.10 に変更

diff --git a/src/cart.js b/src/cart.js
index 297fdfa..1ee3821 100644
--- a/src/cart.js
+++ b/src/cart.js
@@ -1,4 +1,4 @@
-const TAX_RATE = 0.08;
+const TAX_RATE = 0.10;

 function calcTotal(items) {
   let total = 0;
e8bca0f カートの合計計算を追加
(以下、新規追加の差分が続く)

日付と作成者も一緒に見たいときは、表示形式を指定します。

$ git log --format='%h %ad %an %s' --date=short -S '0.08'
de620ee 2026-09-05 taro TAX_RATE を 0.10 に変更
e8bca0f 2026-09-01 taro カートの合計計算を追加

消したコードがいつ消えたかを探す

削除済みの applyCoupon を -S で探すと、追加したコミットと消したコミットの両方が出ます。--name-status を足すと、A(追加)と D(削除)でどちらかがわかります。

$ git log --oneline --name-status -S applyCoupon
c3a74ca クーポン機能をいったん外す
D   src/legacy.js
94ec4ed クーポン適用を追加
A   src/legacy.js

「あの関数、いつ誰が消したのだろう」という疑問は、この1行で解決します。

全ブランチの履歴を探す(--all)

git log は、既定では今いるブランチからたどれるコミットだけを見ます。別ブランチも含めるには --all を付けます。

$ git log --oneline -S FREE_SHIPPING
(何も表示されない)

$ git log --oneline --all -S FREE_SHIPPING
2a89d3c 送料計算を追加 (fix #12)

$ git log --oneline --all --source -S FREE_SHIPPING
2a89d3c refs/heads/feature/shipping 送料計算を追加 (fix #12)

--source を足すと、どのブランチ(参照)からたどり着いたコミットかも表示されます。

-Sで正規表現・大文字小文字の無視・パス指定を使う

$ git log --oneline -S 'calc[A-Z]' --pickaxe-regex
e8bca0f カートの合計計算を追加

$ git log --oneline -i -S tax_rate
e8bca0f カートの合計計算を追加

$ git log --oneline -S TAX_RATE -- src/cart.js
e8bca0f カートの合計計算を追加

$ git log --oneline --since=2026-09-08 -G TAX_RATE
2bcc451 税込計算を withTax に切り出す
足すオプション 効果
--pickaxe-regex -S の引数を正規表現として扱う
-i 大文字と小文字を区別しない(-S、-G、--grep に効く)
-- パス 対象のファイル・フォルダを絞る(大きなリポジトリでは速度にも効きます)
--since / --until 期間で絞る
--author=名前 作成者で絞る
--reverse 日付の早い順に並べる(最初に入ったコミットを先頭にしたいとき)
--pickaxe-all 一致したコミットの、変更された全ファイルを表示する

コミットメッセージから探す(--grep)

$ git log --oneline --all --grep 'fix #12'
2a89d3c 送料計算を追加 (fix #12)

$ git log --oneline -i --grep 'withtax'
2bcc451 税込計算を withTax に切り出す

--grep を複数書くと「どれかを含む」、--all-match を足すと「すべて含む」になります。

$ git log --oneline --grep 'クーポン' --grep '追加' --all-match
94ec4ed クーポン適用を追加

課題番号をコミットメッセージに書く習慣があると、--grep '#12' のように番号から関連コミットを一気に集められます。

関数の変更履歴を追う(-L)

git log -L は、指定した行範囲(関数など)に触れたコミットだけを順に見せてくれます。

$ git log --oneline -L '/function calcTotal/,/^}/:src/cart.js' -s
2bcc451 税込計算を withTax に切り出す
e8bca0f カートの合計計算を追加

-s を外すと、各コミットでその範囲がどう変わったかの差分も表示されます。「この関数だけの履歴」を追いたいときに便利です。

目的から選ぶ:どのコマンドを使うか

flowchart TD
    A[文字列を探したい] --> B{いまのファイルにある?}
    B -->|ある・わからない| C[git grep -n 語]
    C -->|見つからない| D{別ブランチにありそう?}
    D -->|はい| E[git grep 語 ブランチ名]
    D -->|過去に消したかも| F[git log --all -S 語 --oneline]
    B -->|履歴を知りたい| G{知りたいのは?}
    G -->|初めて入った/消えた時点| F
    G -->|その行が変更されたすべての時点| H[git log -G 正規表現 --oneline]
    G -->|メッセージに書いた内容| I[git log --grep 語 --oneline]
    F --> J[git show ハッシュ で差分を確認]
    H --> J
知りたいこと 使うコマンド
この定数はどこで使われているか git grep -n -w 定数名
この関数の呼び出し元と、その前後の処理 git grep -W 関数名
この設定値はいつ今の値になったか git log -S '前の値' -p
この行に手を入れたコミットを全部見たい git log -G 'パターン' --oneline
消えた関数が、いつどのコミットで消えたか git log --all -S 関数名 --name-status
消えた関数の中身をもう一度見たい git grep -l 関数名 $(git rev-list --all) → git show ハッシュ:パス
課題番号に関係するコミット git log --all --grep '#番号' --oneline

通常のgrep・ripgrepとの違いと使い分け

同じ検証リポジトリに、.gitignore 対象の node_modules/x/i.js(TAX_RATE を含む)を置いて3つを比べました。

$ grep -rn TAX_RATE . | head -5
./src/cart.js:1:const TAX_RATE = 0.10;
./src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));
./.git/logs/refs/heads/main:2:e8bca0f... taro <taro@example.com> ... commit: TAX_RATE を 0.10 に変更
./.git/logs/HEAD:2:e8bca0f... taro <taro@example.com> ... commit: TAX_RATE を 0.10 に変更

$ grep -rn TAX_RATE . --exclude-dir=.git
./src/cart.js:1:const TAX_RATE = 0.10;
./src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));
./node_modules/x/i.js:1:const TAX_RATE=1

$ git grep -n TAX_RATE
src/cart.js:1:const TAX_RATE = 0.10;
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

$ rg -n TAX_RATE
src/cart.js:1:const TAX_RATE = 0.10;
src/cart.js:4:  return Math.floor(amount * (1 + TAX_RATE));

※ grep の出力のうち .git/logs の2行は、ハッシュとタイムスタンプ部分を「...」で短くしています。

通常の grep -r は .git の中や node_modules まで探しに行きます。git grep と ripgrep は、どちらも最初からそれらを除いてくれました。 違いは「何を基準に除くか」です。

項目 git grep grep -r ripgrep(rg)
既定の対象 Gitが追跡しているファイル 指定フォルダ以下のすべて .gitignore に従い、隠しファイルとバイナリを除く
.git の中 探さない 探す(--exclude-dir=.git で除外) 探さない
.gitignore 対象 探さない 探す 探さない
未追跡の新規ファイル 探さない(--untracked で対象に) 探す 探す
過去のコミット・別ブランチ 探せる 探せない 探せない
関数名つき表示(-p / -W) できる できない できない
Gitリポジトリの外 --no-index が必要 使える 使える
追加インストール 不要(Gitに付属) 不要 必要

未追跡ファイルの扱いは、次のように実際に差が出ました。

$ git grep -n DRAFT_FLAG
(何も表示されない)

$ rg -n DRAFT_FLAG
scratch.js:1:const DRAFT_FLAG = true; // TODO: 後で消す

使い分けの目安は次のとおりです。

場面 おすすめ
リポジトリのコードを探す(普段使い) git grep
別ブランチや過去の時点を探す git grep(ブランチ・コミット指定)
作りかけの未追跡ファイルも含めて探す ripgrep、または git grep --untracked
Git管理外のログや設定ファイルを探す grep、ripgrep
ツールを追加できないサーバーで探す grep、git grep

つまずきやすい点と対処

何も表示されないとき

一致が無いとき、git grep は何も表示せず終了コード 1 を返します。 エラーではありません。シェルスクリプトでは、この終了コードを条件分岐に使えます(-q は表示を省くオプションです)。

if git grep -q "console.log" -- 'src/*.js'; then
  echo "console.log が残っています"
fi

見つからないときは、次の順に確かめるとスムーズです。

確認すること 試すコマンド
大文字小文字の違い -i を付ける
まだ add していないファイルにある --untracked を付ける
別ブランチにある git grep 語 ブランチ名
すでに削除された git log --all -S 語 --oneline
記号が正規表現として解釈されている -F を付ける
パスの指定が狭い -- パス を外してみる

表示されるメッセージと意味

実際に表示されたメッセージです。

$ cd /tmp && git grep foo
fatal: not a git repository (or any of the parent directories): .git

$ git grep
fatal: no pattern given

$ git log --oneline -S
error: switch `S' requires a value
メッセージ 意味 対処
not a git repository Gitリポジトリの外で実行した リポジトリの中へ移動する。管理外で使うなら --no-index
no pattern given 探す語を書いていない パターンを指定する
switch `S' requires a value -S のあとに語がない -S 語 と続けて書く

-Sで値の書き換えが見つからないとき

「-S で定数名を探したのに、値を変えたコミットが出てこない」というのは、もっともよく出会う場面です。前の章のとおり、-S は回数の変化しか見ないためです。次のどちらかで見つかります。

  • 行の変更を全部見る:git log -G 定数名 --oneline
  • 変わった値を探す:git log -S '前の値' --oneline

便利な設定とエイリアス

よく使う組み合わせは、エイリアス(別名)にしておくと短く打てます。

# 行番号を既定で表示
git config --global grep.lineNumber true

# 大文字小文字を無視し、ファイルごとにまとめて表示する git gg
git config --global alias.gg "grep -n -i --heading --break"

# その語が増減したコミットを全ブランチから探す git find-code
git config --global alias.find-code "log --all --oneline -S"

git gg は検証リポジトリで動作を確認しました(git find-code のエイリアス登録は未実行ですが、中身の git log --all --oneline -S 語 は上で実行したものと同じです)。

よくある質問

Q. git grep と git log -S は、どう使い分けますか? A. 「今どこにあるか」は git grep、「いつ入ったか・いつ消えたか」は git log -S です。git grep にコミットを渡せば過去の中身も探せますが、変化のあったコミットだけを知りたいなら git log -S のほうが結果が絞られます。

Q. -S と -G はどちらを使えばよいですか? A. その語が初めて入った時点や、消えた時点を知りたいなら -S が向いています。値の書き換えや行の移動も含めて、その行に手が入ったコミットをすべて見たいなら -G です。この記事の例では、TAX_RATE に対して -S は1件、-G は3件でした。

Q. 全ブランチを一度に検索できますか? A. できます。ファイルの中身は git grep 語 $(git rev-list --all)、履歴は git log --all -S 語 です。前者は各コミットの中身を全部調べるので結果が多くなりやすく、後者は変化のあったコミットだけが出ます。

Q. git grep で新しく作ったファイルが出てきません。 A. git grep の既定の対象は、追跡中のファイルだけです。git add する前のファイルも含めたいときは --untracked を付けます。

まとめ

  • 今のファイルを探すなら git grep -n 語。.git の中や .gitignore 対象を最初から除いてくれます。
  • -l(ファイル名)・-c(件数)・-i(大文字小文字)・-w(単語単位)が基本の4つです。
  • --and は同じ行、--all-match は同じファイルで条件を組み合わせます。-p と -W で関数単位の文脈も読めます。
  • ブランチ名やコミットを後ろに書けば、その時点の中身を検索できます。全コミットは $(git rev-list --all) です。
  • 履歴は git log。-S は出現回数の増減、-G は変更された行、--grep はコミットメッセージを見ます。
  • 値の書き換えや行の移動は -S では拾われません。-G を使うか、変わった値そのものを -S に渡します。
  • 未追跡ファイルは --untracked。ripgrep は未追跡ファイルも既定で探します。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「git grepの使い方一覧|過去コミットの文字列検索はlog -S」

株式会社RJCでは、Gitでの検索や履歴の調べ方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?