今さら聞けない!Subversion(SVN)の基礎知識と活用法 ~レガシーシステムから新規プロジェクトまで対応できる教科書~
はじめに:なぜ今、Subversion(SVN)なのか?
現代のソフトウェア開発において、バージョン管理システムはなくてはならないツールです。Gitが主流となった今、「バージョン管理システム」と聞いてまずGitを思い浮かべる方が大半でしょう。しかし、プロジェクトによっては、あるいは企業の標準として、今もなおSubversion(以下、SVN)が現役で利用されています。特に、長年運用されているレガシーシステムや、特定の開発環境ではSVNが中心的な役割を果たしているケースが少なくありません。
SVNを使ったことはあるけれど、体系的な知識がないまま「なんとなく」使っている。あるいは、これからSVNを使わなければならない。そんな方のために、この記事ではSVNの基礎から応用、そして運用管理まで、網羅的かつ分かりやすく解説します。この記事を読めば、SVNの基本的な概念を理解し、日々の開発業務で自信を持ってSVNを使いこなせるようになるでしょう。
バージョン管理システムがなぜ必要なのか、そしてSVNがどのように機能するのかをしっかりと学び、あなたの開発スキルをさらに向上させましょう。
第1章:バージョン管理システムとは何か? その必要性
SVNの具体的な話に入る前に、まずはバージョン管理システムというもの全体について理解を深めましょう。
1.1 なぜバージョン管理が必要なのか?
想像してみてください。一人、あるいは複数人で一つのソフトウェアやドキュメントを作成しているとします。時間が経つにつれて、ファイルは何度も修正され、機能が追加され、バグが修正されていきます。この過程で、以下のような問題が発生しがちです。
- 変更履歴が不明確になる: 「あの時どんな変更をしたっけ?」「この機能はいつ誰が追加したんだ?」といった疑問に答えられない。
- 過去の状態に戻せない: 新しい変更を加えたらバグが発生した。以前の安定した状態に戻したいが、どうすれば良いか分からない。
- 複数の人が同時に作業するときの衝突: 同じファイルを複数の人が同時に編集し、お互いの変更を上書きしてしまう。
- 成果物の管理が煩雑になる: ファイル名に日付やバージョン番号(例:
document_v1.0.doc
,document_final_本当にfinal.doc
)を付けて区別するようになり、ファイルが大量に増え、どれが最新か、何が違うのか分からなくなる。
これらの問題は、開発規模が大きくなるにつれて、あるいは参加人数が増えるにつれて深刻化します。手動でのファイルコピーや、共有フォルダでの運用では限界があるのです。
1.2 バージョン管理システムのメリット
バージョン管理システムは、これらの問題を解決するために登場しました。その主なメリットは以下の通りです。
- 変更履歴の自動記録: ファイルやディレクトリに対するすべての変更(追加、削除、修正)が、誰がいつ、どのような意図で行ったのか(コミットメッセージ)とともに自動的に記録されます。これにより、開発の経緯をいつでも追跡できます。
- 過去の任意の状態への復元: 特定の時点(リビジョン)の状態に、いつでも簡単に戻すことができます。これは、バグが発生した場合や、以前の機能に戻したい場合に非常に役立ちます。
- 複数人での並行作業の支援: 同じファイルを複数の人が同時に編集しても、システムが変更の差分を管理し、コンフリクト(競合)が発生した場合はその解決を支援します。これにより、効率的な共同開発が可能になります。
- 分岐(ブランチ)と統合(マージ): メインの開発ラインから一時的に分岐させ、新しい機能の開発やバグ修正を行い、完了したらメインラインに戻す(統合する)ことができます。これにより、メインの開発を止めずに、実験的な作業や並行開発を進めることができます。
- 変更内容の比較: 任意の二つの時点(リビジョン)間、あるいはワーキングコピーとリポジトリの間の変更点を簡単に比較できます。
1.3 バージョン管理システムの分類:集中型と分散型
バージョン管理システムは、そのアーキテクチャによって大きく二つに分類できます。
-
集中型バージョン管理システム(Centralized Version Control System: CVCS):
- リポジトリが中央のサーバーに一つだけ存在します。
- ユーザーはサーバーのリポジトリからファイルを取得し(チェックアウト)、変更を加え、サーバーのリポジトリに変更を送信します(コミット)。
- すべての操作(コミット、更新など)は基本的にサーバーとの通信が必要です。
- 代表的なシステム:Subversion (SVN), CVS (Concurrent Versions System)
-
分散型バージョン管理システム(Distributed Version Control System: DVCS):
- リポジトリが中央だけでなく、各ユーザーのローカル環境にも存在します。
- ユーザーは中央リポジトリを丸ごと複製し(クローン)、ローカルリポジトリで変更履歴を管理します(コミット)。
- ローカルでのコミットはサーバーとの通信なしに行えます。
- 他のユーザーと変更を共有するには、ローカルリポジトリ間のプッシュ/プル操作を行います。
- 代表的なシステム:Git, Mercurial, Darcs
SVNは、このうち集中型バージョン管理システムに分類されます。中央に存在する単一のリポジトリを中心に、すべての開発作業が進められます。このアーキテクチャが、SVNの多くの特徴や操作感に影響を与えています。
第2章:Subversion(SVN)とは? その特徴
2.1 SVNの概要と歴史
Subversionは、Apache Software Foundationによって開発されたオープンソースのバージョン管理システムです。1990年代後半に広く使われていたCVSの後継として設計され、CVSの弱点を克服することを目指して開発が始まりました。特に、CVSでは困難だったファイル名の変更やディレクトリの移動、バイナリファイルの効率的な管理、そして複数の変更をまとめて一つとして記録する「アトミックコミット」などを実現しました。
2004年にバージョン1.0がリリースされて以降、多くの企業やプロジェクトで採用され、集中型バージョン管理システムのデファクトスタンダードとしての地位を確立しました。その後、Gitなどの分散型バージョン管理システムが登場し、近年は主流の座を譲りつつありますが、その安定性、実績、そして集中型ならではのシンプルな管理体制から、今もなお多くの現場で利用されています。
2.2 SVNの基本アーキテクチャ:集中型モデル
SVNは前述の通り、集中型バージョン管理システムです。その核となるのはリポジトリ(Repository)です。
-
リポジトリ(Repository):
- バージョン管理されるすべてのファイルやディレクトリの完全な履歴が格納されている中央のデータベースです。
- 開発の「真実の源泉 (Source of Truth)」として機能します。
- サーバー上に配置されることが一般的です。
- 各コミットはリポジトリ内に新しい「リビジョン(Revision)」を作成します。リビジョンはリポジトリ全体のスナップショットであり、変更が加えられるたびに単調増加する整数(リビジョン番号)で識別されます。
-
ワーキングコピー(Working Copy):
- リポジトリからチェックアウトされた、開発者が実際に作業を行うローカル環境上のファイルやディレクトリのコピーです。
- 開発者はこのワーキングコピー内でファイルの編集、追加、削除などを行います。
- ワーキングコピー内のファイルは、リポジトリの特定のリビジョンの状態に対応しています。
開発者は、サーバー上のリポジトリからワーキングコピーを取得し、ローカルで変更を加え、その変更を再びリポジトリにコミットするというサイクルで作業を進めます。
2.3 SVNの主な特徴
- アトミックコミット(Atomic Commits): 複数のファイルに対する一連の変更を、一つの不可分な操作としてリポジトリにコミットできます。これにより、コミットの途中でエラーが発生した場合でも、リポジトリの状態は変更される前の状態に保たれ、リポジトリの不整合を防ぎます。CVSにはこの機能がありませんでした。
- 効率的なブランチとタグ: SVNでは、ブランチ作成やタグ付けはリポジトリ内でのディレクトリコピーとして実装されます。これにより、非常に高速かつストレージ効率よくブランチやタグを作成できます。ただし、この実装が後のマージ操作をGitなどとは異なるものにしています。
- 履歴の追跡(History Tracking): ファイルやディレクトリの追加、削除、移動、コピーといった操作も含め、すべての変更履歴が正確に記録されます。特に、ファイルの移動やコピー後もその履歴を追跡できる「廉価なコピー (cheap copies)」という機能が優れています。
- バイナリファイル管理の改善: CVSがテキストファイルの管理に特化していたのに対し、SVNはバイナリファイルの差分管理も効率的に行えるように設計されています(ただし、バイナリファイルの差分自体を保存するわけではなく、バージョンごとのファイルを効率的に保存する仕組み)。
- 部分的なチェックアウト: リポジトリ全体ではなく、特定のリポジトリ内のディレクトリだけをワーキングコピーとして取得できます。大規模なリポジトリの一部だけが必要な場合に便利です。
- パスベースの認証: リポジトリ内の特定のパス(ディレクトリやファイル)に対して、ユーザーやグループごとのアクセス権限を細かく設定できます。
これらの特徴は、CVSからの改善点であり、当時の開発環境において大きなメリットをもたらしました。一方、集中型アーキテクチャゆえの限界(オフラインでの作業が難しい、サーバー障害の影響が大きいなど)も存在します。
第3章:SVNの基本操作をマスターする
ここでは、SVNを日常的に利用する上で不可欠な基本的なコマンド操作について説明します。コマンドラインでの操作を基本としますが、多くのGUIクライアントでも同様の操作が行えます。
3.1 リポジトリの作成と構成
まず、バージョン管理の中心となるリポジトリが必要です。サーバー上でリポジトリを作成します。
“`bash
リポジトリを格納するディレクトリを作成
mkdir /path/to/repository/root
リポジトリを作成
svnadmin create /path/to/repository/root/myproject
“`
これにより、/path/to/repository/root/myproject
という名前のリポジトリが作成されます。このディレクトリには、SVNが内部的に利用する様々なファイルやディレクトリ(db
, conf
, hooks
など)が格納されます。
SVNのリポジトリ内では、通常、以下の標準的なディレクトリ構造が推奨されています。
trunk/
: メインの開発ライン(本流)を置く場所です。常に最新の安定版または開発版が置かれます。branches/
: trunkから分岐した開発ブランチや実験的なブランチを置く場所です。tags/
: リリースバージョンなど、特に重要で変更すべきでない時点を記録するためのタグを置く場所です。
この構造を作成するには、リポジトリ作成後に最初のコミットとしてこれらのディレクトリを追加します。
“`bash
リポジトリへのURLを取得 (例: file:///path/to/repository/root/myproject)
または、サーバー経由でのアクセスURL (svn://server/myproject, http://server/myproject など)
一時的にローカルにチェックアウトしてディレクトリを作成し、コミットする
もしくは、svn mkdir -m “Initial layout” URL/trunk URL/branches URL/tags のように直接リポジトリに作成
例:直接作成する場合 (認証設定が必要な場合あり)
svn mkdir -m “Initial layout structure: trunk, branches, tags” \
svn://your_server/myproject/trunk \
svn://your_server/myproject/branches \
svn://your_server/myproject/tags
``
svn://
**注:**や
http://形式のURLでアクセスするには、サーバー側の設定が必要です。ローカルファイルシステム上での練習であれば
file:///` スキームを使います。
3.2 ワーキングコピーの取得:svn checkout
リポジトリから最新のファイルをローカル環境に取得し、作業を開始します。
“`bash
svn checkout svn://your_server/myproject/trunk /path/to/your/working_copy
もしくは svn co svn://your_server/myproject/trunk /path/to/your/working_copy (co は checkout のエイリアス)
“`
このコマンドを実行すると、指定したリポジトリURLの最新リビジョンの内容が、ローカルの指定したディレクトリにコピーされます。このローカルディレクトリがワーキングコピーとなります。ワーキングコピーには、各ディレクトリに隠しディレクトリ .svn
が作成され、SVNがバージョン管理に必要な情報を格納します。
3.3 ファイルの追加:svn add
ワーキングコピー内に新しくファイルやディレクトリを作成した場合、それらをSVNの管理下に置く必要があります。
“`bash
新しいファイルを作成または既存のファイルをワーキングコピーにコピー
例: touch /path/to/your/working_copy/new_file.txt
新しいファイルをSVNの管理下に登録
svn add /path/to/your/working_copy/new_file.txt
新しいディレクトリと中のファイルもまとめて登録
例: mkdir /path/to/your/working_copy/new_dir; touch /path/to/your/working_copy/new_dir/another_file.txt
svn add /path/to/your/working_copy/new_dir
“`
svn add
を実行した時点では、その変更はまだローカルのワーキングコピー内で「追加予定」としてマークされた状態です。リポジトリにはまだ反映されていません。
3.4 ファイルの変更と状態確認:svn status
, svn diff
ワーキングコピー内のファイルに対する変更状況を確認します。
-
状態確認:
svn status
ワーキングコピー内のファイルやディレクトリが、リポジトリの最新状態からどうなっているかを表示します。“`bash
svn status /path/to/your/working_copyまたは、ワーキングコピーのルートディレクトリに移動して
cd /path/to/your/working_copy
svn status
“`
出力例:
M path/to/modified_file.txt # ファイルが変更されている (Modified)
A path/to/added_file.txt # ファイルが追加予定 (Added)
D path/to/deleted_file.txt # ファイルが削除予定 (Deleted)
? path/to/unversioned_file.log # SVNの管理下にないファイル (Unversioned)
! path/to/missing_file.txt # SVN管理下だがワーキングコピーから消えたファイル (Missing)
C path/to/conflicted_file.txt # マージなどで競合が発生したファイル (Conflicted)?
がついているファイルは、svn add
していない新規ファイルです。これらを管理下に置くにはsvn add
が必要です。 -
変更内容の確認:
svn diff
ワーキングコピー内のファイルが、チェックアウトまたは最終更新時(svn update
)のリポジトリの状態からどのように変更されたか(差分)を表示します。“`bash
svn diff /path/to/your/working_copy/modified_file.txtまたは、ワーキングコピーのルートで変更があったファイルをまとめて確認
svn diff
“`
このコマンドは、変更内容を行単位で表示し、追加された行、削除された行などが確認できます。
3.5 変更のリポジトリへの反映:svn commit
ワーキングコピーで行った変更(ファイルの編集、追加、削除など)をリポジトリに記録します。これを「コミット」と呼びます。
“`bash
svn commit -m “ここにコミットメッセージを記述します” /path/to/your/working_copy
または、ワーキングコピーのルートで
svn commit -m “コミットメッセージ”
“`
-m
オプションに続く文字列は、そのコミットで行われた変更の意図や内容を説明する「コミットメッセージ」です。コミットメッセージは、後から変更履歴を確認する際に非常に重要になるため、分かりやすく具体的に記述する習慣をつけましょう。
svn commit
を実行すると、SVNはワーキングコピー内の変更をリポジトリに送信し、新しいリビジョンを作成します。リビジョン番号は1ずつ増えていきます。コミットが成功すると、その変更は他の開発者も利用できるようになります。
重要: SVNのコミットはアトミックです。複数のファイルを同時にコミット対象にしても、すべてが成功するか、すべてが失敗するかのどちらかです。
3.6 リポジトリの最新状態の取得:svn update
他の開発者がリポジトリにコミットした変更を、自分のワーキングコピーに取り込み、最新の状態に更新します。
“`bash
svn update /path/to/your/working_copy
または、ワーキングコピーのルートで
svn update
“`
このコマンドは、ワーキングコピーがチェックアウトしたリビジョン以降にリポジトリに加えられたすべての変更を取得し、ワーキングコピーに適用します。
もし、ローカルで作業中のファイルと、リポジトリから取得した変更が同じ箇所を変更している場合、競合(Conflict)が発生する可能性があります。競合が発生した場合、svn update
はそのファイルを競合状態としてマークし、手動での解決が必要になります(詳細は後述)。
3.7 ファイルの削除:svn delete
ワーキングコピーからファイルを削除し、それをリポジトリにも反映させたい場合に利用します。
“`bash
svn delete /path/to/your/working_copy/file_to_delete.txt
または svn del … (del は delete のエイリアス)
“`
svn delete
を実行すると、ワーキングコピーからファイルが削除され、SVNの状態確認(svn status
)で削除予定(D
)として表示されます。この変更を確定するには、svn commit
が必要です。コミットすることで、そのファイルは指定したリビジョン以降、リポジトリ上でも存在しないことになります(ただし、過去のリビジョンをたどれば復元可能です)。
ワーキングコピーからファイルを単純に rm
コマンドなどで削除しただけでは、SVNはそれを「Missing」(!
)として扱います。この場合、改めて svn delete
で管理下の削除としてマークし直すか、svn cleanup
で修正する必要があります。
3.8 ファイルの移動・コピー:svn move
, svn copy
SVN管理下のファイルやディレクトリを移動したり、コピーしたりする場合に利用します。通常のOSコマンド(mv
, cp
)を使うと、SVNは新しいファイルを「追加」(A
)、元のファイルを「削除」(D
または!
)として扱ってしまい、移動やコピーの履歴として正確に追跡できません。svn move
や svn copy
を使うことで、SVNはその操作を移動またはコピーとして記録し、履歴を正確に追跡できます。
-
移動:
svn move
bash
svn move /path/to/your/working_copy/old_path /path/to/your/working_copy/new_path
# または svn mv ... (mv は move のエイリアス)
移動後、svn status
を見ると、古いパスは削除予定(D
)、新しいパスは追加予定(A
)として表示されますが、これらはペアとして移動(renamed/moved)として扱われます。コミットすることで変更が確定します。 -
コピー:
svn copy
bash
svn copy /path/to/your/working_copy/source_path /path/to/your/working_copy/destination_path
# または svn cp ... (cp は copy のエイリアス)
コピー後、svn status
を見ると、コピー先が追加予定(A
)として表示されます。コミットすることで変更が確定します。svn copy
は、ブランチ作成やタグ付けにも利用される重要なコマンドです。
3.9 変更履歴の確認:svn log
リポジトリに加えられたコミット履歴を確認します。
“`bash
svn log /path/to/your/working_copy
または、ワーキングコピーの特定のファイルやディレクトリの履歴
svn log /path/to/your/working_copy/some_file.txt
または、リポジトリURLを指定して、ワーキングコピーなしで確認
svn log svn://your_server/myproject/trunk
“`
svn log
は、最新のコミットから遡って、各リビジョン番号、コミットしたユーザー、日時、そしてコミットメッセージを表示します。
オプションで表示を絞り込むこともできます。
* -r 開始リビジョン:終了リビジョン
: 指定したリビジョン範囲の履歴を表示
* -l 件数
: 最新から指定した件数だけ表示
* --verbose
(-v
): 変更されたファイルの一覧も表示
3.10 特定のリビジョンの状態確認
SVNでは、リポジトリの任意のリビジョンの状態を参照したり、比較したりできます。
-
特定のリビジョン番号:
リビジョン番号はコミットごとに増える整数で、rN
の形式(例:r100
)で指定します。また、HEAD
というキーワードはリポジトリの最新リビジョンを指します。 -
ワーキングコピーの情報表示:
svn info
ワーキングコピーがリポジトリのどのURL、どのリビジョンに対応しているかなどを確認できます。“`bash
svn info /path/to/your/working_copyまたは svn info /path/to/your/working_copy/some_file.txt
“`
-
特定リビジョンのチェックアウト:
ワーキングコピーを取得する際に、最新ではなく特定のリビジョンを指定して取得できます。bash
svn checkout -r 50 svn://your_server/myproject/trunk /path/to/your/working_copy_r50 -
特定リビジョンの内容表示:
リポジトリ内の特定のファイル、特定リビジョンの内容をワーキングコピーに影響なく表示できます。bash
svn cat -r 50 svn://your_server/myproject/trunk/README.txt -
特定リビジョン間の差分比較:
svn diff -r
任意のリビジョン間の差分を確認できます。“`bash
リビジョン 50 と リビジョン 100 の間の差分
svn diff -r 50:100 svn://your_server/myproject/trunk
または、ワーキングコピーがある場合、ワーキングコピーのベースリビジョンとリビジョン 100 の差分
svn diff -r BASE:100 /path/to/your/working_copy
または、リビジョン 50 の状態とワーキングコピーの状態の差分
svn diff -r 50:HEAD /path/to/your/working_copy
または、リビジョン 50 の状態とワーキングコピーの状態の差分 (HEADは省略可)
svn diff -r 50 /path/to/your/working_copy
“`
第4章:SVNの応用操作:ブランチ、マージ、タグ
SVNの強力な機能であるブランチ、マージ、タグについて詳しく解説します。これらは並行開発やリリース管理に不可欠な機能です。
4.1 ブランチング(Branches)
ブランチとは、メインの開発ライン(通常はtrunk
)から一時的に分岐して、独立した開発ラインを作成することです。
-
なぜブランチが必要か?
- 機能開発: 新しい機能の開発をメインラインに影響を与えずに行うため。開発中にバグを混入させても、メインラインは安定した状態を保てます。
- バグ修正: リリースされたバージョンに対して緊急のバグ修正を行うため。修正完了後、メインラインにも取り込みます。
- 実験: 新しい技術やアイデアを試すため。うまくいかなければ、そのブランチは捨ててしまえば良いだけです。
- バージョン管理: リリースバージョンごとにブランチを作成し、その後の保守開発を独立して行うため。
-
SVNでのブランチ作成:
svn copy
SVNでは、ブランチを作成するためにsvn copy
コマンドを使用します。これは、単にリポジトリ内でディレクトリをコピーしているように見えますが、SVN内部的には「廉価なコピー(cheap copy)」として扱われます。つまり、物理的にすべてのファイルを複製するのではなく、コピー元へのポインタを持つ形で作成されるため、非常に高速かつストレージ効率が良いです。“`bash
trunk の最新状態から新しい機能開発用のブランチを作成
svn copy svn://your_server/myproject/trunk \
svn://your_server/myproject/branches/feature-x \
-m “Create branch for feature X”
“`このコマンドを実行すると、リポジトリの
branches/feature-x
というパスに、trunk
の指定したリビジョン(リビジョン番号を指定しない場合はHEADリビジョン)の内容がコピーされた新しいブランチが作成されます。新しいリビジョンが一つ増えます。
4.2 スイッチング(Switching)
ワーキングコピーは、リポジトリの特定のURL(trunk
、特定のブランチ、特定のタグなど)に対応しています。ワーキングコピーの対象URLを別のものに切り替えるには、svn switch
コマンドを使用します。
“`bash
ワーキングコピーを trunk から feature-x ブランチに切り替える
(ワーキングコピーのルートディレクトリで実行)
svn switch svn://your_server/myproject/branches/feature-x
または svn sw … (sw は switch のエイリアス)
元の trunk に戻す
svn switch svn://your_server/myproject/trunk
“`
svn switch
を実行すると、SVNは現在のワーキングコピーの内容を、切り替え先のURLの最新状態と比較し、差分を適用してワーキングコピーを更新します。これにより、ブランチ間を素早く移動して作業できるようになります。Gitの git checkout
や git switch
に相当する操作です。
4.3 マージング(Merging)
マージとは、あるブランチで行った変更を、別のブランチに取り込む操作です。例えば、機能開発ブランチ(feature-x
)で完了した変更を、メインラインであるtrunk
に取り込む場合などに利用します。
-
SVNでのマージ:
svn merge
SVNのマージ操作は、Gitに比べて少し複雑に感じられることがあります。これは、SVNが変更セット(差分)ではなく、リビジョン範囲をマージの単位として扱うこと、そしてマージ履歴の追跡が明示的に行われる(または行われない)ことに起因します。基本的なマージの考え方:
- マージ先のワーキングコピーを最新にする: マージ操作を行う前に、マージ先のブランチ(例:
trunk
)のワーキングコピーをsvn update
で最新の状態にしておきます。 - マージ元のブランチの変更をマージ先に適用: マージ元のブランチ(例:
feature-x
)で行われた、マージ先にまだ適用されていない変更を、マージ先のワーキングコピーに適用します。 - 競合の解決: もし同じファイルを両方のブランチで変更していて競合が発生した場合、手動で解決します。
- マージ結果のコミット: マージによってワーキングコピーに変更が適用されたら、その結果を
svn commit
します。
マージの主なパターン:
-
特定リビジョン範囲のマージ:
マージ元ブランチの特定のリビジョン範囲で行われた変更を、マージ先ブランチに適用します。これは、特定の機能やバグ修正をピンポイントで取り込みたい場合に使います。“`bash
trunk のワーキングコピーで実行
feature-x ブランチのリビジョン 100 から 150 までの変更を trunk にマージする
(リビジョン 100 から 150 は feature-x ブランチで行われたコミットのリビジョン番号)
svn merge -r 100:150 svn://your_server/myproject/branches/feature-x /path/to/your/trunk_working_copy
または、ワーキングコピーのルートで
svn merge -r 100:150 svn://your_server/myproject/branches/feature-x
“`
-
ブランチ全体の再統合マージ(Reintegrate Merge):
フィーチャーブランチなど、特定の目的のために作成されたブランチでの作業が完了し、そのブランチで行われたすべての変更をメインライン(trunk
)に一度だけ取り込む場合に利用します。SVN 1.5以降で推奨される方法です。“`bash
trunk のワーキングコピーで実行
feature-x ブランチ全体を trunk に再統合する
(feature-x ブランチは、trunk から分岐して以来、trunk にマージされていない変更のみを含む状態である必要がある)
svn merge –reintegrate svn://your_server/myproject/branches/feature-x /path/to/your/trunk_working_copy
または、ワーキングコピーのルートで
svn merge –reintegrate svn://your_server/myproject/branches/feature-x
“`
再統合マージは、そのブランチをマージ元として再度利用することを想定していません(一度再統合したら、そのブランチは役割を終えたと見なされることが多いです)。もしそのブランチで作業を続けたい場合は、
trunk
で行った変更をそのブランチにマージバック(同期)する必要があります。
- マージ先のワーキングコピーを最新にする: マージ操作を行う前に、マージ先のブランチ(例:
-
競合(コンフリクト)の解決
マージやsvn update
の際に、同じファイルで同じ箇所を複数の変更が編集している場合に競合が発生します。SVNは競合が発生したファイルを次のように変更します。- 元のファイルは
.mine
という拡張子でバックアップされます(あなたのワーキングコピーの状態)。 - リポジトリから取得した最新の状態は
.rOLDREV
という拡張子で保存されます(マージ元の変更が適用される前の状態)。 - マージ元ブランチから取得した変更は
.rNEWREV
という拡張子で保存されます(マージ元の変更が適用された後の状態)。 - 元のファイル名(例:
conflicted_file.txt
)は、競合マーカー<<<<<<<
,=======
,>>>>>>>
を含んだ状態で変更されます。
“`
<<<<<<< .mine
あなたの変更
=======
マージ元の変更.rNEWREV
“`競合を解決するには、以下の手順を踏みます。
- 競合マーカーを含むファイルを開き、内容を手動で編集して、望ましい最終的な状態にします。
.mine
,.rOLDREV
,.rNEWREV
ファイルは編集の参考にできます。 -
編集が完了したら、競合を解決済みとしてSVNに伝えます。
“`bash
svn resolve –accept working /path/to/your/working_copy/conflicted_file.txt–accept working オプションは、ワーキングコピー内のファイルを手動で編集した内容で解決することを示します。
“`
-
競合がすべて解決されたら、マージ結果を
svn commit
します。
競合解決には、Merge Toolと呼ばれるGUIツールを利用すると、視覚的に差分を確認しながら解決できて便利です(例: Meld, Beyond Compare, KDiff3など)。SVNクライアント(TortoiseSVNなど)は、これらのツールとの連携機能を持っています。
- 元のファイルは
4.4 タグ付け(Tagging)
タグとは、リポジトリの特定の時点(リビジョン)に名前(タグ名)を付けることです。ブランチと似ていますが、タグは通常、後から変更を加えることを想定しない「静的なスナップショット」として利用されます。
-
なぜタグが必要か?
- リリースバージョンの記録: 製品のリリースバージョン(例: v1.0, v1.1.2)をタグとして記録することで、いつでもそのリリース時点の正確なソースコードを取得できます。
- 重要な状態の記録: マイルストーン達成時や重要な変更を加える直前など、後から参照したい特定の時点を記録するため。
-
SVNでのタグ作成:
svn copy
SVNでは、タグもブランチと同様にsvn copy
コマンドで作成します。対象のブランチやtrunk
から、tags/
ディレクトリ配下にコピーします。“`bash
trunk のHEADリビジョンを v1.0 としてタグ付け
svn copy svn://your_server/myproject/trunk \
svn://your_server/myproject/tags/v1.0 \
-m “Tagging release version v1.0”特定のリビジョン (例: r200) を v0.9.5 としてタグ付け
svn copy svn://your_server/myproject/trunk@200 \
svn://your_server/myproject/tags/v0.9.5 \
-m “Tagging version v0.9.5 (r200)”
``
@リビジョン番号` の形式で、コピー元の特定リビジョンを指定できます。タグは基本的に変更すべきではないため、通常はタグのワーキングコピーをチェックアウトして直接編集することはありません。もしタグに対して修正(例: リリース後のバグ修正)が必要になった場合は、そのタグから新しいブランチを作成して作業するのが一般的なワークフローです。
第5章:SVNの管理と運用
SVNを継続的に利用していく上で、サーバーの管理、バックアップ、権限設定なども重要になります。
5.1 リポジトリのバックアップ戦略
リポジトリは開発履歴のすべてが詰まった非常に重要な資産です。定期的なバックアップは必須です。
-
svnadmin hotcopy
: リポジトリの実行中のコピーを安全に作成できます。最も推奨されるバックアップ方法です。bash
svnadmin hotcopy /path/to/repository/root/myproject /path/to/backup/location/myproject_backup -
svn dump
/svnload
: リポジトリの内容を単一のダンプファイルにエクスポートし、別の場所でインポートすることでリストアや移行を行います。“`bash
ダンプファイルの作成
svnadmin dump /path/to/repository/root/myproject > /path/to/backup/location/myproject.dump
特定リビジョン範囲だけダンプすることも可能: svnadmin dump -r 100:200 …
ダンプファイルからのリストア (新しい空のリポジトリを作成してから)
svnadmin create /path/to/new_repository
svnadmin load /path/to/new_repository < /path/to/backup/location/myproject.dump
“`
これらのツールを組み合わせて、定期的なバックアップを自動化する仕組みを構築することが重要です。
5.2 フック(Hooks)スクリプトの活用
フックとは、リポジトリ上で特定のイベント(例: コミット前、コミット後など)が発生した際に自動的に実行されるスクリプトのことです。リポジトリ/hooks
ディレクトリに配置します。これにより、開発ワークフローに様々な制御や自動化を組み込めます。
一般的なフックの例:
pre-commit
: コミットが実行される前に呼び出されます。コミットメッセージの書式チェック、コミット内容の検証(例: 特定のキーワードが含まれていないか、ビルドが通るかなど)に使用できます。スクリプトがゼロ以外の終了コードを返すと、コミットは拒否されます。post-commit
: コミットが成功した後に呼び出されます。開発者への通知メール送信、CIサーバーへのトリガー、別のシステムとの連携などに使用されます。pre-revprop-change
,post-revprop-change
: リビジョンプロパティ(コミットメッセージなど、コミット後に変更可能なメタデータ)が変更される前後に呼び出されます。リビジョンプロパティの変更はデフォルトでは無効になっているため、これらのフックを設定して変更を許可・制御する必要があります。
これらのフックはシェルスクリプト、Perl、Pythonなどで記述できます。テンプレートが 리포지토리/hooks
ディレクトリに .tmpl
拡張子で用意されています。
5.3 権限管理
SVNでは、リポジトリ全体またはリポジトリ内の特定のパス(ディレクトリやファイル)に対して、ユーザーやグループごとのアクセス権限(読み取り r
, 書き込み w
, アクセス拒否 “)を設定できます。
一般的な権限設定方法:
-
svnserve
を使用する場合:
リポジトリのconf/svnserve.conf
ファイルで認証方法(パスワード認証、SASLなど)を設定し、conf/authz
ファイルでユーザー、グループ、パスごとの権限を設定します。“`ini
authz ファイルの例
[groups]
developers = user1,user2,user3
managers = admin1,admin2[/] # リポジトリ全体
@developers = rw # developers グループは読み書き可能
admin1 = rw # admin1 は読み書き可能
* = r # 上記以外のすべての認証済みユーザーは読み取り専用[myproject:/branches/feature-x] # 特定のブランチ
user2 = rw # user2 はこのブランチで読み書き可能
@developers = r # その他のdevelopersは読み取り専用
“` -
Apache/httpd を使用する場合:
Apacheの設定ファイル(httpd.conf
など)でSVNモジュール(mod_dav_svn
)を有効にし、認証(Basic認証, Digest認証など)と認可(AuthzSVNAccessFile
ディレクティブでauthz
ファイルを指定)を設定します。authz
ファイルの書式はsvnserve
の場合と同じです。
適切な権限設定を行うことで、機密性の高い情報へのアクセスを制限したり、特定のブランチへの書き込み権限を管理したりできます。
5.4 サーバー構成の選択肢
SVNリポジトリをホストする方法にはいくつかの選択肢があります。
svnserve
: SVNに組み込まれている独自の軽量サーバーデーモンです。設定が比較的シンプルで、svn://
プロトコルでアクセスします。小規模なチームや内部利用に適しています。認証にはパスワード認証やSASLを利用できます。- Apache HTTP Server (httpd) と
mod_dav_svn
: ApacheのモジュールとしてSVNを動作させる方法です。http://
またはhttps://
プロトコルでアクセスします。Webサーバーとしての機能(SSL/TLS暗号化、強力な認証・認可オプション、負荷分散など)を利用できるため、大規模な組織やインターネット経由でのアクセスに適しています。 - VisualSVN Server (Windows向け): Windows環境でSVNサーバーを簡単にセットアップできる商用(一部機能は無料版あり)パッケージです。Apacheと
mod_dav_svn
、OpenSSL、認証機能などを統合しており、GUIで設定できます。Windowsサーバーでの運用を検討している場合に便利な選択肢です。
どの方法を選択するかは、運用環境、必要な機能、管理者のスキルなどによって異なります。
5.5 クライアントツールの紹介
SVNを操作するためのクライアントツールは、コマンドライン以外にも多数存在します。GUIツールを利用することで、より直感的で視覚的な操作が可能になります。
- コマンドラインクライアント: SVNの公式クライアントです。すべての操作が可能で、スクリプトとの連携にも適しています。OS(Windows, macOS, Linuxなど)にインストールして使用します。
- TortoiseSVN (Windows向け): Windows Explorerと統合される非常に人気の高いGUIクライアントです。ファイルのアイコンにSVNの状態が表示されたり、右クリックメニューから各種SVN操作(コミット、更新、ログ表示、マージなど)を実行できます。競合解決ツールや差分表示ツールも内蔵・連携できます。
- AnkhSVN (Visual Studio向け): Microsoft Visual Studioに統合されるSVNクライアントです。Visual StudioのIDE内からSVN操作を行いたい場合に便利です。
- IDE統合 (Eclipse, IntelliJ IDEAなど): 多くの統合開発環境(IDE)には、SVNリポジトリと連携するためのプラグインや機能が標準で搭載されています。
これらのツールを組み合わせて、自身の開発スタイルに合った効率的なワークフローを構築できます。
第6章:SVNのメリット・デメリット
Gitと比較されることが多いため、ここではSVNの強みと弱みを整理します。
6.1 SVNのメリット
- シンプルで理解しやすい集中型モデル: 一元化されたリポジトリという概念は直感的で分かりやすく、初心者でも比較的容易に学習・理解できます。Gitのような分散型モデルの複雑さに比べて、シンプルなワークフローを好むチームには適しています。
- 歴史が長く安定している: 長年の運用実績があり、システムとして非常に安定しています。多くの環境で利用されてきたため、関連情報やコミュニティサポートも豊富です。
- バイナリファイルの扱いが得意(Gitに比べて): Gitはファイル内容の差分を格納する設計のため、バイナリファイル(画像、動画、実行ファイルなど)のバージョン管理には向いていません。バージョンごとにまるごと保存するためリポジトリが肥大化しやすい傾向があります。一方、SVNはリビジョンごとにリポジトリ全体の差分を記録する設計であり、バイナリファイルの変更も効率的に(差分ではなくファイル全体を保存しつつも、バージョンツリー内で効率的に管理)扱えます。ゲーム開発やデザイン分野など、バイナリファイルを多く扱うプロジェクトではSVNが好まれる場合があります。
- 部分的なチェックアウトが可能: リポジトリ全体ではなく、必要なディレクトリだけをワーキングコピーとして取得できます。巨大なモノリポジトリ(一つのリポジトリに多くのプロジェクトやコンポーネントが格納されている構造)の一部だけを扱いたい場合に便利です。
- アクセス権限の管理が容易: リポジトリ内のパスごとに詳細な権限設定が可能です。これは、企業などで厳密なアクセス制御が必要な場合に有利です。
6.2 SVNのデメリット
- オフラインでの作業が制限される: コミット、更新、ブランチ作成など、主要な操作は中央リポジトリへの通信が必要です。サーバーが停止している場合やネットワークに接続できない環境では、ほとんどのバージョン管理操作が行えません。
- ブランチ・マージがGitに比べて重い・複雑: ブランチ作成は高速ですが、マージ操作、特に複数ブランチを頻繁に行き来するような開発スタイルには、SVNのマージメカニズムはGitほど洗練されていません。マージ履歴の管理や競合解決がGitに比べて煩雑に感じられることがあります。特にSVN 1.5以前ではマージ履歴の追跡が自動で行われず、マージ漏れや二重マージなどの問題が起こりやすかったため、手動での管理やツールに頼る部分がありました(SVN 1.5以降でマージ追跡機能が改善されています)。
- リポジトリ全体がボトルネックになりうる: すべての操作が中央リポジトリに集中するため、リポジトリサーバーが高負荷になったり、ネットワーク帯域が不足したりすると、開発全体のパフォーマンスに影響が出ます。また、リポジトリの破損は壊滅的なダメージにつながる可能性があります(バックアップは必須です)。
- 履歴の改変が難しい/不可能: 一度コミットされた履歴(リビジョン)は、基本的に変更したり削除したりできません。これは履歴の信頼性を高める一方で、誤ったコミットや機密情報のコミットを取り消すのが非常に困難であることを意味します。
- 分散型に比べて柔軟性に欠ける: Gitのようにローカルリポジトリで自由にコミットやブランチ操作を行い、後から中央リポジトリと同期するといった柔軟なワークフローは実現できません。
第7章:SVNからGitへの移行について(補足)
近年、多くの開発プロジェクトがSVNからGitへ移行しています。その背景には、Gitの分散型モデルがもたらすメリット(オフライン作業、高速な操作、柔軟なブランチ戦略、優れたマージ機能など)があります。
もしあなたが現在SVNを利用していて、将来的にGitへの移行を検討しているのであれば、以下の点を考慮する必要があります。
- なぜ移行するのか? Gitのどの機能が現在の課題を解決するのか、移行によるコスト(学習コスト、移行作業コスト)に見合うメリットがあるのかを明確にします。
- 移行ツールの利用: SVNのリポジトリ履歴をGitリポジトリに変換するためのツール(例:
git-svn
,svn2git
など)が存在します。これらのツールを利用して、既存の履歴を可能な限り引き継ぎながら移行を行います。ただし、SVNとGitではリポジトリ構造や概念が異なるため、完全にそのまま移行できるわけではない点に注意が必要です。特に、SVNのタグやブランチはGitでは異なる形で表現されます。 - 開発ワークフローの変更: Gitの利用にあたっては、SVNとは異なる開発ワークフロー(例: Git-flowなど)を採用することが一般的です。移行に合わせて、チーム全体で新しいワークフローを習得し、適用する必要があります。
- 段階的な移行: 大規模なプロジェクトの場合、一度にすべてを移行するのはリスクが伴います。新規プロジェクトからGitを導入したり、一部のコンポーネントだけを先行して移行したりといった段階的なアプローチも考えられます。
SVNからGitへの移行は、単なるツールの変更ではなく、開発プロセスやチーム文化にも影響を与える大きな変化となり得ます。十分な計画と準備をもって進めることが重要です。
第8章:SVNでよくあるトラブルとその解決策
SVNを利用していると、いくつか典型的な問題に遭遇することがあります。ここでは、よくあるトラブルとその解決策を紹介します。
8.1 競合(コンフリクト)の発生と解決
前述の「マージング」のセクションで詳しく解説しましたが、svn update
や svn merge
の際に発生する競合は最も一般的なトラブルの一つです。
- 問題:
svn update
やsvn merge
を実行した際に、ローカルの変更とリポジトリからの変更が同じ箇所で衝突する。 - 解決策:
svn status
で競合しているファイル(C
と表示される)を確認します。- 競合マーカー(
<<<<<<<
,=======
,>>>>>>>
)が含まれたファイルをテキストエディタで開き、手動で編集して最終的な内容を決定します。必要に応じて.mine
,.rOLDREV
,.rNEWREV
ファイルを参照します。 - 手動での編集が完了したら、
svn resolve --accept working ファイル名
コマンドでSVNに解決済みであることを伝えます。 - すべての競合ファイルを解決したら、
svn status
で競合ファイルがないことを確認し、svn commit -m "Resolved conflicts and merged changes"
のようにコミットします。 - GUIクライアント(TortoiseSVNなど)の競合解決ツールを利用すると、視覚的に解決できて効率的です。
8.2 コミット漏れや更新漏れ
- 問題: 他の人がコミットした最新の変更を反映せずに作業を続けてしまい、後でマージが大変になったり、自分のコミットが古くなってしまったりする。あるいは、自分の変更をコミットし忘れてしまう。
- 解決策:
- 頻繁な
svn update
: 作業を開始する前、そして作業中も定期的にsvn update
を実行し、常に最新のリポジトリ状態に基づいて作業することを心がけましょう。 - コミット前の最終確認: コミットする前に必ず
svn status
で変更内容を確認し、意図しない変更が含まれていないか、すべての必要なファイルが追加・削除・変更対象になっているか確認します。svn diff
で最終的な差分を確認するのも有効です。 - コミット後の確認: コミットが成功したら、
svn log -l 1
などで自分のコミットが最新リビジョンとしてリポジトリに反映されたことを確認しましょう。
- 頻繁な
8.3 認証エラー
- 問題: SVN操作(チェックアウト、コミットなど)を実行しようとした際に、「Authentication failed」や「Authorization failed」といったエラーが表示される。
- 解決策:
- 認証情報の確認: 入力したユーザー名やパスワードが正しいか確認します。誤っている場合は再入力します。GUIクライアントを使用している場合は、保存されている認証情報が古い可能性があります。
- キャッシュされた認証情報のクリア: クライアントによっては、認証情報をキャッシュしています。認証エラーが続く場合は、キャッシュされた認証情報をクリアしてから再度試します(例: TortoiseSVNの設定画面など)。
- サーバー側の設定確認: SVNサーバー側の認証設定(
svnserve.conf
, Apache設定)や、ユーザー、グループ、権限設定(authz
ファイル)に問題がないか、管理者に確認してもらいます。指定されたユーザーに適切な権限が付与されているか確認が必要です。
8.4 リポジトリの破損
- 問題: リポジトリのファイルが何らかの原因(サーバーのクラッシュ、ディスク障害など)で破損し、アクセスできなくなったり、不整合が生じたりする。
- 解決策:
- バックアップからのリストア: これが最も確実な方法です。定期的に取得していた
svnadmin hotcopy
やsvn dump
のバックアップからリポジトリを復元します。だからこそ、定期的なバックアップが非常に重要なのです。 - リポジトリの検証:
svnadmin verify
: リポジトリに論理的な問題がないかチェックできます。破損が疑われる場合はまずこれで検証します。 - リポジトリの回復:
svnadmin recover
: 一部の軽微な破損であれば、このコマンドで回復できる可能性があります。ただし、必ず成功するわけではありません。 - 専門家への相談: 重大な破損の場合は、自力での復旧が難しい場合があります。SVNに詳しい専門家やコミュニティに相談することも検討します。
- バックアップからのリストア: これが最も確実な方法です。定期的に取得していた
第9章:まとめ:SVNとの付き合い方
この記事では、SVNの基礎から応用、管理、トラブルシューティングまでを網羅的に解説しました。
SVNは集中型バージョン管理システムとして、Gitとは異なるアーキテクチャと操作感を持っています。Gitが普及した今でも、その安定性、バイナリ管理の得意さ、そして既存プロジェクトでの継続利用といった理由から、多くの現場で利用され続けています。
「今さら聞けない」と思っていても、SVNの基本的な概念(リポジトリ、ワーキングコピー、リビジョン)や、主要なコマンド操作(チェックアウト、更新、コミット、追加、削除、移動、コピー、ログ)をしっかりと理解していれば、日々の業務で困ることはほとんどありません。さらに、ブランチ、マージ、タグといった応用操作、そして権限管理やバックアップといった管理の基礎を知っていれば、SVNプロジェクトでより効率的に、そして安心して作業を進めることができるでしょう。
Gitと比較した場合のメリット・デメリットを理解することも重要です。ツールにはそれぞれ得意・不得意があります。プロジェクトの特性やチームの状況に合わせて、最適なバージョン管理システムを選択したり、あるいは両方のシステムを併用したりすることが、現代の開発環境においては現実的なアプローチとなります。
もしあなたが現在SVNを使っているのであれば、この記事を参考に、今一度基本的な操作や概念を確認してみてください。そして、もし可能であれば、あなたのチームやプロジェクトでのSVNの運用方法(ディレクトリ構成、ブランチ戦略、フックの活用状況など)について、他のメンバーと情報共有し、より良いプラクティスを模索していくことをお勧めします。
バージョン管理システムは、あなたのコードやドキュメントの歴史を守り、チームメンバーとの協力を円滑にするための強力なツールです。SVNの知識を深め、それを最大限に活用してください。
この記事が、あなたのSVN理解の一助となれば幸いです。