今さら聞けない svn add の基本と使い方:バージョン管理の第一歩を徹底解説
バージョン管理システムは、ソフトウェア開発をはじめとする様々なプロジェクトにおいて、ファイルの変更履歴を管理し、複数人での共同作業を円滑に進めるための必須ツールです。中でも、Subversion (以下、svn) は、歴史が長く、現在でも多くの現場で利用されています。
Gitのような分散型バージョン管理システムが主流となりつつありますが、集中型であるsvnにも独自の強みがあり、根強いユーザーがいます。特に、既存のプロジェクトがsvnで管理されている場合、svnの基本的な操作は避けて通れません。
svnのコマンドの中でも、新しいファイルやディレクトリをバージョン管理の対象に加えるためのコマンドが svn add
です。このコマンドは、svnを使ったバージョン管理の第一歩とも言える非常に重要なものですが、「今さら聞けない」と感じている方もいらっしゃるかもしれません。
この記事では、svnの基本的な概念に触れつつ、svn add
コマンドに焦点を当て、その目的、基本的な使い方から、様々なオプション、関連するコマンド、よくある疑問やトラブルシューティングまで、徹底的に詳細に解説します。この記事を読めば、svn add
に関するあなたの疑問はきっと解消されるでしょう。
1. なぜ今さら Subversion (svn) なのか?
まず、なぜ今でもsvnが使われているのか、簡単にその背景に触れておきましょう。
1.1. バージョン管理システムとは
バージョン管理システムは、ファイルやディレクトリの変更履歴を記録し、管理するためのシステムです。これにより、以下のようなメリットが得られます。
- 変更履歴の追跡: いつ、誰が、何をどのように変更したかを正確に記録できます。
- 過去の状態への復元: 必要に応じて、過去の任意の状態にファイルを戻すことができます。
- 複数人での共同作業: 同じファイルを同時に編集しても、変更を安全に統合できます。
- 差分の確認: ファイルの変更内容を、過去の状態と比較して確認できます。
1.2. 集中型バージョン管理システム (CVCS) と分散型バージョン管理システム (DVCS)
バージョン管理システムには、主に集中型と分散型があります。
- 集中型 (CVCS): リポジトリ(変更履歴の集中管理場所)が一つ存在し、各ユーザーはリポジトリからファイルを取得し、変更をリポジトリに反映させます。Subversion はこの集中型に分類されます。
- メリット: 管理が容易(サーバーが一箇所)、アクセス権限の管理がしやすい、プロジェクト全体の状態把握が比較的容易。
- デメリット: サーバーが停止すると作業が困難になる、ネットワーク接続が必須(オフラインでのコミットができない)、ブランチやタグの操作が比較的重い。
- 分散型 (DVCS): 各ユーザーがリポジトリ全体の複製をローカルに持ちます。コミットはまずローカルリポジトリに対して行われ、その後必要に応じて他のリポジトリ(通常は共有のセントラルリポジトリ)と同期します。Git はこの分散型に分類されます。
- メリット: オフラインでの作業が可能、コミットやブランチ/タグの操作が高速、ローカルでの試行錯誤が容易。
- デメリット: リポジトリが各所に分散するため管理がやや複雑になる場合がある、大規模なバイナリファイルの扱いに注意が必要な場合がある。
1.3. Subversion (svn) が使われ続ける理由
Gitなどの分散型システムが主流になった現在でも、svnが利用され続けているのは、以下のような理由が挙げられます。
- 歴史的な経緯: 長年使われてきたシステムであり、既存の多くのプロジェクトがsvnで管理されているため、移行コストが高い。
- シンプルさ: 集中型であるため、概念が比較的シンプルで理解しやすいと感じるユーザーもいる。特に、ローカルリポジトリの管理を意識する必要がない点は、初心者にとって扱いやすい場合がある。
- 管理の容易さ: サーバーが集中しているため、管理者にとっては権限管理などが一元的に行いやすい。
- 特定のワークフローへの適合: プロジェクトの性質や組織の文化によっては、集中型のワークフローが適している場合がある。
あなたがsvnプロジェクトに関わることになった以上、svnの基本操作を習得することは必須です。そして、新しいファイルやディレクトリをバージョン管理下に加える最初のステップが svn add
コマンドです。
2. Subversionの基本的な流れと svn add
の位置づけ
svn add
コマンドを理解するためには、svnの基本的なワークフローを把握しておくことが重要です。
2.1. svnの主要な構成要素
- リポジトリ (Repository): プロジェクトの全てのファイルとその変更履歴が保管される中央の保管庫です。通常、サーバー上に配置されます。
- ワーキングコピー (Working Copy): リポジトリの特定のリビジョン(バージョン)のファイル一式を、ローカルコンピュータにチェックアウト(取得)したものです。このワーキングコピー内でファイルの編集作業を行います。
- リビジョン (Revision): リポジトリ全体のスナップショット(ある時点での状態)を識別する番号です。コミットが行われるたびにリビジョン番号は増加します。
2.2. svnの基本的なワークフロー
一般的なsvnのワークフローは以下のようになります。
- チェックアウト (Checkout): リポジトリからワーキングコピーをローカルに取得します。
bash
svn checkout URL [PATH] - 更新 (Update): 他の人がリポジトリにコミットした変更を、自分のワーキングコピーに取り込みます。
bash
svn update [PATH] - 編集 (Edit): ワーキングコピー内のファイルを編集します。ここで新しいファイルを作成したり、既存のファイルを変更したりします。
- 追加 (Add): 新しく作成したファイルやディレクトリを、次にコミットする変更として予約します。 このステップで
svn add
コマンドを使います。
bash
svn add PATH... - 削除/移動/コピー (Delete/Move/Copy): ファイルやディレクトリを削除、移動、コピーする場合、これらの操作もsvnコマンドで行うことで、履歴が正しく管理されます。
bash
svn delete PATH...
svn move SOURCE DEST
svn copy SOURCE DEST - ステータスの確認 (Status): ワーキングコピーでどのような変更が行われたか(変更されたファイル、追加されたファイル、削除されたファイルなど)を確認します。
bash
svn status [PATH...] - 差分の確認 (Diff): ワーキングコピーでの変更内容を、オリジナルの状態と比較して確認します。
bash
svn diff [PATH...] - コミット (Commit): ワーキングコピーで行った変更(ファイルの編集、追加、削除、移動など)をリポジトリに反映させます。これにより、新しいリビジョンが作成されます。
bash
svn commit -m "コミットメッセージ" [PATH...]
2.3. svn add
の役割
上記のワークフローの中で、svn add
は「追加 (Add)」のステップを担当します。
あなたがローカルのワーキングコピー内で新しいファイルやディレクトリを作成しただけでは、それはまだsvnの管理対象ではありません。svn
コマンドにとっては、単に「ワーキングコピー内の管理対象外のファイル」と認識されます。
svn add
コマンドを実行することで、svnに対して「このファイル/ディレクトリを、次のコミットでリポジトリに追加したい」という意図を伝えます。これにより、そのファイル/ディレクトリはバージョン管理下に加えるための予約が行われた状態になります。
重要なのは、svn add
を実行しただけでは、まだリポジトリには何も変更が反映されないということです。変更をリポジトリに反映させるためには、次のステップである svn commit
コマンドを実行する必要があります。
たとえるなら、svn add
は買い物カゴに商品を入れるようなものです。カゴに入れただけではまだ購入は確定していません。レジ(svn commit
)で精算して初めて自分のものになります。
3. svn add
コマンドの基本
それでは、svn add
コマンドの基本的な使い方を見ていきましょう。
3.1. 目的と構文
- 目的: 新しいファイルまたはディレクトリを、バージョン管理下に加えるための予約をします。
- 構文:
bash
svn add PATH...
PATH
には、バージョン管理下に加えたいファイルまたはディレクトリのパスを指定します。複数のパスを同時に指定することも可能です。
3.2. svn add
実行時の挙動
svn add
コマンドを実行すると、主に以下の処理が行われます。
- 追加予約: 指定されたファイルやディレクトリが、ローカルのワーキングコピー内で「追加予約された」状態になります。
- ステータス変更: そのファイルやディレクトリのステータスが
A
(Added) と表示されるようになります。これはsvn status
コマンドで確認できます。 .svn
ディレクトリの更新: svnが内部的に管理している情報(通常、各ディレクトリにある.svn
サブディレクトリ内に格納されています)が更新され、このファイル/ディレクトリが次回のコミットで追加される予定であることが記録されます。- リポジトリへの未反映: 繰り返しになりますが、この時点ではリポジトリ自体にはまだ何も変更は送られていません。 変更はローカルのワーキングコピー内に留まります。
3.3. 具体的な使い方(単一ファイル)
例えば、ワーキングコピーのディレクトリ myproject/src/
の中に、新しく hello.c
というファイルを作成したとします。
myproject/
├── .svn/
└── src/
└── main.c (既存ファイル, バージョン管理下)
ここに hello.c
を新規作成しました。
myproject/
├── .svn/
└── src/
├── main.c
└── hello.c (新規ファイル)
この hello.c
をバージョン管理下に加えたい場合、以下のコマンドを実行します。
bash
cd myproject/
svn add src/hello.c
コマンド実行後、特にエラーが出なければ成功です。
3.4. svn status
での確認
svn add src/hello.c
を実行した後、svn status
コマンドでワーキングコピーの状態を確認してみましょう。
bash
svn status
以下のような出力が表示されるはずです。
A src/hello.c
この A
は “Added” を意味します。つまり、src/hello.c
というファイルがバージョン管理下に追加されることが予約された状態であることを示しています。
もし svn add
を実行する前に svn status
を実行していたら、以下のような出力が表示されていたでしょう。
? src/hello.c
この ?
は “Not versioned” を意味します。つまり、ワーキングコピー内に存在するが、svnの管理下に置かれていないファイルやディレクトリであることを示しています。
svn add
コマンドは、この ?
ステータスのファイルを A
ステータスに変更する役割を果たします。
3.5. svn add
と svn commit
の違い(重要)
svn初心者が最も混同しやすい点の一つが、svn add
と svn commit
の違いです。
svn add
: 新しいファイル/ディレクトリをローカルのワーキングコピー内で、バージョン管理下への追加を予約するコマンドです。この時点ではリポジトリには何も変更されません。svn commit
: ワーキングコピーで行った変更(svn add
で予約した追加、編集、削除、移動など)をリポジトリに反映させるコマンドです。このコマンドによって初めて、新しいファイルがリポジトリに登録され、他の人もそのファイルを取得できるようになります。
したがって、新しいファイルを追加する際は、以下の2段階の操作が必要です。
svn add
で追加を予約する。svn commit
で予約した追加をリポジトリに反映させる。
svn add
を忘れて svn commit
しようとしても、新しく作成したファイルはコミットされません。svn commit
は、あくまで「バージョン管理下のファイルに対する変更」を反映するコマンドだからです。新しく作成したファイルは、svn add
を実行するまではバージョン管理下ではないため、コミットの対象になりません。
4. svn add
の様々な使い方とオプション
svn add
にはいくつかの使い方や、挙動を制御するオプションがあります。
4.1. 複数ファイルの追加
複数の新しいファイルを同時に追加予約したい場合、svn add
コマンドに複数のパスをスペース区切りで指定します。
例えば、src/
ディレクトリに utils.c
と utils.h
という2つの新しいファイルを作成した場合。
bash
svn add src/utils.c src/utils.h
svn status
を確認すると、両方のファイルが A
ステータスになっているはずです。
bash
svn status
A src/utils.c
A src/utils.h
4.2. ディレクトリの追加
新しいディレクトリを作成し、そのディレクトリごとバージョン管理下に加えたい場合も、svn add
コマンドを使用します。
例えば、myproject/tests/
という新しいディレクトリを作成し、その中にテストファイル test_hello.c
を作成したとします。
myproject/
├── .svn/
├── src/
│ ├── main.c
│ └── hello.c
└── tests/ (新規ディレクトリ)
└── test_hello.c (新規ファイル)
ここで、tests/
ディレクトリをバージョン管理下に加えたい場合。
bash
cd myproject/
svn add tests/
このコマンドを実行すると、tests/
ディレクトリだけでなく、そのディレクトリ内にすでに存在する管理対象外のファイル (test_hello.c
) も含めて、再帰的に追加予約されます。
svn status
を確認してみましょう。
bash
svn status
A tests
A tests/test_hello.c
このように、ディレクトリ自身と、その中にあるファイル(またはサブディレクトリ)が同時に追加予約されるのが svn add
のデフォルトの挙動です。これは非常に便利で、新しい機能のために複数のファイルとディレクトリを一度に追加したい場合などに役立ちます。
4.3. 非再帰的な追加 (--non-recursive
/ -N
)
場合によっては、「ディレクトリ自体はバージョン管理下に入れたいが、その中にある既存のファイルやサブディレクトリはまだ追加したくない」ということがあります。例えば、新しいディレクトリ構造だけを先にコミットしておきたい場合などです。
このような場合、--non-recursive
または短縮形の -N
オプションを使用します。
例えば、先ほどの tests/
ディレクトリを、中身の test_hello.c
はまだ追加せずにディレクトリだけ追加予約したい場合。
“`bash
cd myproject/
svn add –non-recursive tests/
または
svn add -N tests/
“`
このコマンド実行後、svn status
を確認してみましょう。
bash
svn status
A tests
? tests/test_hello.c
出力からわかるように、tests
ディレクトリは A
(Added) ステータスになりましたが、その中の test_hello.c
は ?
(Not versioned) のままです。ディレクトリだけが非再帰的に追加予約されたことになります。
--non-recursive
オプションは、ディレクトリに対してのみ意味を持ちます。ファイルに対して指定しても効果はありません(ファイルは常に単体で追加されるため、再帰/非再帰の概念がないからです)。
4.4. 追加するファイルのパターンを指定する (--depth
と svn:ignore
との関連)
svn add
コマンド自体には、特定のパターンに一致するファイル(例: *.log
や *.tmp
)を自動的に除外して追加する直接的なオプションはありません。しかし、関連する機能やワークフローで、意図しないファイルがバージョン管理下に加えられるのを防ぐことができます。
4.4.1. --depth
オプション
--depth
オプションは、svn add
コマンドだけでなく、svn update
, svn checkout
, svn status
など、様々な再帰的な操作コマンドで使用されます。これは、操作の対象とする深さを指定するためのオプションです。
svn add
コマンドで使用する場合、ディレクトリの追加予約の深さを制御できます。
svn add --depth empty mydir/
:mydir/
ディレクトリ自体のみを追加予約します(内容は含まない)。これは--non-recursive
と似た効果になりますが、--depth
はより細かい制御が可能です。svn add --depth files mydir/
:mydir/
ディレクトリと、その直下にあるファイルのみを追加予約します(サブディレクトリやその内容は含まない)。svn add --depth immediate mydir/
:mydir/
ディレクトリと、その直下にあるファイルおよびサブディレクトリ自体を追加予約します(サブディレクトリ内の内容は含まない)。svn add --depth infinity mydir/
:mydir/
ディレクトリと、その中の全てのファイルおよびサブディレクトリを再帰的に追加予約します(これが--recursive
またはオプションなしのデフォルト動作です)。
例として、以下のような構造で、mydir/
ディレクトリを files
の深さで追加予約する場合を考えます。
myproject/
└── mydir/ (新規ディレクトリ)
├── file1.txt (新規ファイル)
├── file2.log (新規ファイル)
└── subdir/ (新規ディレクトリ)
└── file3.txt (新規ファイル)
bash
cd myproject/
svn add --depth files mydir/
svn status
を確認すると、以下のようになるはずです。
bash
svn status
A mydir
A mydir/file1.txt
? mydir/file2.log (拡張子が異なるがファイルなので追加される)
? mydir/subdir (サブディレクトリは追加されない)
? mydir/subdir/file3.txt (サブディレクトリ内のファイルも追加されない)
注意点として、--depth files
は「その深さにあるファイル」を追加予約する指定であり、ファイル名のパターンによるフィルタリングは行いません。上記の例で file2.log
が A
になっているのはそのためです。パターンによる除外は、次に説明する svn:ignore
プロパティの役割です。
4.4.2. svn:ignore
プロパティの活用
特定のファイルやディレクトリをバージョン管理の対象から恒久的に除外したい場合、svn:ignore
プロパティを使用します。これは、svn status
で ?
と表示されるリストから、指定されたパターンに一致するものを非表示にしたり、svn add
コマンドの実行時に誤って追加してしまうのを防ぐのに役立ちます。(厳密には、svn add *
のようなワイルドカードを使った場合に、svn:ignore
の設定を考慮するかどうかはクライアントの実装に依存しますが、一般的には考慮されます)。
例えば、コンパイル生成物 (*.o
, *.exe
) やログファイル (*.log
)、一時ファイル (*.tmp
) などは、通常バージョン管理する必要がありません。これらを間違って svn add
してしまわないように、svn:ignore
を設定しておくと便利です。
svn:ignore
プロパティは、無視したいファイルやディレクトリが存在するディレクトリに対して設定します。
例: myproject/src/
ディレクトリにある *.log
ファイルを無視したい場合。
- 無視するパターンをファイル (
ignore_patterns.txt
など) に記述するか、直接コマンドラインで指定します。
*.log
temp_* - そのパターンを
src/
ディレクトリにsvn propset
コマンドで設定します。
bash
cd myproject/
# ファイルから設定する場合
svn propset svn:ignore -F ignore_patterns.txt src/
# コマンドラインで直接設定する場合(改行区切り)
svn propset svn:ignore "*.log"$'\n'"temp_*" src/
MacやLinuxのBashでは$'\n'
で改行を表現できます。Windowsのコマンドプロンプトでは、改行を含んだ文字列をペーストするなど工夫が必要です。複数行のパターンを扱う場合は、ファイルを指定するのが一般的です。 svn propset
コマンド自体がワーキングコピーの変更なので、これをリポジトリに反映させるためにコミットします。
bash
svn commit -m "Add svn:ignore property to src/" src/
これで、src/
ディレクトリ内に test.log
や temp_output.txt
といったファイルを作成しても、svn status
コマンドで ?
と表示されなくなり、svn add * src/
のようなコマンドでまとめて追加しようとした際にも誤って追加される可能性が低くなります。
もし、svn:ignore
を設定する前に誤って svn add
してしまい、ステータスが A
になってしまった場合は、svn revert
コマンドで追加予約を取り消すことができます。(後述の「追加予約の取り消し」を参照)。
4.5. バイナリファイルの追加
svn add
コマンドは、テキストファイルでもバイナリファイルでも同じように使用できます。svnはファイルの MIME タイプを自動的に検出するか、必要に応じてプロパティ (svn:mime-type
) を設定することで、バイナリファイルを適切に扱います。
バイナリファイル(画像ファイル、実行可能ファイル、圧縮ファイルなど)は、通常差分を取ることができません。svnはバイナリファイルの変更に対しては、ファイル全体を新しいバージョンとしてリポジトリに格納します。テキストファイルの差分管理に比べてリポジトリの容量を消費しやすい傾向があるため、非常に大きなバイナリファイルや頻繁に変更されるバイナリファイルを大量に管理する際には注意が必要です。
svn:executable
プロパティを設定することで、実行可能ファイルとしてマークすることも可能です。(例: svn propset svn:executable ON your_script.sh
)
5. svn add
実行後の状態と次のステップ
svn add
コマンドを実行した後のワーキングコピーの状態と、次に取るべきアクションについて解説します。
5.1. ワーキングコピーの状態を確認する (svn status
)
前述の通り、svn add
実行後の最も重要な変化は、指定したファイルやディレクトリのステータスが A
(Added) になることです。これは svn status
コマンドで確認します。
bash
svn status
出力例:
M src/main.c # 既存ファイルで変更があったもの
A src/hello.c # svn add で追加予約したもの
A tests # svn add で追加予約したディレクトリ
A tests/test_hello.c # ディレクトリ追加時に再帰的に追加予約されたファイル
? build/output.log # ワーキングコピーにあるが未管理のファイル
svn add
したファイルは A
と表示されます。また、svn status
は svn add
されていない未管理のファイル(?
ステータス)も同時に表示してくれます。
5.2. 追加予約を取り消す (svn revert
)
「やっぱりこのファイルはバージョン管理下に加えなくていいや」「間違って追加予約してしまった」という場合、svn add
による追加予約を取り消すことができます。これには svn revert
コマンドを使用します。
bash
svn revert PATH...
例えば、src/hello.c
の追加予約を取り消したい場合。
bash
svn revert src/hello.c
コマンド実行後、svn status
を確認すると、src/hello.c
のステータスが A
から ?
に戻っているはずです。
bash
svn status
M src/main.c
? src/hello.c # 追加予約が取り消された
A tests
A tests/test_hello.c
? build/output.log
svn revert
は、svn add
だけでなく、ファイルの内容変更 (M
) や削除予約 (D
) など、ローカルのワーキングコピーで行った様々な変更を取り消すために使用できる強力なコマンドです。svn revert
は変更内容を破棄するため、使用する際は注意が必要です。ただし、svn add
の revert
は、ファイル自体を削除するわけではなく、あくまで「追加予約」を取り消すだけです。ファイル自体はワーキングコピーにそのまま残ります。
5.3. リポジトリに反映させる (svn commit
)
svn add
で追加予約したファイルやディレクトリを、いよいよリポジトリに反映させます。これには svn commit
コマンドを使用します。
bash
svn commit -m "コミットメッセージ" [PATH...]
コミットメッセージ (-m
オプションに続く文字列)は、そのコミットでどのような変更を行ったのかを簡潔に説明する重要な情報です。必ず分かりやすいメッセージを記述しましょう。
例えば、先ほど svn add
した src/hello.c
と tests/
ディレクトリ(とその中身)をコミットする場合。
bash
cd myproject/
svn commit -m "Add hello.c and test directory for the new feature" src/hello.c tests/
パスを省略して svn commit -m "..."
とだけ実行した場合、ワーキングコピー全体で行われた全ての変更(A
, M
, D
ステータスなど)がコミット対象となります。特定のファイル/ディレクトリだけをコミットしたい場合は、パスを引数に指定します。
svn commit
が成功すると、以下のような情報が表示されます。
Adding src/hello.c
Adding tests
Adding tests/test_hello.c
Transmitting file data ... done
Committing revision XXX.
XXX
は新しく作成されたリビジョン番号です。
5.4. commit
後の状態
svn commit
が成功すると、以下のようになります。
svn add
で追加予約されていたファイルやディレクトリが、正式にリポジトリに登録されます。- ワーキングコピー内のそれらのファイルのステータスが
A
から消え、通常の状態に戻ります(svn status
で何も表示されなくなります)。 - 新しくコミットされたリビジョンが作成され、他のユーザーはそのリビジョンを
svn update
コマンドで取得できるようになります。 - コミット対象外だった未管理ファイル(
?
ステータスのままだったファイル)は、コミット後も?
ステータスのままワーキングコピーに残ります。
6. 実践的なシナリオと応用
svn add
がどのような場面で使われるか、いくつかの実践的なシナリオを見てみましょう。
6.1. 新しいプロジェクトを開始する際の初期コミット
新しいプロジェクトをsvnで管理し始める際、最初に行うのが初期コミットです。
- プロジェクトのルートディレクトリを作成し、その中に管理したいファイルやディレクトリを配置します。
bash
mkdir mynewproject
cd mynewproject
echo "Hello, world!" > main.c
mkdir includes
echo "#include <stdio.h>" > includes/header.h - 空のリポジトリを作成するか、既存のリポジトリ内のパスを使用します。ここでは既存のリポジトリ
svn://server/repo
内のmynewproject
パスを使用するとします。 -
ローカルのディレクトリを、リポジトリの特定のパスにインポート (import) します。インポートは、ローカルのディレクトリ構造を、一度にリポジトリの新しいパスにコピーし、バージョン管理下に置く操作です。この操作は、新規のファイルやディレクトリをリポジトリに追加する特別な
commit
と考えることができます。内部的には、インポート対象の全てのファイルとディレクトリが「追加」として扱われます。
bash
svn import . svn://server/repo/mynewproject -m "Initial import of mynewproject"
このsvn import
コマンドは、ローカルディレクトリ (.
) の内容をリモートのURL (svn://server/repo/mynewproject
) に一括で追加(コミット)します。インポート元ディレクトリは、インポート後もローカルに残りますが、インポートされたファイル自体はバージョン管理下にはなりません。ワーキングコピーを作成するには、改めてsvn checkout
する必要があります。 -
インポートが完了したら、ワーキングコピーを作成します。
bash
cd ..
svn checkout svn://server/repo/mynewproject mynewproject_wc
svn import
はプロジェクトの初期登録に使われることが一般的ですが、既存のワーキングコピー内で新しく大量のファイルやディレクトリを追加したい場合は、通常 svn add
を使います。
6.2. 既存プロジェクトに新機能を追加する
既存のsvnプロジェクトに、新しいファイルやディレクトリを追加しながら機能開発を進めるのは最も一般的なシナリオです。
- 最新のリビジョンにワーキングコピーを更新します。
bash
svn update - 新しい機能に必要なファイルやディレクトリを作成します。
bash
cd myproject/src/
touch new_feature.c
touch new_feature.h
mkdir data
echo "sample data" > data/sample.txt - 作成した新しいファイルやディレクトリを
svn add
で追加予約します。ディレクトリごと追加すれば、中のファイルも同時に予約されます。
bash
svn add new_feature.c new_feature.h
svn add data/ svn status
で追加予約されたことを確認します。
bash
svn status
A src/new_feature.c
A src/new_feature.h
A src/data
A src/data/sample.txt- 必要に応じて、既存のファイルも修正します (
svn add
は不要)。 svn diff
で変更内容を確認します。- 全ての変更(追加したファイル、編集したファイルなど)をコミットします。
bash
svn commit -m "Implement new feature and add related files/directory"
6.3. 誤って svn add
してしまった場合のリカバリ
バージョン管理すべきでないファイル(例: 設定ファイル、ビルド生成物、個人用メモ)を誤って svn add
してしまい、ステータスが A
になってしまった場合。
svn status
で誤ってA
になっているファイルを確認します。
bash
svn status
A my_personal_notes.txt # これを間違えて追加してしまった
A build/output.log # これも間違えて追加してしまった
M src/main.c- これらのファイルの追加予約を
svn revert
で取り消します。
bash
svn revert my_personal_notes.txt build/output.log
確認のプロンプトが表示される場合があります。y
で確定します。
Reverted 'my_personal_notes.txt'
Reverted 'build/output.log' - 再度
svn status
で確認し、A
から?
に戻っていることを確認します。
bash
svn status
M src/main.c
? my_personal_notes.txt # ? に戻った
? build/output.log # ? に戻った
これで、誤って追加予約したファイルがコミット対象から外されました。今後同様のミスを防ぐために、これらのファイルを無視するようにsvn:ignore
プロパティを設定することを検討しましょう。
7. svn add
と関連するコマンド
svn add
は単独で使うだけでなく、他のsvnコマンドと組み合わせてバージョン管理ワークフローを構成します。ここでは、svn add
と特に関連の深いコマンドを改めて整理します。
7.1. svn status
- 役割: ワーキングコピーの状態を表示します。どのファイルが変更されたか (
M
)、追加予約されているか (A
)、削除予約されているか (D
)、競合しているか (C
)、管理対象外か (?
) などを一覧で確認できます。 svn add
との関係:svn add
コマンドの実行結果(ファイルがA
ステータスになったこと)を確認するために必須のコマンドです。また、svn add
すべきファイル(?
ステータス)を見つけるためにも使います。
7.2. svn commit
- 役割: ワーキングコピーで行われた変更(追加、編集、削除、移動など)をリポジトリに反映させ、新しいリビジョンを作成します。
svn add
との関係:svn add
で追加予約されたファイルは、svn commit
を実行することで初めてリポジトリに登録されます。svn add
はコミットのための準備であり、svn commit
はその準備を完了させる最終ステップです。
7.3. svn revert
- 役割: ワーキングコピーで行われたローカルな変更(ファイルの編集内容、追加予約、削除予約など)を取り消し、元の状態に戻します。
svn add
との関係: 誤ってsvn add
してしまったファイルの追加予約を取り消すために使用します。
7.4. svn delete
- 役割: ファイルやディレクトリをバージョン管理下から削除するための予約をします。
svn add
との関係:svn add
が新規ファイルを管理下に入れるのに対し、svn delete
は管理下のファイルを取り除く予約をします。どちらもsvn commit
で確定されます。ローカルでファイルを直接削除しただけでは、svnはそれを「管理下のファイルが見つからない」と認識し、!
ステータスやD
ステータスとして報告することがありますが、正式な削除予約はsvn delete
で行います。
7.5. svn copy
/ svn move
- 役割: バージョン管理下にあるファイルやディレクトリをコピー (
svn copy
) または移動 (svn move
) します。 svn add
との関係:svn copy
やsvn move
コマンドは、内部的に「コピー元/移動元を削除予約」し、「コピー先/移動先を新しいファイルとして追加予約」するような操作を行います。これらのコマンドを使うことで、コピーや移動の履歴がsvnで正しく追跡されるようになります。ローカルでファイルシステム操作(cp
やmv
)でコピー/移動した後で、元のファイルをsvn delete
し、新しいファイルをsvn add
するという手順でも同様の結果を得られますが、履歴を追跡する上ではsvn copy
やsvn move
を使うのが推奨されます。
7.6. svn info
- 役割: ファイルやディレクトリに関する様々な情報を表示します(URL、リビジョン、作者、サイズなど)。
svn add
との関係:svn add
してまだコミットしていないファイルに対してsvn info
を実行すると、リポジトリ上の情報が存在しないため、表示される情報が限定されます(例えばリビジョンなどが表示されない)。これは、そのファイルがまだリポジトリに存在しない、ローカルな追加予約の状態であることを示唆します。
7.7. svn:ignore
プロパティ
- 役割: 特定のディレクトリ配下で、バージョン管理から除外したいファイルやディレクトリのパターンを指定します。
svn add
との関係:svn:ignore
を適切に設定しておくことで、svn status
の表示がクリアになり、svn add *
のような操作で誤って無視すべきファイルを追加してしまうリスクを減らせます。svn:ignore
自体はディレクトリのプロパティとして管理されるため、svn propset
で設定し、その変更をsvn commit
でリポジトリに反映させる必要があります。
これらのコマンドを組み合わせることで、svnを使った効率的かつ安全なバージョン管理ワークフローが実現できます。
8. よくある疑問とトラブルシューティング
svn add
を使う上で、初心者が遭遇しやすい疑問やトラブルについて解説します。
8.1. 「svn add
したのにリポジトリに見えない、他の人が update
しても取得できない」
- 原因:
svn add
はローカルでの追加予約であり、リポジトリへの反映は行いません。リポジトリに反映させるにはsvn commit
が必要です。 - 解決策:
svn status
でファイルがA
ステータスになっていることを確認した後、忘れずにsvn commit -m "コミットメッセージ"
を実行してください。コミットが成功すると、他の人がsvn update
でそのファイルを取得できるようになります。
8.2. 「追加しようとしたらエラーになった」
svn add
時にエラーになる原因はいくつか考えられます。
- 「Entry ‘PATH’ is already under version control」: 指定したファイルまたはディレクトリは、すでにバージョン管理下にある(
A
,M
,D
などのステータスになっている)。既存のファイルを編集する場合はsvn add
は不要です。 - 「Entry ‘PATH’ is not a working copy file」: 指定したパスがワーキングコピー内に存在しない、またはパスの指定が間違っている。現在のディレクトリやファイル名、パスを再度確認してください。
- 親ディレクトリがバージョン管理下にない: svnでは、ファイルやサブディレクトリを追加する前に、その親ディレクトリがバージョン管理下にある必要があります。もし新しいディレクトリ構造を作成してファイルを追加した場合、ディレクトリごと
svn add
するか、先に親ディレクトリをsvn add
してから中のファイルを追加する必要があります。svn add newdir/newfile.txt
と実行した場合、newdir/
がまだ管理下でなければエラーになることがあります。この場合はsvn add newdir/
を実行してからsvn add newdir/newfile.txt
とするか、単にsvn add newdir/
と実行して再帰的に追加するのが簡単です。 - 権限がない: リポジトリに対してコミットする権限がない場合、
svn add
自体はローカル操作なので成功しますが、その後のsvn commit
でエラーになります。しかし、クライアントの設定やリポジトリ側の設定によっては、svn add
の段階で権限エラーに近いメッセージが出ることがないとは言えません。通常はコミット時の問題です。
8.3. 「ディレクトリを追加したら中のファイルも全部追加されてしまった」
- 原因:
svn add
のデフォルトの挙動は再帰的 (--depth infinity
) です。ディレクトリを指定してsvn add
すると、その中のファイルやサブディレクトリも全て追加予約されます。 - 解決策:
- ディレクトリだけを追加したい場合は、
svn add --non-recursive directory/
またはsvn add -N directory/
を使用します。 - 特定の深さまで追加したい場合は、
--depth
オプションを使用します。 - もし既に再帰的に
svn add
してしまったが、一部のファイル/ディレクトリは追加したくなかった場合は、svn revert
コマンドで不要なファイルの追加予約を取り消します。
- ディレクトリだけを追加したい場合は、
8.4. 「特定のファイル(例: *.log
)を追加しないようにしたい」
- 原因:
svn add
コマンド自体にはパターンによる除外機能はありません。svn add *
のようにワイルドカードを使用した場合、ワーキングコピー内の未管理ファイルが全て対象になる可能性があります。(クライアントの実装によりsvn:ignore
を考慮する場合もあります)。 - 解決策:
- 最も推奨される方法は、対象のディレクトリに対して
svn:ignore
プロパティを設定することです。これにより、svn status
で無視すべきファイルが表示されなくなり、svn add *
のようなコマンドでも通常は追加されなくなります。 - 既に
svn add
してA
ステータスになってしまった場合は、svn revert
で取り消します。 - コミット時に特定のファイルを除外したい場合は、
svn commit
コマンドにコミットしたいファイルやディレクトリのパスを明示的に指定します(svn commit file1.c file2.h
のように)。
- 最も推奨される方法は、対象のディレクトリに対して
8.5. 「svn add
を大量に実行してしまった後で、一部だけ commit
したい」
- 原因: 複数のファイルやディレクトリを
svn add
した後、気が変わって一部だけを先にコミットしたくなった。 -
解決策:
svn commit
コマンドは、引数としてコミットしたいファイルやディレクトリのパスを指定できます。パスを指定しなかった場合は、ワーキングコピー全体で行われた全ての変更(A
,M
,D
ステータスなど)が対象となりますが、パスを指定すればそのパス配下の変更だけがコミットされます。
“`bash
# 全てコミットする場合
svn commit -m “Commit all changes”特定のファイルだけコミットする場合
svn commit -m “Commit only new_feature.c” src/new_feature.c
特定のディレクトリ配下の変更だけコミットする場合
svn commit -m “Commit changes in tests/” tests/
``
A
コミットされなかったファイルやディレクトリは、引き続きや
M` などのステータスのままワーキングコピーに残ります。
9. より高度な話題 (簡潔に)
svn add
コマンド自体はシンプルですが、svnにはさらに多くの機能や概念があります。svn add
に直接関連はしませんが、知っておくと役立つ可能性のある話題に簡単に触れておきます。
9.1. プロパティの追加 (svn propset
)
svnでは、ファイルやディレクトリに対してメタデータとして「プロパティ」を設定できます。前述の svn:ignore
もプロパティの一つです。他にも、svn:executable
(実行権限)、svn:mime-type
(MIMEタイプ)、svn:keywords
(特定のキーワードを自動展開)、カスタムプロパティなどがあります。
これらのプロパティは、ファイルやディレクトリがバージョン管理下にあることに関連して設定されるため、svn add
でファイルを追加予約した後や、コミット後に設定することがあります。プロパティの設定自体もワーキングコピーの変更として扱われるため、svn propset
で設定後、svn commit
でリポジトリに反映させる必要があります。
9.2. ロック (svn lock
)
集中型であるsvnでは、排他制御のためにファイルのロック機能があります。あるファイルをロックすると、他のユーザーはそのファイルをコミットできなくなります。これは、バイナリファイルのようにマージが困難なファイルを複数人が同時に編集するのを防ぐのに役立ちます。
新しいファイルを追加する際には、svn add
の時点ではロックは関係ありません。ファイルがリポジトリにコミットされ、バージョン管理下に置かれた後に、必要に応じて svn lock
コマンドでロックします。ロックされたファイルは svn status
で L
ステータスとして表示されます。
9.3. フックスクリプト (Hook Scripts)
svnリポジトリでは、特定のアクション(コミットの前、コミットの後、リビジョンプロパティの変更など)が発生した際に自動的に実行されるスクリプトを設定できます。これらは「フックスクリプト」と呼ばれます。
例えば、pre-commit
フックスクリプトは、コミットがリポジトリに受け付けられる前に実行され、コミットを拒否することができます。これにより、コミットメッセージのフォーマットをチェックしたり、コミットに含まれるファイルの内容を検証したり(例えば、デバッグコードが含まれていないかなど)、意図しないファイルが追加されていないか(例えば、svn:ignore
されるべきファイルが svn add
されていないか)をチェックするルールを設けることができます。
svn add
自体はローカルな操作なのでフックは実行されませんが、svn add
されたファイルを含む svn commit
が行われる際に、pre-commit
フックがそのコミット内容全体を評価する可能性があります。
10. まとめ
この記事では、「今さら聞けない」と感じがちな svn add
コマンドについて、その基本的な使い方から応用、関連コマンド、よくある疑問まで、詳細に解説しました。
svn add
は、新しいファイルやディレクトリをSubversionのバージョン管理下に加えるための最初のステップです。これを実行することで、ローカルのワーキングコピー内で、そのファイルが「次回のコミットで追加される予定」という状態になります (A
ステータス)。しかし、この時点ではまだリポジトリには何も反映されていません。リポジトリへの反映は、必ず svn commit
コマンドで行う必要があります。
svn add
のデフォルト動作はディレクトリに対して再帰的ですが、--non-recursive
や --depth
オプションを使うことで、追加の深さを制御できます。また、バージョン管理すべきでないファイルが誤って追加されるのを防ぐためには、svn:ignore
プロパティの適切な設定が非常に有効です。
もし誤って svn add
してしまった場合は、慌てずに svn revert
コマンドで追加予約を取り消すことができます。
svn add
は svn status
, svn commit
, svn revert
などの他の基本的なコマンドと密接に関連しており、これらのコマンドを理解し組み合わせて使うことで、svnでのバージョン管理ワークフローをスムーズに進めることができます。
この記事を通じて、あなたが svn add
コマンドに自信を持って向き合えるようになり、svnでのファイル管理がより効率的に行えるようになることを願っています。バージョン管理は開発プロジェクトの基盤となる重要なスキルです。一歩ずつ着実に習得していきましょう。