-
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 配管コマンド
A2.2 付録 B: Gitをあなたのアプリケーションに組み込む - Libgit2を使う方法
Libgit2を使う方法
あなたが取れる2つ目のオプションは、Libgit2を使用することです。 Libgit2は、他のプログラムへの依存性のないGitの実装であり、プログラムから使いやすいAPIを提供することにフォーカスしています。 Libgit2は http://libgit2.github.com から取得できます。
まずは、C言語用のAPIがどのようなものか見てみましょう。 ここは駆け足で行きます。
// リポジトリを開く
git_repository *repo;
int error = git_repository_open(&repo, "/path/to/repository");
// HEADへの参照を解決してコミットを取得
git_object *head_commit;
error = git_revparse_single(&head_commit, repo, "HEAD^{commit}");
git_commit *commit = (git_commit*)head_commit;
// コミットのプロパティのうちいくつかを出力
printf("%s", git_commit_message(commit));
const git_signature *author = git_commit_author(commit);
printf("%s <%s>\n", author->name, author->email);
const git_oid *tree_id = git_commit_tree_id(commit);
// クリーンアップ
git_commit_free(commit);
git_repository_free(repo);
最初の2行で、Gitのリポジトリを開いています。
git_repository
型は、メモリにキャッシュされているリポジトリへのハンドルを表しています。
リポジトリの作業ディレクトリか、または .git
フォルダの正確なパスが分かっている場合、これがリポジトリを開く最もシンプルな方法です。
他の方法としては、 git_repository_open_ext
を使って検索オプション付きで開く方法、 git_clone
とその仲間を使ってリモートリポジトリのローカルなクローンを作る方法、 git_repository_init
を使って全く新規にリポジトリを作る方法があります。
2番目のコードのかたまりは、 rev-parse 文法(詳細は ブランチの参照 を参照)を使って、HEADが最終的に指しているコミットを取得しています。
戻り値は git_object
型のポインタで、これはリポジトリのGitオブジェクトデータベースに存在する何かを表しています。
git_object
型は、実際には数種類のオブジェクトの “親” にあたります。 “子” にあたる型のメモリレイアウトは git_object
型と同じになっているので、正しい型へのキャストは安全に行えます。
上記の場合では、 git_object_type(commit)
が GIT_OBJ_COMMIT
を返すので、 git_commit
型のポインタへ安全にキャストできます。
次のかたまりは、コミットのプロパティにアクセスする方法を示しています。
ここの最後の行では git_oid
型を使用しています。これは、 Libgit2 において SHA-1 ハッシュを表現する型です。
このサンプルからは、いくつかのパターンが見て取れます。
-
ポインタを宣言して、 Libgit2 の呼び出しにそのポインタへの参照を渡すと、その呼び出しは多くの場合 int 型のエラーコードを返す。 値
0
は成功を表す。それより小さい値はエラーを表す。 -
Libgit2 がポインタへ値を入れて返したら、解放は自前で行わなければならない。
-
Libgit2 の呼び出しが
const
ポインタを返した場合、開放する必要はない。ただし、それがそれが属するオブジェクトが解放されたら、ポインタは無効になる。 -
Cでコードを書くのはちょっとキツい。
最後の1つは、 Libgit2 を使用するときに、C言語でコードを書こうということはまずないだろう、というくらいの意味です。 幸いなことに、様々な言語用のバインディングが利用可能です。これを使えば、あなたの使っている特定の言語や環境から、Gitリポジトリに対する作業を非常に簡単に行えます。 Libgit2 の Ruby 向けバインディングを使って上記の例を書いたものを見てみましょう。Libgit2 の Ruby 向けバインディングは Rugged という名前で、 https://github.com/libgit2/rugged から取得できます。
repo = Rugged::Repository.new('path/to/repository')
commit = repo.head.target
puts commit.message
puts "#{commit.author[:name]} <#{commit.author[:email]}>"
tree = commit.tree
ご覧のように、コードがだいぶすっきりしました。
第一に、 Rugged は例外を使用します。エラーの状態を知らせるのに、 ConfigError
や ObjectError
のような例外を raise できます。
第二に、リソースの明示的な解放処理がありません。これは、 Ruby がガベージコレクションをしてくれるためです。
それではもう少し複雑な例を見てみましょう。次の例では、コミットをゼロから作成しています。
blob_id = repo.write("Blob contents", :blob) # (1)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(:path => 'newfile.txt', :oid => blob_id) # (2)
sig = {
:email => "bob@example.com",
:name => "Bob User",
:time => Time.now,
}
commit_id = Rugged::Commit.create(repo,
:tree => index.write_tree(repo), # (3)
:author => sig,
:committer => sig, # (4)
:message => "Add newfile.txt", # (5)
:parents => repo.empty? ? [] : [ repo.head.target ].compact, # (6)
:update_ref => 'HEAD', # (7)
)
commit = repo.lookup(commit_id) # (8)
-
新しいファイルの内容を含む新しい blob を作成します。
-
インデックスとHEADのコミットのツリーを取得し、パス
newfile.txt
にある新しいファイルを追加します。 -
ODBに新しいツリーを作成し、それを新しいコミット用に使用しています。
-
author フィールドと committer フィールドに同じ署名を使います。
-
コミットメッセージです。
-
コミットを作成するときには、新しいコミットの親を指定する必要があります。 ここではHEADの先端を単一の親として指定しています。
-
Rugged (およびLibgit2)では、コミットを作成する際に、必要に応じて参照を更新することもできます。
-
戻り値は新しいコミットオブジェクトの SHA-1 ハッシュです。これは後で
Commit
オブジェクトを取得するために使用できます。
このRubyのコードは単純明快です。また、重い処理はLibgit2が行っているので、非常に高速に実行できます。 Rubyist でない方のために、 その他のバインディング では他のバインディングにも触れています。
高度な機能
Libgit2 には、Git のコアがスコープ外としている機能がいくつか備わっています。 一つの例がプラグイン機能です。 Libgit2 では、一部の機能に対し、カスタム “バックエンド” を指定できます。これにより、Git が行うのとは別の方法でデータを保存することができます。 Libgit2 では設定、refストレージ、オブジェクトデータベースなどに対してカスタムバックエンドを指定できます。
バックエンドがどのように機能するか見てみましょう。 次のコードは、Libgit2チームが提供しているサンプル( https://github.com/libgit2/libgit2-backends から取得できます)から拝借しています。 オブジェクトデータベース用のカスタムバックエンドを設定する方法を示しています。
git_odb *odb;
int error = git_odb_new(&odb); // (1)
git_odb_backend *my_backend;
error = git_odb_backend_mine(&my_backend, /*…*/); // (2)
error = git_odb_add_backend(odb, my_backend, 1); // (3)
git_repository *repo;
error = git_repository_open(&repo, "some-path");
error = git_repository_set_odb(odb); // (4)
(ここで、エラーの捕捉はしていますが、エラー処理は行っていないことに注意してください。あなたのコードが私たちのものより優れていることを願っています。)
-
空のオブジェクトデータベース(ODB) “フロントエンド” を初期化します。これは、実際の処理を行う “バックエンド” のコンテナとして機能します。
-
カスタムODBバックエンドを初期化します。
-
フロントエンドにバックエンドを追加します。
-
リポジトリを開きます。作成したODBを、オブジェクトの検索に使うように設定します。
さて、この git_odb_backend_mine
というのは何でしょうか?
そう、これは自作のODB実装のコンストラクタです。この中では、 git_odb_backend
構造体へ適切に値を設定しさえしていれば、どんな処理でも行えます。
処理は 例えば 以下のようになります。
typedef struct {
git_odb_backend parent;
// Some other stuff
void *custom_context;
} my_backend_struct;
int git_odb_backend_mine(git_odb_backend **backend_out, /*…*/)
{
my_backend_struct *backend;
backend = calloc(1, sizeof (my_backend_struct));
backend->custom_context = …;
backend->parent.read = &my_backend__read;
backend->parent.read_prefix = &my_backend__read_prefix;
backend->parent.read_header = &my_backend__read_header;
// …
*backend_out = (git_odb_backend *) backend;
return GIT_SUCCESS;
}
ここで、非常に分かりにくい制約として、 my_backend_struct
の最初のメンバ変数は git_odb_backend
構造体である必要があります。これによって、Libgit2 のコードが期待している通りのメモリレイアウトになることが保証されます。
構造体の残りの部分は任意です。この構造体は必要に合わせて大きくしたり小さくしたりして構いません。
この初期化関数では、構造体にメモリを割り当て、カスタムコンテキストを設定し、それがサポートしている parent
構造体のメンバーへデータを設定しています。
その他の呼び出しのシグネチャについては、Libgit2のソースの include/git2/sys/odb_backend.h
ファイルを見てみてください。ユースケースがはっきりしていれば、シグネチャのうちどれをサポートすればよいかを判断するのに役立つでしょう。
その他のバインディング
Libgit2 には各種の言語向けのバインディングがあります。
ここでは、これを書いている時点で利用できるバインディングの中から、その一部を使用して、小さなサンプルプログラムを示していきます。他にも、C++、Go、Node.js、Erlang、JVMなど多くの言語向けのライブラリがあり、成熟度合いも様々です。
バインディングの公式なコレクションは、 https://github.com/libgit2 にあるリポジトリを探せば見つかります。
以降で示すコードはいずれも、最終的にHEADが指しているコミットのコミットメッセージを返します(git log -1
のようなものです)。
LibGit2Sharp
バインディングは C# で書かれていて、生の Libgit2 の呼び出しを、ネイティブ感のある CLR API でラップすることに細心の注意が払われています。 サンプルプログラムは次のようになります。
new Repository(@"C:\path\to\repo").Head.Tip.Message;
Windows向けのデスクトップアプリケーション向けにはNuGetパッケージもあります。これは、すぐに作業を始めようという時に役立ちます。
objective-git
Apple のプラットフォーム向けのアプリケーションを書いているなら、おそらく実装には Objective-C を使用しているものと思います。 Objective-Git (https://github.com/libgit2/objective-git) は、そういった環境向けの Libgit2 のバインディングです。 サンプルプログラムは次のようになります。
GTRepository *repo =
[[GTRepository alloc] initWithURL:[NSURL fileURLWithPath: @"/path/to/repo"] error:NULL];
NSString *msg = [[[repo headReferenceWithError:NULL] resolvedTarget] message];
Objective-git は Swift に対しても完全な相互運用性があるので、 Objective-C を捨てたとしても怖くありません。
pygit2
Libgit2 の Python 向けバインディングは Pygit2 という名前で、 http://www.pygit2.org/ から取得できます。 サンプルプログラムは次のようになります。
pygit2.Repository("/path/to/repo") # リポジトリを開く
.head # 現在のブランチを取得
.peel(pygit2.Commit) # HEADが指すコミットまで移動
.message # メッセージを読む
参考文献
もちろん、 Libgit2 の機能の扱い方すべてを取り上げるのは、本書の範囲外です。 Libgit2 自体についてより多くの情報が必要な場合は、 API ドキュメントが https://libgit2.github.com/libgit2 にあります。また、ガイドが https://libgit2.github.com/docs にあります。 他のバインディングについては、同梱されている README やテストを見てみてください。ちょっとしたチュートリアルや、参考文献へのポインタが書かれていることがあります。