分散バージョン管理システムつかってますか?
世の中ではgitやhgなどの分散型のバージョン管理システムが流行していて、「もうsvnなんて、、、」「まだsvnつかっているの、、、」という風潮になっています。
弊社内でもgitのレポジトリが立ったり、svnのプロジェクトでも自分の環境だけはgit-svnで分散バージョン管理を使う人が増えています。
「自分の環境だけはgit-svnで」。そう、社内ではまだまだsvnを使っているプロジェクトが多いのです。「日本語のファイル名が使えない」「デザイナーさんに使ってもらうためのわかりやすいクライアントが無い」「svnからなかなか移行するコストが、、」などの理由でsvnを使い続けているプロジェクトも多いと思います。
というわけで、分散バーション管理システムではなく社内で運用されているsvnでのブランチマネジメントについて、備忘録もかねて説明します。
次の様な前提で話をします。
説明する構成はこちら。
小規模なプロジェクトや、保守の少ないプロジェクトでよく見られます。
trunkで開発ないし保守を行い、リリース時にタグを打ちます。
o (tags/release_2010_12_10)
|
| o (tags/release_2010_12_13)
| |
v v
o----o----o----o----o----o----o----o (trunk)
という状況で利用します。
o (tags/release_2010_12_10)
|
| o (tags/release_2010_12_13)
| |
v v
o----o---------o (branches/release_2010_12_10)
/
/
o----o----o----o----o (trunk)
ブランチマネージャというブランチを管理する役割をたてます。
releaseしたアプリケーションの修正はreleaseブランチに対して行います。
releaseの修正とtrunkで取りこぼさないために、ブランチマネージャはrelaseブランチに発生した修正をtestingにマージします。trunkにマージします。(2024/07/25 編集部訂正)
cd trunk
svn merge -r A:C svn+ssh://hostname/path/to/svn/repos/branches/release_2010_12_10
o (tags/release_2010_12_10)
|
| o (tags/release_2010_12_13)
| |
v v
A----B---------C (branches/release_2010_12_10)
/ \
/ \ B-Cをマージ
o----o----o----o----o-----o (trunk)
最近のsvnではmergeinfoというマージの情報が記録されます。マージ漏れを防ぐためにB-Cのように、常に-でつなぐ形になるようにしましょう。
svn proplist -v .
'.' の属性:
svn:mergeinfo
/branches/release_2010_12_10:B-C
など、何らかの理由releaseで作業ができない場合はtrunkに修正を入れ、その修正をreleaseブランチにマージバックする場合もあります。
この場合、修正の数に比例して(releaseブランチの品質が低いほど)ブランチマネージャの負担が増加します。
o (tags/release_2010_12_10)
|
| o (tags/release_2010_12_13)
| |
v v
o------------------o (branches/release_2010_12_10)
/
/
/
/ o--------o-------o----o-----------o--------o (branches/testing_2010_12_20)
/ /
/ /
/ /
o----o----o----o----o------------o-----------------o------------o (trunk)
この構成の場合のブランチのメンテナンスは二通りあります。
「trunk + release ブランチ」の場合のメンテナンス方法をそのまま適応したパターンです。
releaseの修正はreleaseにコミット。testingの修正はtestingにコミットし、ブランチマネージャは
「release -> testing」のマージ、「testing -> trunk」のマージを順番に行う必要があります。
releaseの修正をtestingにコミットし、特定のリビジョンをブランチマネージャがreleaseにマージバックするパターンです。ブランチマネージャは「testing -> trunk」のマージだけを気にすればよく、順番に依存する事は無くなります。
マージの回数は増えますが、releaseには数コミットずつのマージしか発生しないため、衝突の解決が簡単になります。
testingをリリースする場合は、testing_2010_12_20をrelease_2010_12_20にリネームします。
その瞬間前リリースブランチのrelease_2010_12_10は役目を終え、メンテナンスを終了します。
svn mv svn+ssh://hostname/path/to/svn/repos/branches/testing_2010_12_20 \
svn+ssh://hostname/path/to/svn/repos/branches/release_2010_12_20
o (tags/release_2010_12_10)
|
| o (tags/release_2010_12_13) o (tags/release_2010_12_20)
| | |
v v v
o------------------o (branches/release_2010_12_10) o (branches/release_2010_12_20)
/ /
/ /
/ /
/ o--------o-------o----o-----------o--------o (branches/testing_2010_12_20)
/ /
/ /
/ /
o----o----o----o----o------------o-----------------o------------o (trunk)
期日までに開発が終わらなくなってしまった場合にtestingブランチを延命する事があります。
svn cp svn+ssh://hostname/path/to/svn/repos/branches/testing_2010_12_20 \
svn+ssh://hostname/path/to/svn/repos/branches/testing_2010_12_30
svn mv svn+ssh://hostname/path/to/svn/repos/branches/testing_2010_12_20 \
svn+ssh://hostname/path/to/svn/repos/branches/release_2010_12_20
o (tags/release_2010_12_10)
|
| o (tags/release_2010_12_13) o (tags/release_2010_12_20)
| | |
v v v
o------------------o (branches/release_2010_12_10) o (branches/release_2010_12_20)
/ /
/ /
/ /
/ o--------o-------o----o-----------o--------o (branches/testing_2010_12_20)
/ / \
/ / o (branches/testing_2010_12_30)
/ /
o----o----o----o----o------------o-----------------o------------o (trunk)
「ある機能を実装するが、他の人のコミットに左右されたくない」という場合に利用します。
ある機能を入れたいブランチ(たとえばtrunk)から自分用のブランチを作成し、作業が完了したら分岐元のブランチにマージします。
svn cp svn+ssh://hostname/path/to/svn/repos/trunk \
svn+ssh://hostname/path/to/svn/repos/branches/troter/working \
-m "troter用の作業ブランチ"
# 作業ブランチにスイッチ
svn sw svn+ssh://hostname/path/to/svn/repos/branches/troter/working
# 何か作業してコミット
emacs xxx; svn ci -m "hoge";
# 分岐元にスイッチ
svn sw svn+ssh://hostname/path/to/svn/repos/trunk
# 作業ブランチでの変更をマージ
svn merge -r n:m svn+ssh://hostname/path/to/svn/repos/branches/troter/working
# コミット
svn ci -m "○○を実装"
# 用が済んだら消しましょう。
svn rm svn+ssh://hostname/path/to/svn/repos/branches/troter/working
個人用の作業ブランチは人を主軸に置いた考えですが、人ではなく機能に主軸を置くとトピックブランチになります。ある機能を実装するためだけにブランチを作成します。
イシュートラッカー(trac、redmine)などのイシューの番号をブランチ名にするとわかりやすいです。
svn cp svn+ssh://hostname/path/to/svn/repos/trunk \
svn+ssh://hostname/path/to/svn/repos/branches/issue/2010 \
-m "#2010 ○○機能の実装"
実装できたら個人用の作業ブランチと同じように分岐元に変更をマージします。
ブランチマネージャの立場を考えると、trunk + releaseブランチしか存在しない瞬間に行ってほしいです。
それ以外のタイミングで行うとコンフリクトの解決が大変です。
testingとtrunkが乖離しないように頻繁にマージを行った方がよいです。
bugfixがメインの状態であれば40リビジョンくらいのマージでもそれほど苦労はありません。
開発がメインでどんどん変更される場合は15位を目安にマージした方がよいと思います。
ブランチの運用に困っている人に参考になれば幸いです。