-
1. Gitの基本
- 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 スマートHTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 サードパーティのホスティングオプション
- 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 Resetの謎を解き明かす
- 7.8 高度なマージ
- 7.9 Rerere
- 7.10 Gitを使ったデバッグ
- 7.11 サブモジュール
- 7.12 バンドル
- 7.13 Replace
- 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 パックファイル
- 10.5 リフスペック
- 10.6 転送プロトコル
- 10.7 メンテナンスとデータ復旧
- 10.8 環境変数
- 10.9 まとめ
-
A1. 付録A: 他の環境におけるGit
- A1.1 グラフィカルインターフェース
- A1.2 Visual StudioでのGit
- A1.3 Visual Studio CodeでのGit
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMineでのGit
- A1.5 Sublime TextでのGit
- A1.6 BashでのGit
- A1.7 ZshでのGit
- A1.8 PowerShellでのGit
- A1.9 まとめ
-
A2. 付録B: アプリケーションへのGitの埋め込み
- A2.1 コマンドラインGit
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
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 Plumbingコマンド
7.5 Gitツール - 検索
検索
ほぼどんな規模のコードベースでも、関数がどこで呼び出されているか、あるいは定義されているかを探したり、メソッドの履歴を表示したりする必要がよくあります。Gitは、データベースに保存されたコードやコミットを素早く簡単に調べるための便利なツールをいくつか提供しています。そのうちのいくつかを見ていきましょう。
Git Grep
Gitには`grep`というコマンドが付属しており、コミットされた任意のツリー、作業ディレクトリ、あるいはインデックスの中から、文字列や正規表現を簡単に検索することができます。以下の例では、Git自身のソースコードを検索します。
デフォルトでは、`git grep`は作業ディレクトリ内のファイルを検索します。最初のバリエーションとして、`-n`または`--line-number`オプションのいずれかを使用して、Gitが一致を見つけた行番号を出力することができます。
$ 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:826:struct tm *gmtime_r(const time_t *timep, struct tm *result)
compat/mingw.h:206:struct tm *gmtime_r(const time_t *timep, struct tm *result);
date.c:482: if (gmtime_r(&now, &now_tm))
date.c:545: if (gmtime_r(&time, tm)) {
date.c:758: /* gmtime_r() in match_digit() may have clobbered it */
git-compat-util.h:1138:struct tm *git_gmtime_r(const time_t *, struct tm *);
git-compat-util.h:1140:#define gmtime_r git_gmtime_r
上記で示した基本的な検索に加えて、`git grep`は他にも多くの興味深いオプションをサポートしています。
例えば、すべての一致を出力する代わりに、`-c`または`--count`オプションを使って、検索文字列を含むファイルと各ファイル内の一致数だけを表示するよう`git grep`に求めることができます。
$ git grep --count gmtime_r
compat/gmtime.c:4
compat/mingw.c:1
compat/mingw.h:1
date.c:3
git-compat-util.h:2
検索文字列の*コンテキスト*に興味がある場合は、`-p`または`--show-function`オプションのいずれかを使用して、各一致文字列の囲んでいるメソッドや関数を表示できます。
$ git grep -p gmtime_r *.c
date.c=static int match_multi_number(timestamp_t num, char c, const char *date,
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)) {
date.c=int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
date.c: /* gmtime_r() in match_digit() may have clobbered it */
ご覧のとおり、`gmtime_r`ルーチンは`date.c`ファイルの`match_multi_number`関数と`match_digit`関数の両方から呼び出されています(表示されている3番目の一致は、コメント内に出現する文字列を示しています)。
さらに、`--and`フラグを使用して文字列の複雑な組み合わせを検索することもできます。これは、複数のマッチが同じ行に出現することを保証します。例えば、タグ`v1.8.0`で表されるGitコードベースの古いバージョンで、「LINK」または「BUF_MAX」のいずれかの部分文字列を含む定数を定義している行を探してみましょう(出力をより読みやすい形式に分割するのに役立つ`--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 */
`git grep`コマンドには、`grep`や`ack`のような通常の検索コマンドに比べていくつかの利点があります。1つ目は非常に高速であること、2つ目は作業ディレクトリだけでなく、Gitの任意のツリーを検索できることです。上記の例で見たように、現在チェックアウトされているバージョンではなく、古いバージョンのGitソースコード内の用語を検索しました。
Gitログの検索
おそらく、ある用語が*どこ*に存在するのかではなく、*いつ*存在したのか、あるいはいつ導入されたのかを探しているかもしれません。`git log`コマンドには、コミットメッセージの内容や、導入された差分の内容によって特定のコミットを見つけるための強力なツールがいくつかあります。
例えば、`ZLIB_BUF_MAX`定数がいつ最初に導入されたかを調べたい場合、`-S`オプション(通称Gitの「つるはし」オプション)を使用すると、その文字列の出現回数が変更されたコミットのみを表示するようにGitに指示できます。
$ git log -S ZLIB_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`オプションで検索する正規表現を提供できます。
行ログ検索
もう一つの非常に高度で非常に便利なログ検索は、行履歴検索です。単に`-L`オプションを付けて`git log`を実行するだけで、コードベース内の関数やコード行の履歴を表示できます。
例えば、`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がプログラミング言語での関数やメソッドのマッチング方法を特定できない場合、正規表現(*regex*)を提供することもできます。例えば、これは上記の例と同じことを行います: `git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c`。行の範囲や単一行番号を指定することもでき、同じ種類の出力が得られます。