-
1. 使い始める
- 1.1 バージョン管理に関して
- 1.2 Git略史
- 1.3 Gitの基本
- 1.4 コマンドライン
- 1.5 Gitのインストール
- 1.6 最初のGitの構成
- 1.7 ヘルプを見る
- 1.8 まとめ
-
2. Git の基本
- 2.1 Git リポジトリの取得
- 2.2 変更内容のリポジトリへの記録
- 2.3 コミット履歴の閲覧
- 2.4 作業のやり直し
- 2.5 リモートでの作業
- 2.6 タグ
- 2.7 Git エイリアス
- 2.8 まとめ
-
3. Git のブランチ機能
- 3.1 ブランチとは
- 3.2 ブランチとマージの基本
- 3.3 ブランチの管理
- 3.4 ブランチでの作業の流れ
- 3.5 リモートブランチ
- 3.6 リベース
- 3.7 まとめ
-
4. Gitサーバー
- 4.1 プロトコル
- 4.2 サーバー用の Git の取得
- 4.3 SSH 公開鍵の作成
- 4.4 サーバーのセットアップ
- 4.5 Git デーモン
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 サードパーティによる Git ホスティング
- 4.10 まとめ
-
5. Git での分散作業
- 5.1 分散作業の流れ
- 5.2 プロジェクトへの貢献
- 5.3 プロジェクトの運営
- 5.4 まとめ
-
6. GitHub
- 6.1 アカウントの準備と設定
- 6.2 プロジェクトへの貢献
- 6.3 プロジェクトのメンテナンス
- 6.4 組織の管理
- 6.5 スクリプトによる GitHub の操作
- 6.6 まとめ
-
7. Git のさまざまなツール
- 7.1 リビジョンの選択
- 7.2 対話的なステージング
- 7.3 作業の隠しかたと消しかた
- 7.4 作業内容への署名
- 7.5 検索
- 7.6 歴史の書き換え
- 7.7 リセットコマンド詳説
- 7.8 高度なマージ手法
- 7.9 Rerere
- 7.10 Git によるデバッグ
- 7.11 サブモジュール
- 7.12 バンドルファイルの作成
- 7.13 Git オブジェクトの置き換え
- 7.14 認証情報の保存
- 7.15 まとめ
-
8. Git のカスタマイズ
- 8.1 Git の設定
- 8.2 Git の属性
- 8.3 Git フック
- 8.4 Git ポリシーの実施例
- 8.5 まとめ
-
9. Gitとその他のシステムの連携
- 9.1 Git をクライアントとして使用する
- 9.2 Git へ移行する
- 9.3 まとめ
-
10. Gitの内側
- 10.1 配管(Plumbing)と磁器(Porcelain)
- 10.2 Gitオブジェクト
- 10.3 Gitの参照
- 10.4 Packfile
- 10.5 Refspec
- 10.6 転送プロトコル
- 10.7 メンテナンスとデータリカバリ
- 10.8 環境変数
- 10.9 まとめ
-
A1. 付録 A: その他の環境でのGit
- A1.1 グラフィカルインタフェース
- A1.2 Visual StudioでGitを使う
- A1.3 EclipseでGitを使う
- A1.4 BashでGitを使う
- A1.5 ZshでGitを使う
- A1.6 PowershellでGitを使う
- A1.7 まとめ
-
A2. 付録 B: Gitをあなたのアプリケーションに組み込む
- A2.1 Gitのコマンドラインツールを使う方法
- A2.2 Libgit2を使う方法
- A2.3 JGit
-
A3. 付録 C: Gitのコマンド
- A3.1 セットアップと設定
- A3.2 プロジェクトの取得と作成
- A3.3 基本的なスナップショット
- A3.4 ブランチとマージ
- A3.5 プロジェクトの共有とアップデート
- A3.6 検査と比較
- A3.7 デバッグ
- A3.8 パッチの適用
- A3.9 メール
- A3.10 外部システム
- A3.11 システム管理
- A3.12 配管コマンド
7.5 Git のさまざまなツール - 検索
検索
コード量の大小を問わず、関数の参照位置・定義やメソッドの変更履歴を確認したくなることはよくあります。Git には便利なツールがいくつも用意されていて、コードやコミット履歴の確認が簡単にできるようになっています。具体的な方法をいくつか見ていきましょう。
Git Grep
Git に付属する grep
コマンドを使うと、コミット済みのツリーや作業ディレクトリが簡単に検索(文字列・正規表現)できます。使い方の説明を兼ねて、Git のソースコードを覗いてみることにしましょう。
このコマンドはデフォルトでは作業ディレクトリを検索します。-n
オプションと一緒に使うと、検索条件とマッチした行の番号も表示してくれます。
$ git grep -n gmtime_r
compat/gmtime.c:3:#undef gmtime_r
compat/gmtime.c:8: return git_gmtime_r(timep, &result);
compat/gmtime.c:11:struct tm *git_gmtime_r(const time_t *timep, struct tm *result)
compat/gmtime.c:16: ret = gmtime_r(timep, result);
compat/mingw.c:606:struct tm *gmtime_r(const time_t *timep, struct tm *result)
compat/mingw.h:162:struct tm *gmtime_r(const time_t *timep, struct tm *result);
date.c:429: if (gmtime_r(&now, &now_tm))
date.c:492: if (gmtime_r(&time, tm)) {
git-compat-util.h:721:struct tm *git_gmtime_r(const time_t *, struct tm *);
git-compat-util.h:723:#define gmtime_r git_gmtime_r
その他にも、興味深いオプションがこのコマンドにはいくつも用意されています。
上記の実行例とは違い、コマンド出力を Git に要約させることもできます。例えば、検索にマッチしたファイルの名前とマッチ回数を表示させるには、--count
オプションを使います。
$ git grep --count gmtime_r
compat/gmtime.c:4
compat/mingw.c:1
compat/mingw.h:1
date.c:2
git-compat-util.h:2
検索にマッチした結果からメソッドや関数と思われるものだけを確認したい場合は、-p
オプションを使いましょう。
$ git grep -p gmtime_r *.c
date.c=static int match_multi_number(unsigned long num, char c, const char *date, char *end, struct tm *tm)
date.c: if (gmtime_r(&now, &now_tm))
date.c=static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt)
date.c: if (gmtime_r(&time, tm)) {
この例では、gmtime_r
が date.c ファイルにある関数 match_multi_number
と match_digit
から呼び出されていることがわかります。
また、文字列の複雑な組み合わせを探したい場合は --and
オプションを使いましょう。検索条件がすべて同一行に含まれている行だけを返すためのオプションです。例として、文字列 “LINK” か “BUF_MAX” を含む定数が記述されている行を、Git の古いバージョン 1.8.0 から探してみます。
なお、この例では --break
と --heading
のオプションも使っています。出力を分割して読みやすくするためです。
$ git grep --break --heading \
-n -e '#define' --and \( -e LINK -e BUF_MAX \) v1.8.0
v1.8.0:builtin/index-pack.c
62:#define FLAG_LINK (1u<<20)
v1.8.0:cache.h
73:#define S_IFGITLINK 0160000
74:#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
v1.8.0:environment.c
54:#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
v1.8.0:strbuf.c
326:#define STRBUF_MAXLINK (2*PATH_MAX)
v1.8.0:symlinks.c
53:#define FL_SYMLINK (1 << 2)
v1.8.0:zlib.c
30:/* #define ZLIB_BUF_MAX ((uInt)-1) */
31:#define ZLIB_BUF_MAX ((uInt) 1024 * 1024 * 1024) /* 1GB */
grep
や ack
のような他の検索用コマンドと比較すると、git grep
コマンドには利点がふたつあります。とても早く動作することと、作業ディレクトリだけでなくコミット済みの全ツリーが検索対象であることです。上記の例ではその利点を示すために、検索対象を古いバージョンの Git のソースコードとし、チェックアウトされたバージョンのものにはしませんでした。
Git ログの検索
場合によっては、探しているのは語句の 所在 ではなく、語句が存在した・追加された 時期、ということもあるでしょう。git log
コマンドの強力なオプションを使うと、コミットメッセージの内容やコミットごとの差分をもとに、特定のコミットを絞り込めます。
ここでは、定数 ZLIB_BUF_MAX
が追加された時期を調べてみましょう。その文字列が追加、あるいは削除されたコミットだけを表示するには、-S
オプションを用います。
$ git log -SZLIB_BUF_MAX --oneline
e01503b zlib: allow feeding more than 4GB in one go
ef49a7a zlib: zlib can only process 4GB at a time
これらのコミットの差分を見てみると、コミット ef49a7a
でこの定数が追加され、コミット e01503b
でそれが変更されたことがわかります。
より詳しく調べたいのなら、-G
オプションをつけましょう。検索に正規表現が使えるようになります。
ログの行指向検索
一歩進んだログ検索の方法をもうひとつ見ておきましょう。履歴を行指向で検索するという、ものすごく便利な方法です。最近になって Git に追加された機能であまり知られていませんが、本当に便利です。git log
コマンドに -L
オプションをつけると行指向検索が有効になり、指定した行(関数など)の履歴を確認できます。
ここでは仮に、zlib.c
ファイルにある git_deflate_bound
関数の変更履歴を確認したいとしましょう。用いるコマンドは git log -L :git_deflate_bound:zlib.c
です。これを実行すると、指定された関数の定義範囲がまずは推測されます。そして、その範囲の全変更履歴をパッチの形でひとつずつ、関数が追加されたときの履歴にまでさかのぼって表示します。
$ git log -L :git_deflate_bound:zlib.c
commit ef49a7a0126d64359c974b4b3b71d7ad42ee3bca
Author: Junio C Hamano <gitster@pobox.com>
Date: Fri Jun 10 11:52:15 2011 -0700
zlib: zlib can only process 4GB at a time
diff --git a/zlib.c b/zlib.c
--- a/zlib.c
+++ b/zlib.c
@@ -85,5 +130,5 @@
-unsigned long git_deflate_bound(z_streamp strm, unsigned long size)
+unsigned long git_deflate_bound(git_zstream *strm, unsigned long size)
{
- return deflateBound(strm, size);
+ return deflateBound(&strm->z, size);
}
commit 225a6f1068f71723a910e8565db4e252b3ca21fa
Author: Junio C Hamano <gitster@pobox.com>
Date: Fri Jun 10 11:18:17 2011 -0700
zlib: wrap deflateBound() too
diff --git a/zlib.c b/zlib.c
--- a/zlib.c
+++ b/zlib.c
@@ -81,0 +85,5 @@
+unsigned long git_deflate_bound(z_streamp strm, unsigned long size)
+{
+ return deflateBound(strm, size);
+}
+
検索対象のコードで用いられているプログラミング言語によっては、 Git が関数やメソッドの定義範囲を絞り込めないことがあります。そんな場合は、正規表現を使いましょう。上記の例でいえば git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c
はまったく同じ結果を出力します。また、行番号で検索対象を指定(単一行の指定、複数行で範囲指定の両方が可能)しても、同じような結果が得られます。