- Git
git grepの使い方一覧|過去コミットの文字列検索はlog -S
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期連続の黒字決算。