- 追加された行はこの色です。
- 削除された行はこの色です。
* Subversionにおけるブランチ [#g6c33a4e]
#contents
** Subversionにおけるブランチの概念 [#z99c7e96]
Subversionにおけるブランチの概念は、単なるフォルダやファイルのコピーです。
例えば、trunkフォルダで作業中に、試験的にXという機能を実装する必要が出たとします。Xは、実際に使われるかどうかまだわかりません。
もしtrunkフォルダ上のファイルにXに関する変更を加えると、Xが正しく動くまでテストなどが出来ない状態になり、Xはいらないよ、ということになった時に、元に戻すのが大変です。
そこで、branch-xという名前でtrunkフォルダのコピーをつくり、そこで作業すれば、trunkフォルダの中身に影響を与えずに済みます。
trunkはtrunkで改良などが続き、branch-xではXの機能実装が行われる訳です。その間、trunkとbranch-xは、互いに影響を与えることはありません。
Xの機能はいらないとわかったら、branch-xフォルダを削除すれば良いですし、まぁ後々役に立つかもしれないと思うなら、残しておいても良いでしょう。trunkには影響を与えないので、残しておいても害はありません。
もしXの機能が必要なのでtrunkに組み込む、ということになれば、brach-xを、trunkに「マージ」することで、trunkにbranch-xの変更を適用できます。
これで、面倒な依存影響に煩わされることなく、開発を行うことが出来ます。
** 前提 [#hba18d51]
まず、trunkのみで、リビジョン120まで開発したとします。
そこで、機能Xの実装を試みるために、trunkをbranch-xという名前でコピーします。ここで、リビジョンは121になります。branch-xは、リビジョン121で作成されます。
そして、trunkとbranch-xの両方の更新が行われ、レポジトリのリビジョンは150まで上がったとします。そこで、機能Xをtrunkに取り込むことにします。
ちなみに、レポジトリ構造としては、
http://server/svn/project1/ - レポジトリのルートフォルダ
http://server/svn/project1/trunk - 主開発フォルダ
http://server/svn/project1/tags - タグ用のフォルダ
http://server/svn/project1/branches - ブランチ用フォルダ
http://server/svn/project1/branches/branch-x - Xの機能をためしに実装してみるフォルダで、リビジョン120のhttp://server/svn/project1/trunkをコピーして作られた
という感じになります。
** 操作の流れ [#n779afa9]
最初に、操作の流れだけ書いておきます。まとめや結論を先に、です。
+ ブランチを作る(trunkを、branch-xとしてコピーする)
+ trunkとbranch-xでそれぞれ開発を行い、必要に応じてtrunkの修正をbranch-xに取り込む(マージする)
+ trunkにXの機能追加を適用するために、branch-xの修正をtrunkに取り込む(マージする)
2.のマージ作業をこまめにやっておくと、3.のマージ作業が楽になります。
** ブランチの作り方 [#f2c7d4f1]
単純にコピーを行うだけです。基本はフォルダ単位で行います。
コマンドラインなら、svn copyコマンドを使って、trunkフォルダをbranch-xというフォルダでコピーしてください。
TortoiseSVNであれば、[[http://tortoisesvn.bluegate.org/Help/dailyuseguide.html#Copy]]辺りを参考にしてください。このページで、to URLにbranch-xという名前(正確には、フルURLにする必要があるが)を指定すれば、ブランチの作成が可能です。
Subclipseなら、プロジェクトリストのフォルダを右クリックして、Teamの所からブランチを作成できます。
ブランチは、レポジトリ内のコピーなので、作った直後は(ローカル側では)何も起きません。
なお、レポジトリ内では、リンクによりコピーが行われるので、巨大なファイルだろうが何だろうが気にする必要はありません。
** ブランチの使い方 [#o196fd84]
ブランチの使い方は二通りあります。
一つは、レポジトリ切り替えを行って、trunkの編集をやめてbranch-xの編集を始める方法です。
もう一つは、branch-xを新しくチェックアウトする方法です。
ここでは、後者をお奨めするので、その方法についてです。
trunkをチェックアウトした時と同じように、branch-xを指定してチェックアウトしてください。
操作はそれだけです。ローカル作業領域には、trunkとbranch-xの二つができることになります。
これで、同時に、もともとのtrunkの開発も行えて、branch-xでXの機能追加も行えます。
** trunkの修正をbranch-xに反映させる [#e5b66d31]
trunkで重要なバグ修正等があると、branch-xも更新する必要が出てきます。そうしないと、バグのあるままXの機能実装をすることになりますから。
そこで、trunkの修正をbranch-xに反映させる必要が出てきます。
マージ作業の原理は、次のようになります。
*** マージの原理 [#y8836596]
まず、trunkのリビジョンを二つ指定します。その二つのリビジョンの期間にtrunkに行われた変更点を、branch-xのローカルコピーに適用します。
リビジョンを含めて説明すると、リビジョン120からリビジョン150までの間に、trunkに行われた変更を、branch-xに適用すれば、branch-xの元となったtrunkは見かけ上、リビジョン120のものからリビジョン150のものになります。これがマージです。
マージは行単位で行われます。いわゆるdiffと同じ原理です。もし行単位でマージが出来ない場合は、手作業でのマージとなります。
マージできる例としては、次のようなものがあります。
trunk@120
if(a > b) {
x++;
}
trunk@150
if(a > b) {
y--;
x++;
}
branch-x@150
if(a > b) {
x++;
z = 0;
}
branch-x@マージ結果
if(a > b) { //この行は両方一致
y--; //trunk@150からもってきて追加した
x++; //この行は両方一致
z = 0; //branch-xからもってきて追加した
} //この行は両方一致
マージできない例としては、次のようなものがあります。
trunk@120
if(a > b) {
x++;
}
trunk@150
if((a > b) && (c < 0)) {
y--;
x++;
}
branch-x@150
if((a > b) && (c < b)) {
x++;
z = 0;
}
branch-x@マージ結果
if((a > b) && (c < 0) && (c < b)) { //手作業でマージする必要がある
y--; //trunk@150からもってきて追加した
x++; //この行は両方一致
z = 0; //branch-xからもってきて追加した
} //この行は両方一致
このように、trunkかbranch-xのどっちかの行を組み合わせてマージできない場合は、手作業でマージする必要が出てきます。もちろん、それ以外の場所は極力自動でマージされます。
*** 操作方法 [#s2184d89]
コマンドラインの場合は、svn mergeコマンドを使ってください。
svn merge -r [旧リビジョン]:[新リビジョン] [trunk(URL)] [branch-x(パス)]
です。変更元のtrunkの指定はレポジトリのURLであるのに対し、適用先のbranch-xの指定はローカル作業域へのパスであることに注意してください。
TortoisSVNなら、branch-xフォルダに対して、マージを実行してください。[[http://tortoisesvn.bluegate.org/Help/dailyuseguide.html#Merge]]に、trunkへのマージの仕方がありますので、違いに気をつけながら(今は、branch-xへのマージです)参考にしてください。
Subclipseなら、プロジェクトリストのbranch-xフォルダを右クリックして、Teamからマージを選び、マージ元にtrunkのURLを指定して、リビジョン番号を指定しましょう。
この作業により、ローカルにあるbranch-xの作業領域が更新されます。branch-xをコミットすれば、レポジトリにも反映されます。
** branch-xの機能をtrunkに反映させる [#oe371026]
基本は前述のマージ手順と同じで、対象が逆転しただけです。つまり、今までの説明だと、trunkの変更 =>> branch-x、だったのが、branch-xの変更 =>> trunk、になっただけです。
注意すべき点だけを書いておきます。
- マージの適用先は、ローカルにあるtrunk
- マージの適用元は、レポジトリにあるbranch-x
- マージの開始リビジョンは、branch-xをコピーした時(ブランチを作った時=リビジョン121)
- マージの終了リビジョンは、branch-xを最後に更新したりビジョン(HEADリビジョンでも別に構わない)
ということです。
** 終わりに [#n9a9f5b5]
trunkとbranch-xをそれぞれチェックアウトしたのは、両方の作業を簡単に進められるというだけではなく、trunkの変更を簡単に知ることが出来るように、という意味もあります。
trunkが変更されたことがわかったら、コミットコメントを見て、必要な部分をbranch-xに適用しましょう。バグのあるままbranch-xの開発をしても苦労するだけでしょう。多分。
こまめにマージしてtrunkの変更を取り込んでおけば、最後にtrunkにマージする時に一度にマージ作業をやる手間が省けます。