git-svn ヘルプの日本語訳 のバックアップソース(No.5)

更新

[[公開メモ]]

以下は git help svn より、使用例から後の部分を適当に日本語訳した物 (2009-06-10)。

#contents

*  基本的な使用例 [#fe1a70fc]

Subversion で管理されるプロジェクトの trunk に対して、
git を使って変更を追跡したり開発に貢献するには:

 # リポジトリを複製 (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 にするか [#b189eff3]

はじめのころ、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 [#j2574311]

Subversion は merge の追跡ができないため、Subversion でブランチを使った
開発をするとやっかいな事になりうる。git-svn であれば通常のレイアウトを
採用した場合、複製の履歴(ブランチやタグも含む)をたどれるのに対して、
git 上で起きた merge の履歴を SVN ユーザーに知らせる事はまだできない。
したがって、利用者は git 上での更新履歴をできる限りを直線的に保ち、
SVN との整合性を取りやすくすべきだ。(CAVEATSも参照)


* CAVEATS [#pd9edee1]

簡単のため、そして、機能性に劣るシステム(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 [#a06e0ca2]

svn:executable 以外の SVN プロパティは全て無視される。プロパティが無視された際には
$GIT_DIR/svn/<refname>/unhandled.log にログが残る。

ディレクトリの名前が変更されたことや、ディレクトリの複製が行われた事は git で
自動的に検出されない。したがって、SVN にコミットしたときに履歴が残らない。この点が
改善される予定はない。全ての可能性を網羅して正しく動作させるのが非常に難しく時間が
掛かるためだ(これは git にもできない)。ファイルの名前が変更されたり、ファイルが
複製された場合、その内容が十分に似ていれば git はそれらを認識し、完全に正しく扱われる。

* CONFIGURATION [#lbc955b8]

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 を使って手で書く必要がある。

* コメント [#l7133416]

自由にコメントを付けて下さい。

#article_kcaptcha

Counter: 12468 (from 2010/06/03), today: 2, yesterday: 2