git-svn ヘルプの日本語訳 の履歴(No.1)
更新git help svn より: 基本的な使用例†
Subversion で管理されるプロジェクトの trunk に対して、変更を追跡したり 開発に貢献するには:
# リポジトリを複製 (git clone と同様に) git-svn clone http://svn.foo.org/project/trunk # 複製されたディレクトリに移動 cd trunk # master ブランチで作業している必要があるので git-branch で確認。 git branch # 何か作業を行った後、git のローカルリポジトリにコミット git commit ... # SVN に何かコミットされているかもしれないので、ローカルの変更点を # SVN の最新の更新に対するものとして rebase する git-svn rebase # 変更点を (先に git でローカルにコミットされたもの) SVN にコミットする # このときワーキングディレクトリの HEAD リビジョンも自動的に更新される git-svn dcommit # svn:ignore の設定を git の除外ファイルとして追加する git-svn show-ignore >> .git/info/exclude
Subversion で管理されるプロジェクトの全てに対して、(trunk, tags, branches を含めて) 変更を追跡したり開発に貢献するには:
# リポジトリを複製 (git clone と同様に) git-svn clone http://svn.foo.org/project -T trunk -b branches -t tags # 複製したリポジトリにあるすべての branch や tag を表示 git branch -r # master を trunk に reset (あるいは 'trunk' を変える事で他の任意の branch に) git reset --hard remotes/trunk # 一度に一つの branch/tag/trunk にしか dcommit することはできない。 # dcommit/rebase/show-ignore の使い方は上と同じ。
最初の git-svn clone はとても時間が掛かるかもしれない(特に大きな SVN リポジトリに対しては)。もし複数の人が(または一人が複数の機械で) 同じ Subversion リポジトリに対して git-svn clone したいのであれば、 まず一人が git-svn clone して、残りは git リポジトリを git clone することもできる。
# 始めのインポートをサーバー上で行う ssh server "cd /pub && git-svn clone http://svn.foo.org/project # サーバー上のリポジトリをローカルに clone する # refs/remotes/ の部分はサーバーに合わせること mkdir project cd project git-init git remote add origin server:/pub/project git config --add remote.origin.fetch '+refs/remotes/*:refs/remotes/*' git fetch # ローカルで git-svn を初期化 #(サーバーで付けたのと同じ URL や -T/-b/-t オプションをつけること) git-svn init http://svn.foo.org/project # Subversion の最新の更新情報を反映 git-svn rebase
REBASE にするか PULL/MERGE にするか†
はじめのころ、git-svn は remotes/git-svn ブランチを pull または merge することを推奨していた。これは、git-svn set-tree A..B の書き方で複数の コミットを行うよりも git-svn set-tree B の形で HEAD のみをコミットする 事を作者が好んだためでした。
もしあなたが git-svn set-tree A..B を使っていくつかの変更点をコミットしていて、 かつ、最新の remotes/git-svn を自分のブランチにマージしていないとすれば、 あなたは git-svn rebase を使ってあなたのブランチをアップデートすべきであって、 git pull や git merge を使うべきではない。pull や merge では、SVN にコミット する際に、本来直線的でない履歴がフラットになってしまう。これは、 SVN 上で merge commits reversing previous commits してしまう危険性がある。
DESIGN PHILOSOPHY†
Subversion は merge の追跡ができないため、Subversion でブランチを使った 開発をするとやっかいな事になりうる。git-svn であれば通常のレイアウトを 採用した場合、複製の履歴(ブランチやタグも含む)をたどれるのに対して、 git 上で起きた merge の履歴を SVN ユーザーに知らせる事はまだできない。 したがって、利用者は git 上での更新履歴をできる限りを直線的に保ち、 SVN との整合性を取りやすくすべきだ。(CAVEATSも参照)
CAVEATS†
簡単のため、そして、機能性に劣るシステム(SVN)と相互運用をするため、 git-svn を使う場合には clone, fetch, dcommit は必ず直接 SVN サーバーに 対して行い、git リポジトリやブランチの間で clone/pull/merge/push を するのを避けるべきだ。git ブランチ間、あるいは git ユーザー間で コードのやりとりをする最良の方法は、git-format-patch と git-am を つかうことであり、あるいは単に SVN リポジトリに dcommit することだ。
後に SVN サーバーに dcommit するつもりがあるブランチに対して git-merge や git-pull を使う事は推奨されない。Subversion が merge の履歴を管理する 方法は、理にかなってもいないし、使いやすくもない。だから、Subversion の ユーザーは自分が行った merge を見る事ができない。さらに悪いことに、 SVN をミラーした git ブランチから merge や pull してしまうと、dcommit する際に間違ったブランチにコミットしてしまう可能性がある。
git-clone は refs/remotes/ 階層や git-svn メタデータ、あるいは config で 管理されるブランチ情報を複製しない。従って、git-svn で作成され、管理されている リポジトリを、もしどうしても複製するのであれば、rsync を使うべきだ。
dcommit は内部で rebase を使うので、dcommit する前に git-push された git ブランチが存在すると、リモートのリポジトリにある ref を上書きすることを force しなければならなくなる。これは一般に良くない方法と考えられている。 詳細については git-push(1) のドキュメントを参照のこと。
すでに dcommit した変更に対して git-commit(1) の --amend オプションを使っては ならない。他のユーザーのことを考えれば、リモートリポジトリにすでに push した 内容を commit --amend するのは良くない習慣と考えられ、SVN に対して dcommit する のも同じように考える事ができる。
BUGS†
svn:executable 以外の SVN プロパティは全て無視される。プロパティが無視された際には $GIT_DIR/svn/<refname>/unhandled.log にログが残る。
ディレクトリの名前が変更されたことや、ディレクトリの複製が行われた事は git で 自動的に検出されない。したがって、SVN にコミットしたときに履歴が残らない。この点が 改善される予定はない。全ての可能性を網羅して正しく動作させるのが非常に難しく時間が 掛かるためだ(これは git にもできない)。ファイルの名前が変更されたり、ファイルが 複製された場合、その内容が十分に似ていれば git はそれらを認識し、完全に正しく扱われる。
CONFIGURATION†
git-svn は [svn-remote] 設定情報を .git/config ファイルに保存する。内容は core git の [remote] セクションと似ているが、fetch キーが * を含む事ができないという点で異なる。 代わりに branch や tag キーが使われる。複数のプロジェクトを含む SVN リポジトリが 通常とは異なる形で作られている場合があるため、以下に挙げる形でのみ * の展開を使う事が できるようになっている。
[svn-remote "project-a"] url = http://server.org/svn branches = branches/*/project-a:refs/remotes/project-a/branches/* tags = tags/*/project-a:refs/remotes/project-a/tags/* trunk = trunk/project-a:refs/remotes/project-a/trunk
ローカル ref に含まれる( : の右側の)アスタリスク * ワイルドカードは、 一番右のパス要素でなければならないことに注意せよ。これに対して、リモートの ワイルドカードは、それ自体が独立したパス要素である( / か : で挟まれている) 限り、どこに現れても良い。この形の設定は init を使って自動的に作る事は できないので、テキストエディタや git-config を使って手で書く必要がある。