「clmemo@aka: Repo って何だろ? -- 複数 git リポジトリーのためのツール」の続き。Repo を自分用のプロジェクトで使ってみる。言い換えると、複数の git リポジトリー管理に repo を使うお話。
Repo を使うためには、管理したい「複数の git リポジトリー」がどこにあるかを repo コマンドに教えないといけない。そのファイルが Manifest ファイルになる。簡単な Manifest ファイルを書いたので、それをサンプルに説明をしていきませう。
サンプル
サンプルの Manifest を github で公開した。名前は gm-manifest.git。
ソース・コード (default.xml) は次の通り。
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="github"
fetch="git://github.com/"
review="at-aka.blogspot.com" />
<default revision="master"
remote="github" />
<project path=".welcome"
name="ataka/gm-manifest"
remote="github">
<copyfile src="README" dest="README" />
</project>
<project path="greader-sbm"
name="ataka/greader-sbm" remote="github" />
<project path="greader-show-original"
name="ataka/greader-show-original" remote="github" />
</manifest>
ぼくが管理している 2 つの Greasemonkey スクリプトの git リポジトリーを、一括で管理する。
流れ
- Manifest ファイル (default.xml) を書く
- Manifest ファイルを git で管理する (公開リポジトリー)
- 作業用ディレクトリーを作成
- repo init (Manifest リポジトリーを git clone & repo コマンド実体をダウンロード)
- repo sync (各リポジトリーの git clone)
repo は、Manifest ファイルが git で公開されていることを前提にしている。ここで言う「公開」は、「他の人に公開している」という意味ではなくて、「bare リポジトリー」であることを指している。
作業的にはかうなる。
$ mkdir gm-manifest && cd gm-manifest # 作業用ディレクトリーを作成
$ vi default.xml # Manifest ファイルを書く
$ vi README # README ファイルを書いておくと親切かもね
$ git init # git 管理開始
$ git add .
$ git commit -m 'first commit'
Manifest ファイルを書いて git 管理を開始したら、公開用リポジトリー (bare リポジトリー) を作る。ローカルに作ってもいいし、github なんかのリポジトリー・ホスティング・サーバーにアップしてもいい。ここでは、github にアップしてみる。
# Github で Manifest 用のプロジェクト (ここでは gm-manifest.git) を作る
# 以下、Github へのアップロード作業
$ git config user.email masayuki.ataka+gravatar@gmail.com
$ git remote add origin git@github.com:ataka/gm-manifest.git # アカウントは自分のアカウントを使ってね
$ git push origin master
Manifest リポジトリーを公開したら、repo init で Manifest リポジトリーを指定する。
$ mkdir working-dir && cd working-dir # 作業用ディレクトリーに移動
$ repo init -u git://github.com/ataka/gm-manifest.git
repo init -u git://github.com/ataka/gm-manifest.git
Getting repo ...
from git://android.git.kernel.org/tools/repo.git
remote: Counting objects: 269, done.
remote: Compressing objects: 100% (124/124), done.
remote: Total 269 (delta 136), reused 262 (delta 132)
Receiving objects: 100% (269/269), 153.23 KiB | 77 KiB/s, done.
Resolving deltas: 100% (136/136), done.
From git://android.git.kernel.org/tools/repo
* [new branch] for-gerrit2 -> origin/for-gerrit2
(略)
From git://android.git.kernel.org/tools/repo
* [new tag] v1.0 -> v1.0
(略)
Getting manifest ...
from git://github.com/ataka/gm-manifest.git
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 7 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (7/7), done.
From git://github.com/ataka/gm-manifest
* [new branch] master -> origin/master
Branch default set up to track remote branch refs/remotes/origin/master.
Switched to a new branch "default"
Your Name [ataka]:
Your Email [masayuki.ataka@gmail.com]:
repo initialized in /home/ataka/program/2009/working-dir
repo init はまず最初に、repo コマンドの本体 (Python スクリプト) をダウンロードして、.repo/repo ディレクトリー内に格納する (repo init コマンド実行直後のログがそれ)。いきなり android.git.kernel.org にアクセスして驚くかもしれないけど、それは repo 本体を取って来ているだけなので心配しなくていい。
続いて repo init は、Manifest リポジトリーを取得し .repo/manifests ディレクトリーに保存する。また、.repo/manifests/default.xml は .repo/manifest.xml にシンボリック・リンクが張られる。
repo sync コマンドを実行すると、ダウンロードした Manifest ファイルに従って、レポジトリーの clone が始まる。
$ repo sync
Initializing project ataka/gm-manifest ...
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 7 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (7/7), done.
From git://github.com/ataka/gm-manifest
* [new branch] master -> github/master
Initializing project ataka/greader-sbm ...
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 7 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (7/7), done.
From git://github.com/ataka/greader-sbm
* [new branch] master -> github/master
Initializing project ataka/greader-show-original ...
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 7 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (7/7), done.
From git://github.com/ataka/greader-show-original
* [new branch] master -> github/master
リファレンス
Repo 用の Manifest ファイルの説明は、Android のページに載っていない (ぼくが見つけていないだけかもしれないけれど ^^;)。
Manifest ファイルの唯一の資料は、.repo ディレクトリーの中にある。
- .repo/repo/docs/manifest-format.txt
せっかくなので、manifest-format.txt の中にある DTD を転載しておきませう。
<!DOCTYPE manifest [
<!ELEMENT manifest (remote*,
default?,
remove-project*,
project*,
add-remote*)>
<!ELEMENT remote (EMPTY)>
<!ATTLIST remote name ID #REQUIRED>
<!ATTLIST remote fetch CDATA #REQUIRED>
<!ATTLIST remote review CDATA #IMPLIED>
<!ATTLIST remote project-name CDATA #IMPLIED>
<!ELEMENT default (EMPTY)>
<!ATTLIST default remote IDREF #IMPLIED>
<!ATTLIST default revision CDATA #IMPLIED>
<!ELEMENT project (remote*)>
<!ATTLIST project name CDATA #REQUIRED>
<!ATTLIST project path CDATA #IMPLIED>
<!ATTLIST project remote IDREF #IMPLIED>
<!ATTLIST project revision CDATA #IMPLIED>
<!ELEMENT add-remote (EMPTY)>
<!ATTLIST add-remote to-project ID #REQUIRED>
<!ATTLIST add-remote name ID #REQUIRED>
<!ATTLIST add-remote fetch CDATA #REQUIRED>
<!ATTLIST add-remote review CDATA #IMPLIED>
<!ATTLIST add-remote project-name CDATA #IMPLIED>
<!ELEMENT remove-project (EMPTY)>
<!ATTLIST remove-project name CDATA #REQUIRED>
]>
Manifest ファイルの書式
default.xml (manifest.xml) の書式は次のやうになる。
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="github"
fetch="git://github.com/" />
<default revision="master"
remote="github" />
<project path="greader-sbm"
name="ataka/greader-sbm" remote="github" />
<project path="greader-show-original"
name="ataka/greader-show-original" remote="github" />
</manifest>
まず、remote 要素で「name」と「fetch」属性を指定する。「name」で指定した名前は、後で project 要素の中でも使われるし、git リポジトリーの「remote」名としても使われる。「fetch」は、git リポジトリーの URL のうち、共通するパスを書いておく。
default 要素では、デフォールト設定を書く。後で説明する project 要素で、属性を省略した時、この default 要素で設定した値が使われる。「revision」属性は、デフォールトで使うブランチ名。普通は master でいいと思う。「remote」属性は、デフォールトで使う「remote」の名前。
project 要素は、manifest ファイルの肝。ここに、リポジトリーの設定を書く。「remote」属性には remote 要素の「name」を指定する。「name」属性は、git リポジトリーの URL (の末尾) を書く。git リポジトリーの URL は、次のような形に分離されることになる。
${remote_fetch}/${project_name}.git
project 要素の「path」属性は、リポジトリーを展開する場所を指定する。path 属性を上手く使えば、こっちのリポジトリーは lib ディレクトリーの下、あっちのリポジトリーは doc ディレクトリーの下、という風にディレクトリー構造を作れる。path 属性はオプションなので省略も OK。省略した場合は、「name」属性と同じ名前のディレクトリーがトップに出来る。
さて、ここまで書いてきて、上のサンプル manifest が、もう少しシンプルに書けることに気付いた ^^;
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="github"
fetch="git://github.com/ataka" />
<default revision="master"
remote="github" />
<project name="greader-sbm" />
<project name="greader-show-original" />
</manifest>
うん、シンプルになった。
分からないこと
git push にあたるコマンド、repo upload について調べると、次のような説明がある。
Attribute `review`: Hostname of the Gerrit server where reviews
are uploaded to by `repo upload`. This attribute is optional;
if not specified then `repo upload` will not function.
upload 先が Gerrit (Android 専用のレビュー・サーバー) になっている。これはどういふことかしらん。う〜ん、ssh や git なサーバーに push できるのかな? ダメなのかな? こんど試してみやう。