svn upの基本を理解しよう!コマンドの使い方を徹底解説


svn up の基本を理解しよう!コマンドの使い方を徹底解説

ソフトウェア開発やドキュメント作成において、複数人で一つのプロジェクトを進める際には、バージョン管理システムが不可欠です。Subversion (SVN) は、長年にわたり多くの現場で利用されてきた分散型ではない中央集権型のバージョン管理システムの一つです。そのSVNにおいて、日常的に最も頻繁に使用されるコマンドの一つが svn up です。

svn up コマンドは、あなたの作業ディレクトリ(ワーキングコピー)をリポジトリの最新の状態に更新するために使われます。しかし、単に「最新にする」だけでなく、特定のリビジョンに戻したり、更新する範囲を指定したり、競合を自動的に解決したりするなど、様々な高度な機能を持っています。

この記事では、svn up コマンドの基本的な使い方から、知っておくと便利なオプション、トラブルシューティング、そして他のコマンドとの連携まで、網羅的に解説します。これを読めば、svn up コマンドを完全に理解し、より安全かつ効率的にSVNを活用できるようになるでしょう。

Subversion (SVN) の基本

svn up コマンドを理解するためには、まずSVNの基本的な概念を把握しておく必要があります。

リポジトリとワーキングコピー

SVNはクライアント・サーバーモデルを採用しています。

  • リポジトリ (Repository): プロジェクトのすべてのファイルと、それらの変更履歴(バージョン履歴)が集中管理されている場所です。通常、サーバー上に置かれます。リポジトリはプロジェクトの「真実の源泉」であり、すべての変更は最終的にここに保存されます。
  • ワーキングコピー (Working Copy): リポジトリからチェックアウト(取得)した、ユーザー個人の作業用のディレクトリです。ワーキングコピーには、リポジトリの特定のリビジョン時点でのプロジェクトのファイル一式が含まれています。ユーザーはワーキングコピーでファイルの編集や追加、削除などの作業を行います。

開発者は、リポジトリからワーキングコピーを取得し、そこで作業を進めます。作業が完了したら、変更内容をリポジトリにコミット(送信・登録)します。他の開発者の変更を取り込む際は、svn up コマンドを使用してワーキングコピーを更新します。

SVNの基本的なワークフロー

SVNを使った開発の基本的なワークフローは以下のようになります。

  1. Checkout: プロジェクトを開始する際や、初めてSVNを利用する際に、リポジトリからプロジェクト全体または一部をローカルマシンに取得し、ワーキングコピーを作成します (svn checkout)。
  2. Edit: ワーキングコピーで、ファイルを編集したり、新しいファイルを追加したり、不要なファイルを削除したりします。
  3. Update: 他の人がリポジトリにコミットした変更を、自分のワーキングコピーに取り込みます (svn update または svn up)。これはコミットする前に行うのが一般的です。
  4. Review (Optional): 自分の変更点や、svn up で取り込んだ他の人の変更点を確認します (svn status, svn diff)。
  5. Resolve Conflicts (If necessary): svn up によって自分の変更と他の人の変更が衝突した場合、競合を手動またはツールを使って解決します。
  6. Commit: 自分のワーキングコピーでの変更内容をリポジトリに送信し、新しいリビジョンとして登録します (svn commit)。

このサイクルのステップ3にあたるのが svn up です。

なぜ svn up が必要か?

SVNは中央集権型であるため、複数の開発者が同時に同じファイルを作業することがよくあります。誰か一人が変更をリポジトリにコミットしても、他の人のワーキングコピーは自動的には更新されません。

svn up を実行することで、あなたのワーキングコピーがリポジトリの最新の状態に同期されます。これにより、他の開発者が行った変更を自分の作業に取り込むことができます。これは、以下のような目的で重要です。

  • 他の開発者の作業を取り込む: チームメンバーがコミットした新機能やバグ修正を自分の環境に反映させ、自分の作業に組み込むため。
  • 競合 (コンフリクト) を検出・解決する: 自分が変更した箇所と、他の人が変更した箇所が同じ場合、コンフリクトが発生します。svn up を実行することでコンフリクトが検出され、コミットする前に解決することができます。コミット前にコンフリクトを解決しておくことは、他の人にとって負担を減らし、安全な開発を進める上で非常に重要です。
  • 最新の環境で作業する: プロジェクトは常に変化しています。最新の環境で作業することで、古いコードベースに対する作業による無駄や、他の人との不整合を防ぐことができます。
  • 過去のリビジョンに戻る: 特定のバグが発生したリビジョンを特定したり、古いリリースバージョンのコードを確認したりするために、ワーキングコピーを過去の状態に戻すことができます。

特に、コミット前に必ず svn up を実行するという習慣は、SVNを利用する上での「黄金律」と言われるほど重要です。これにより、自分の変更をコミットする際に不要な競合発生を防ぎ、円滑なチーム開発を促進します。

svn up コマンドとは?

改めて、svn up (または svn update) コマンドは、ワーキングコピー内のファイルとディレクトリを、リポジトリの特定のリビジョン、通常は最新のリビジョンに同期させるために使用されます。

このコマンドは、ワーキングコピーの各アイテムについて、リポジトリと比較し、以下の処理を行います。

  1. 追加: リポジトリには存在するが、ワーキングコピーには存在しないファイルやディレクトリを、ワーキングコピーに追加します。
  2. 削除: リポジトリから削除されたファイルやディレクトリを、ワーキングコピーからも削除します。
  3. 更新: リポジトリで変更されたファイルを、ワーキングコピーで同じパスにあるファイルの内容で置き換えます。
  4. 競合の検出: ワーキングコピーでローカルに変更が加えられているファイルが、リポジトリでも他の人によって変更されていた場合、競合が発生します。svn up はこれを検出し、ユーザーに通知します。
  5. プロパティの更新: ファイルの内容だけでなく、svn:ignore, svn:executable といったSVNプロパティも更新します。

これらの処理を経て、ワーキングコピーは指定されたリビジョン(通常は最新)の状態になります。

svn up の基本的な使い方

まずは最も基本的で、日常的に使うことの多い svn up の使い方を見ていきましょう。

シンプルな更新: ワーキングコピー全体

ワーキングコピーのルートディレクトリ(svn checkout したディレクトリの最上位)に移動して、引数なしで svn up を実行すると、ワーキングコピー全体がリポジトリの最新リビジョンに更新されます。

bash
$ cd /path/to/your/workingcopy
$ svn up

このコマンドを実行すると、SVNはリポジトリに接続し、ワーキングコピーの状態とリポジトリの最新の状態を比較します。そして、必要な変更(ファイルの追加、削除、更新、プロパティの更新など)をローカルのワーキングコピーに適用します。

特定のパスだけを更新

svn up コマンドには、引数として特定のファイルやディレクトリへのパスを指定することができます。これにより、ワーキングコピー全体ではなく、指定したパス以下のアイテムだけを更新することが可能です。

“`bash

特定のファイルを最新に更新する

$ svn up path/to/your/file.txt

特定のディレクトリ以下を最新に更新する

$ svn up path/to/your/directory/
“`

これは、大規模なプロジェクトでワーキングコピー全体を更新するのに時間がかかる場合や、特定のファイルやディレクトリに関連する作業のみを行いたい場合に便利です。

パスを指定しない場合は、カレントディレクトリ(コマンドを実行したディレクトリ)以下のアイテムが更新対象となります。ワーキングコピーのルートディレクトリで実行すれば全体が更新され、ワーキングコピー内のサブディレクトリで実行すれば、そのサブディレクトリ以下のみが更新されます。

svn up の出力の見方

svn up コマンドを実行すると、SVNは更新されたファイルやディレクトリのリストを表示します。各アイテムの行頭には一文字のステータスコードが表示され、そのアイテムに対してどのような操作が行われたかを示します。主なステータスコードは以下の通りです。

  • U: Updated (更新) – ファイルの内容がリポジトリの最新の内容に更新されました。ローカルでの変更はなかったか、ローカルの変更とリポジトリの変更が衝突せずにマージされました。
  • A: Added (追加) – リポジトリには存在したが、ワーキングコピーには存在しなかったファイルやディレクトリが追加されました。
  • D: Deleted (削除) – リポジトリから削除されたファイルやディレクトリが、ワーキングコピーからも削除されました。
  • C: Conflict (競合) – ワーキングコピーでローカルに変更が加えられていたファイルが、リポジトリでも他の人によって変更されており、その変更が衝突しました。手動での解決が必要です。
  • G: Merged (マージ) – ワーキングコピーでローカルに変更が加えられていたファイルに、リポジトリの変更が自動的にマージされました。競合は発生しませんでした。GU の一種ですが、ローカルに変更があった場合に区別して表示されることがあります。
  • E: Existed (既に存在) – リポジトリから追加されるべきアイテムが、ワーキングコピーに既に存在していました。通常は問題ありません。
  • R: Replaced (置換) – ファイルが削除され、同じパスで新しいファイルが追加されました。内部的には一つの操作として扱われます。
  • _ (スペース): No Change (変更なし) – アイテムは最新であり、変更は必要ありませんでした。

例えば、以下のような出力が表示されることがあります。

Updating '.':
U path/to/file_a.txt
A path/to/new_directory/
A path/to/new_directory/file_b.txt
D path/to/old_file.txt
C path/to/conflict_file.txt
G path/to/merged_file.txt
Updated to revision 1234.

この例では、file_a.txt が更新され、new_directory/ とその中の file_b.txt が追加され、old_file.txt が削除されました。また、conflict_file.txt では競合が発生し、merged_file.txt ではローカルの変更とリポジトリの変更が自動的にマージされたことがわかります。最後に、ワーキングコピーがリビジョン 1234 に更新されたことが示されています。

C が表示された場合は、競合が発生しているため、そのファイルを編集して手動で競合を解決する必要があります。競合の解決方法については後述します。

svn up の詳細な使い方:オプション解説

svn up コマンドには、その動作を細かく制御するための多くのオプションが用意されています。これらのオプションを使いこなすことで、より柔軟かつ強力にバージョン管理を行うことができます。

特定リビジョンへの更新 (-r)

--revision または -r オプションを使用すると、ワーキングコピーをリポジトリの最新の状態ではなく、特定の過去のリビジョンに更新することができます。

構文は以下の通りです。

bash
$ svn up -r REV [PATH...]

REV には、リビジョンを指定する方法がいくつかあります。

リビジョン番号で指定

最も一般的なのは、特定のリビジョン番号(例えば 1234)を指定する方法です。

“`bash

ワーキングコピー全体をリビジョン 1234 の状態にする

$ svn up -r 1234

特定のファイルのみをリビジョン 567 の状態にする

$ svn up -r 567 path/to/some_file.txt
“`

これにより、ワーキングコピーの状態が、指定したリビジョン番号の時点でのリポジトリの状態と一致するように変更されます。

日付で指定

特定の日付と時刻の時点でのリポジトリの状態に更新することもできます。日付の指定には、ISO 8601 形式を使用するのが一般的です。

“`bash

2023年10月27日午前9時00分00秒 (UTC) の状態に更新

$ svn up -r “{2023-10-27T09:00:00Z}”

タイムゾーンを指定しない場合はローカルタイムが使用されることが多いが、UTC推奨

$ svn up -r “{2023-10-27T18:00:00}” # ローカルタイムが考慮される
“`

日付の指定は、特定のリリース日時点のコードを確認したい場合などに便利です。日付文字列は {} で囲む必要があります。

キーワードで指定

SVNには、特定のリビジョンを指すための特別なキーワードがいくつか用意されています。

  • -r HEAD: リポジトリ内の最新のリビジョン。-r HEAD を指定して svn up を実行するのは、引数なしで svn up を実行するのと基本的に同じです。
  • -r BASE: 指定したパスまたはカレントディレクトリのワーキングコピーのベースリビジョン。これは、最後にワーキングコピー全体を更新したときのリビジョンや、特定のアイテムをチェックアウトしたときのリビジョンなど、そのアイテムがリポジトリから取得された際のリビジョンを指します。
  • -r COMMITTED: 指定したパスまたはカレントディレクトリのアイテムが最後にコミットされたリビジョン。
  • -r PREV: COMMITTED の一つ前のリビジョン。

これらのキーワードを使うと、特定の時点からの変更を取り消したり(-r PREV)、ワーキングコピーの状態を過去のある時点に戻したりするのに便利です。

“`bash

ワーキングコピー全体を、最後に更新した時の状態に戻す

$ svn up -r BASE

特定のファイルを、そのファイルが最後にコミットされた時の状態に戻す

$ svn up -r COMMITTED path/to/file.txt
“`

過去のリビジョンへの更新の注意点

svn up -r OLD_REV を実行してワーキングコピーを過去の状態に戻した場合、そのワーキングコピーは一時的に「古い」状態になります。この状態でファイルに変更を加えて svn commit を実行すると、その変更はリポジトリの HEAD リビジョンに対して行われます。つまり、過去のリビジョンを直接編集してその歴史を改変するわけではありません。

過去のリビジョンに戻す操作は、主に以下の目的で行われます。

  • 特定の時点でのコードの状態を確認する。
  • 過去のバグがどのリビジョンで発生したかを特定する。
  • 特定の過去の機能実装を確認する。

もし、過去のリビジョンで行われた変更を取り消したい場合は、svn up -r PREV file.txt のようにしてファイルの内容を過去の状態に戻し、その状態を改めて svn commit する必要があります。これは、svn revert コマンド(ローカルでの未コミットの変更を取り消すコマンド)とは目的が異なる点に注意が必要です。svn revert はワーキングコピーのローカルでの編集内容をリポジトリのベースリビジョンに戻すコマンドであり、他の人のコミットを取り消すものではありません。他の人のコミットを取り消す場合は、svn merge -c -REV URL (リバースマージ) を使用するのがより一般的な方法です。

更新の深さを制御 (–depth)

SVNでは、ワーキングコピーを作成したり更新したりする際に、ディレクトリの深さを指定できます。これは、プロジェクトの一部だけが必要な場合や、大規模なプロジェクトで不要なサブディレクトリをチェックアウト・更新しないようにしたい場合に役立ちます。svn up でも --depth オプションを使用できます。

構文は以下の通りです。

bash
$ svn up --depth ARG [PATH...]

ARG には以下のいずれかの値を指定します。

デフォルトの動作 (–depth infinity)

引数なしの svn up--depth infinity は、指定したパス(またはカレントディレクトリ)以下のすべてのファイルとサブディレクトリを再帰的に更新します。これが通常の動作です。

“`bash

ワーキングコピー全体を完全に更新する (デフォルト)

$ svn up –depth infinity
“`

直下のみ (–depth immediates)

指定したディレクトリ直下のファイルとサブディレクトリは更新しますが、サブディレクトリの中身は更新しません。サブディレクトリ自体はワーキングコピーに作成されますが、内容は空になります。

“`bash

src ディレクトリ直下のファイルとサブディレクトリは更新するが、その中身は更新しない

$ svn up –depth immediates src/
“`

ディレクトリ構造だけ把握したい場合や、必要なサブディレクトリだけを後から svn up で深く取得したい場合に便利です。

ファイルのみ (–depth files)

指定したディレクトリ直下のファイルのみを更新します。サブディレクトリはワーキングコピーに作成されません。

“`bash

doc ディレクトリ直下のファイルのみを更新し、サブディレクトリは作成しない

$ svn up –depth files doc/
“`

特定のディレクトリにあるドキュメントファイルだけを最新にしたい場合などに使えます。

空のディレクトリのみ (–depth empty)

指定したディレクトリ自体はワーキングコピーに作成・更新されますが、その中身(ファイルやサブディレクトリ)は一切更新されません。

“`bash

images ディレクトリ自体はワーキングコピーに作成するが、中身は空にする

$ svn up –depth empty images/
“`

これは、チェックアウト時に特定の巨大なディレクトリ(例: バイナリファイルがたくさん含まれるディレクトリ)の中身を取得しないようにするために --depth empty でチェックアウトしておき、後から必要になったサブディレクトリだけを --depth infinity で更新する場合などに使用できます。

非再帰的な更新 (-N)

--depth immediates と似ていますが、-N オプションは指定したディレクトリ直下のファイルやサブディレクトリ自体は更新・取得するものの、そのサブディレクトリの中身は扱いません。

“`bash

lib ディレクトリ直下のファイルとディレクトリは更新するが、サブディレクトリの中身は更新しない

$ svn up -N lib/
“`

これは --depth immediates とほぼ同等ですが、古いオプション名として残っています。通常は --depth オプションを使用するのが推奨されます。

-r オプションと --depth オプションは組み合わせて使用することもできます。例えば、特定のリビジョン時点の、あるディレクトリ直下のファイルだけを更新する、といったことが可能です。

外部参照 (svn:externals) の扱い (–ignore-externals)

SVNには svn:externals というプロパティがあり、これによりワーキングコピー内に、別のリポジトリや同じリポジトリ内の別のパスにあるプロジェクトを自動的にチェックアウトさせることができます。これは、共通ライブラリなどを別のプロジェクトとして管理し、それを参照するプロジェクトのワーキングコピー内に自動的に配置したい場合に便利です。

通常、svn up を実行すると、svn:externals で設定された外部参照も自動的に更新されます。しかし、外部参照の更新に時間がかかる場合や、特定の状況下で外部参照の更新をスキップしたい場合があります。その場合は --ignore-externals オプションを使用します。

“`bash

ワーキングコピー全体を更新するが、外部参照の更新はスキップする

$ svn up –ignore-externals
“`

このオプションは、外部参照が一時的に利用不能な場合や、外部参照を特定の古いリビジョンに固定して作業したい場合などに役立ちます。

競合発生時の動作制御 (–accept)

svn up を実行した際に競合 (コンフリクト) が発生すると、デフォルトではSVNは競合マーカー (<<<<<<<, =======, >>>>>>>) を挿入した状態でファイルに C のマークを付け、ユーザーに手動での解決を求めます。しかし、--accept オプションを使用することで、競合発生時のSVNの動作を自動化・制御することができます。

構文は以下の通りです。

bash
$ svn up --accept ARG [PATH...]

ARG には、競合発生時にどのように自動的に変更を適用するかを指定します。

競合 (コンフリクト) とは

コンフリクトは、ワーキングコピーでローカルに編集中のファイルが、リポジトリで他の開発者によっても同じ場所で編集・コミットされた場合に発生します。SVNは賢く、異なる場所の変更であれば自動的にマージしてくれます(これが G のステータス)。しかし、同じ箇所の変更はどちらを優先すべきか判断できないため、コンフリクトとしてユーザーに解決を委ねます。

コンフリクトが発生したファイルには、SVNが特別なマーカーを挿入し、ローカルの変更、リポジトリの変更、そしてベースリビジョン(更新前のワーキングコピーの状態)の3つの状態を示す一時ファイルを作成します。

–accept オプションがない場合 (postpone)

--accept オプションを指定しない場合、デフォルトの動作は postpone です。これは競合を検出したファイルを C マーク付きでそのまま残し、ユーザーが後で手動で解決するのを待つモードです。

各 accept 引数の詳細

  • --accept postpone (デフォルト): 競合ファイルをそのまま残し、ユーザーが後で解決します。最も安全で推奨される方法です。
  • --accept base: ワーキングコピーのベースリビジョン(更新前)の状態を無条件に採用します。ローカルでの変更もリポジトリからの変更も両方破棄されます。非常に危険なオプションであり、特別な理由がない限り使うべきではありません。
  • --accept mine-full: ワーキングコピーのローカルでの変更を無条件に採用します。リポジトリからの変更は完全に破棄されます。これも危険なオプションです。他の開発者の作業を完全に無視することになるため、注意が必要です。
  • --accept theirs-full: リポジトリからの変更を無条件に採用します。ワーキングコピーでのローカルの変更は完全に破棄されます。これも非常に危険なオプションです。自分の作業を完全に失う可能性があります。
  • --accept mine-conflict: 競合している箇所についてのみ、ローカルの変更を採用し、リポジトリの変更を破棄します。コンフリクトしていない箇所は通常通りマージされます。
  • --accept theirs-conflict: 競合している箇所についてのみ、リポジトリの変更を採用し、ローカルの変更を破棄します。コンフリクトしていない箇所は通常通りマージされます。
  • --accept edit: 競合が発生した直後に、SVNが設定されているエディタを起動し、ユーザーにその場で手動で解決を促します。
  • --accept launch: 競合が発生した直後に、SVNが設定されているマージツールを起動し、ユーザーにその場でツールを使って解決を促します。

ほとんどの場合、--accept オプションを使用せずにデフォルトの postpone に任せ、後で落ち着いて手動またはマージツールを使って解決するのが最も安全で確実な方法です。自動解決オプション(mine-full, theirs-full など)は、変更内容を完全に理解しており、一方の変更を完全に破棄しても問題ないと確信できる場合にのみ、慎重に使用してください。

プロパティのみの更新 (–just-properties)

通常、svn up はファイルの内容とプロパティの両方を更新します。しかし、場合によってはファイルの内容はそのままに、プロパティ(例: svn:ignore, svn:keywords, svn:executable など)だけを更新したいことがあります。その場合は --just-properties オプションを使用します。

“`bash

ファイルの内容は更新せずに、プロパティだけを最新の状態にする

$ svn up –just-properties
“`

これは、例えば svn:ignore プロパティの設定がリポジトリで変更されたが、ローカルでの作業内容(ファイルの編集状態など)はそのままにしておきたい場合などに有効です。

詳細情報の非表示 (-q)

--quiet または -q オプションを使用すると、svn up の実行中に表示される詳細な情報(各ファイルの更新状況など)を抑制することができます。エラーメッセージや競合情報は表示されますが、通常時の U, A, D といった一行ごとの表示は抑制されます。

“`bash

ワーキングコピー全体を静かに更新する

$ svn up -q
“`

スクリプトの中で svn up を実行する場合など、人手で出力を確認する必要がない場合に便利です。

その他の便利なオプション

  • --no-auth-cache: 認証情報をキャッシュしないようにします。セキュリティ上の理由や、異なるユーザーとして操作したい場合に一時的に使用できます。
  • --username USER, --password PASS: リポジトリへのアクセスに必要なユーザー名とパスワードをコマンドラインで直接指定します。ただし、パスワードをコマンド履歴に残すのはセキュリティリスクがあるため、通常はプロンプトが表示されたときに入力するか、SVNクライアントの認証キャッシュ機能を利用します。
  • --trust-server-cert: サーバー証明書を信頼するか尋ねられた際に、一時的に信頼して接続を続行します。SSL証明書の問題で接続できない場合にデバッグなどで使用することがありますが、本番環境で安易に使用すべきではありません。

これらのオプションは特定の状況下で役立ちますが、日常的な使用ではあまり頻繁には使用しないかもしれません。必要に応じてマニュアル (svn help up) を参照してください。

svn up 実行時のトラブルシューティング

svn up は通常スムーズに実行されますが、いくつかの状況で問題が発生することがあります。最も一般的な問題とその解決策を見ていきましょう。

競合 (コンフリクト) の解決

前述の通り、svn up 実行時にファイルに C のステータスが表示された場合、競合が発生しています。これは手動で解決する必要があります。

コンフリクトマーカーの理解

競合が発生したファイルを開くと、以下のような特別なマーカーが挿入されています。

“`
<<<<<<< .mine
// これはワーキングコピーでのあなたの変更です
Your local change here
=======
// これはリポジトリからの変更です (他の人のコミット)
Theirs change from repository here

.rREV
“`

  • <<<<<<< .mine: ここからローカルの変更が始まります。
  • =======: ローカルの変更とリポジトリの変更の区切りです。
  • >>>>>>> .rREV: ここでリポジトリからの変更が終わります。REV はリポジトリの変更がコミットされたリビジョン番号です。

また、SVNはデフォルトで以下の3つのファイルを作成します(設定による)。

  • original_filename.mine: ワーキングコピーのベースリビジョン (更新前) での状態。
  • original_filename.rOLD_REV: 更新直前のリポジトリの状態 (他の人の変更は含まれていない状態)。
  • original_filename.rNEW_REV: 更新後のリポジトリの状態 (他の人の変更が適用された状態)。

これらのファイルを参考にしながら、競合マーカーが含まれるファイルを編集し、最終的に含めるべき内容に修正します。

手動による解決手順

  1. svn up を実行し、競合 (C マーク) を確認します。
  2. 競合が発生したファイルをテキストエディタで開きます。
  3. ファイル内の <<<<<<<, =======, >>>>>>> とそれらの間のコードを確認し、手動で適切な内容に修正します。どちらか一方の変更を採用したり、両方の変更を組み合わせたりします。
  4. 競合マーカーの行自体を忘れずに削除します。 マーカーが残ったままコミットするとエラーになります。
  5. 修正したファイルを保存します。

svn resolved コマンド

ファイルを編集して競合を解決したら、SVNに対して「このファイルの競合は解決しました」と通知する必要があります。これには svn resolved コマンドを使用します。

“`bash

競合を解決したファイルに対して実行する

$ svn resolved path/to/conflict_file.txt
“`

svn resolved を実行すると、conflict_file.txt のステータスは C から M (Modified) に変わります。これで、このファイルをコミットできるようになります。

もし、競合マーカー入りのファイルを編集せずに、ローカルの変更を完全に破棄してリポジトリの最新の状態に戻したい場合は、svn revert path/to/conflict_file.txt を実行します。これにより、競合マーカーも削除され、ファイルはリポジトリの最新の状態(競合相手の変更のみが反映された状態)に戻り、ステータスはクリアされます。

ツリー競合 (Tree Conflict)

通常のファイル内容の競合とは別に、ツリー競合 (Tree Conflict) が発生することがあります。これは、ファイルの移動、削除、追加といった「ツリー構造」に関する操作が複数人によって行われ、それが衝突した場合に発生します。

例:
* Aさんがファイル foo.txt を削除してコミットした。
* Bさんが同じファイル foo.txt を編集してコミットした。
* Bさんが svn up を実行すると、Aさんの削除と自分の編集が衝突し、ツリー競合が発生する。

ツリー競合は、ファイル内容の競合よりも解決が少し複雑です。svn status を実行すると、対象アイテムに C のステータスと共に tree conflict のマークが表示されます。

bash
$ svn status
C foo.txt
> local file edit, incoming file delete upon update

ツリー競合の解決方法は、どのような操作が衝突したか、そしてどちらの変更を最終的に採用したいかによって異なります。解決策としては、以下のようなものが考えられます。

  1. どちらかの変更を完全に採用する: 例えば、Aさんの「削除」を採用し、自分の編集を捨てる。あるいは、自分の「編集」を採用し、Aさんの削除を取り消す。
  2. 両方の変更を組み合わせる: 例えば、Aさんがディレクトリを移動し、Bさんがそのディレクトリ内のファイルを編集した場合など。

解決には、衝突したアイテムに対して svn resolve --accept ARG path/to/item コマンドを使用します。ARG には mine-full, theirs-full, working などを指定します。

  • --accept mine-full または working: ローカルでの変更を採用し、相手の変更を破棄。
  • --accept theirs-full: 相手の変更を採用し、ローカルでの変更を破棄。

ツリー競合は発生状況が多様なため、解決方法も状況によって異なります。もし解決が困難な場合は、SVNの公式ドキュメントや、チーム内の経験者に相談することをおすすめします。

認証エラー

svn up 実行時にリポジトリへの認証に失敗することがあります。

svn: E170001: Authorization required for 'https://svn.example.com/repo'
svn: E170001: Basic authentication realm: '<http://svn.example.com:80> Subversion Repository'
svn: E120109: Unable to authenticate to 'https://svn.example.com/repo'

原因としては、ユーザー名やパスワードの間違い、またはリポジトリへのアクセス権限がないなどが考えられます。

  • 正しいユーザー名とパスワードを使用しているか確認します。
  • 必要であれば、--username および --password オプションで明示的に指定して試します(ただしセキュリティに注意)。
  • リポジトリ管理者に、自分のアカウントがリポジトリへのアクセス権を持っているか確認してもらいます。
  • 認証情報がキャッシュされていて問題を引き起こしている場合、認証キャッシュをクリアして再試行します (SVNクライアントによってキャッシュの場所やクリア方法が異なります)。

リポジトリへの接続問題

リポジトリが存在しない、URLが間違っている、ネットワークに問題があるなどの理由でリポジトリに接続できない場合があります。

svn: E170013: Unable to connect to a repository at URL 'https://svn.example.com/wrong/path'
svn: E170013: The XML response contains invalid XML

  • svn info コマンドを実行し、ワーキングコピーが指しているリポジトリのURLが正しいか確認します。
  • ネットワーク接続を確認します。
  • ファイアウォールやプロキシの設定を確認します。

ファイルシステム関連のエラー

ワーキングコピーのあるディスクの容量不足、ファイルの権限問題、ファイル名に使用できない文字が含まれているなどが原因でエラーが発生することがあります。

svn: E000002: Can't create directory 'path/to/new_dir': No such file or directory
svn: E000013: Can't open file 'path/to/file.txt': Permission denied

  • ディスクの空き容量を確認します。
  • ワーキングコピーディレクトリとその中のファイル/ディレクトリに対するユーザーの書き込み権限を確認します。
  • OSのファイル名に関する制限を確認します。

これらのトラブルはSVNの基本的な理解と、落ち着いてエラーメッセージを読むことで解決できることが多いです。

svn up と他のコマンドとの連携

svn up コマンドは、他のSVNコマンドと組み合わせて使用することで、さらに効果を発揮します。特に以下のコマンドは svn up の前後でよく使用されます。

svn status

svn status コマンドは、ワーキングコピーの現在の状態を表示します。リポジトリと比較して、どのファイルが変更されたか、追加されたか、削除されたか、競合しているかなどを一覧できます。

svn up を実行する前に svn status を実行することで、ローカルでの未コミットの変更を確認できます。これにより、svn up によって自分の変更がどう影響されるか(特に競合が発生しそうか)を予測するのに役立ちます。

“`bash

ワーキングコピーの現在の状態を確認する

$ svn status
“`

svn diff

svn diff コマンドは、ワーキングコピーでのローカルの変更内容を表示します。引数なしで実行すると、ワーキングコピーのファイルと、それらのファイルのベースリビジョン(最後に svn up または svn checkout した時点)との差分を表示します。

svn up を実行する前に svn diff を実行して、自分の変更内容を再確認できます。また、svn up によってコンフリクトが発生した場合、svn diff を使用してコンフリクトマーカーが挿入されたファイルの内容を確認し、解決の参考にすることができます。

“`bash

ローカルでの変更内容を確認する

$ svn diff
“`

svn log

svn log コマンドは、リポジトリの変更履歴(ログメッセージ)を表示します。

svn up -r REV で特定の過去リビジョンに更新する際に、どのリビジョンがどのような変更だったかを確認するために svn log を使用します。

“`bash

最新のリビジョンから順にログを表示する

$ svn log

特定のファイルやディレクトリのログを表示する

$ svn log path/to/file_or_dir
“`

svn log の出力から目的のリビジョン番号を確認し、その番号を -r オプションに指定して svn up を実行するのが一般的な流れです。

svn commit 前の svn up の重要性

繰り返しになりますが、自分の変更をリポジトリにコミット (svn commit) する前に、必ず svn up を実行してワーキングコピーを最新の状態にすることが強く推奨されます。

理由は以下の通りです。

  1. 競合の早期発見と解決: 他の人があなたが作業しているファイルやディレクトリに変更を加えて既にコミットしている場合、svn up を実行することでそれらの変更を自分のワーキングコピーに取り込み、自分の変更との間で競合が発生するかどうかを確認できます。競合が発生した場合は、コミット前に自分のローカル環境で落ち着いて解決できます。
  2. 手戻りの防止: コミット直前に svn up を行わず、他の人の変更と自分の変更が衝突したまま svn commit を試みると、SVNはコミットを拒否し、先に svn up して競合を解決するように求めてきます。この場合、コミットは中断され、改めて svn up と競合解決を行う必要があるため、手間がかかります。
  3. 「動くコード」のコミット: svn up を行うことで、他の人の最新の変更が自分のワーキングコピーに取り込まれます。これにより、自分の変更と最新の他の人の変更が組み合わさった状態でコードをテストできます。もし他の人の変更によって自分のコードに問題が発生した場合でも、コミット前にそれを発見し、修正することが可能です。最新の状態との組み合わせで正常に動作することを確認してからコミットすることで、リポジトリには常に安定した状態のコードが蓄積されていきます。

このため、「svn up -> 競合解決 (もしあれば) -> テスト -> svn commit」というサイクルを守ることが、チーム開発におけるSVN運用のベストプラクティスとされています。

svn up の実践的な活用例

svn up コマンドは、日々の開発作業だけでなく、様々な状況で活用できます。

日々の作業開始時の更新

これは最も基本的な使い方です。開発日の始まりに、まずワーキングコピーのルートディレクトリで svn up を実行します。これにより、チームメンバーが前日や早朝に行った変更をすべて取り込み、最新のコードベースで作業を開始できます。

bash
$ cd /path/to/your/workingcopy
$ svn up

コミット前の最終確認としての更新

前述の通り、自分の変更をコミットする直前には必ず svn up を実行します。これにより、他の人の最新のコミットによる変更を取り込み、自分の変更との間に競合がないかを確認し、あれば解決します。

bash
$ cd /path/to/your/workingcopy
$ svn status # 自分の変更を確認
$ svn diff # 変更内容をレビュー
$ svn up # 最新に更新し、競合をチェック・解決
$ svn status # 競合が解決されているか確認
$ svn commit -m "コミットメッセージ" # 自分の変更をコミット

特定のタグやブランチへの切り替え

SVNでは、ワーキングコピーの svn up 先を、trunk から特定のブランチやタグのパスに変更することで、簡単にブランチやタグに切り替えることができます。

例えば、メインの開発ライン(trunk)から feature ブランチに切り替えたい場合:

“`bash

現在のワーキングコピーが trunk を指していると仮定

$ cd /path/to/your/workingcopy
$ svn info | grep URL # 現在のURLを確認

URL: https://svn.example.com/repo/project/trunk

feature ブランチのパスに更新する

$ svn up https://svn.example.com/repo/project/branches/feature_branch
“`

これにより、ワーキングコピーの中身が trunk から feature_branch の内容に置き換わります。内部的には、SVNは trunkfeature_branch の差分を計算し、ワーキングコピーに必要な追加、削除、変更を適用します。

同様に、特定のタグ(リリースバージョンなど)の状態にワーキングコピーを切り替えたい場合も、タグのパスを指定して svn up を実行します。

“`bash

リリース 1.0 のタグに切り替えたい場合

$ svn up https://svn.example.com/repo/project/tags/release-1.0
“`

これにより、リリース 1.0 時点のコード状態を簡単に再現できます。

過去の状態を確認する

バグの発生リビジョンを特定したり、過去の機能がどのように実装されていたかを確認したりするために、ワーキングコピーを一時的に過去のリビジョンに戻すことがあります。

“`bash

特定のバグが報告されたリビジョン 800 の状態に戻す

$ svn up -r 800
“`

これにより、ワーキングコピー全体がリビジョン 800 の時点の状態になります。確認作業が終わったら、再度 svn up (引数なし、または -r HEAD) を実行して最新の状態に戻すことを忘れないでください。

“`bash

確認が終わったので最新の状態に戻す

$ svn up
“`

これらの活用例からもわかるように、svn up コマンドは、単なる「最新化」だけでなく、ワーキングコピーの状態を柔軟に制御するための強力なツールです。

まとめ

この記事では、Subversion (SVN) における svn up (または svn update) コマンドについて、その基本的な役割から高度な使い方、トラブルシューティング、そして他のコマンドとの連携、実践的な活用例まで、網羅的に解説しました。

svn up は、ワーキングコピーをリポジトリの最新の状態に同期させることが主な目的ですが、-r オプションによる特定リビジョンへの更新、--depth オプションによる更新範囲の制御、--accept オプションによる競合解決の自動化など、多くの機能を持っています。

特に重要なのは、チーム開発においてコミット前に必ず svn up を実行するという習慣です。これにより、他の開発者の変更を自分の作業に取り込み、競合を早期に発見・解決し、常に安定したコードベースで作業を進めることができます。

svn up 実行時に発生しうる競合やツリー競合、認証エラーなどのトラブルについても、その解決方法を理解しておくことで、問題発生時にも落ち着いて対処できます。

svn status, svn diff, svn log といった関連コマンドと組み合わせて使用することで、svn up はさらに効果的なバージョン管理ツールとなります。

この記事を通じて svn up コマンドの理解が深まり、あなたのSVNを使った開発がよりスムーズで安全になることを願っています。日々の開発の中で積極的に svn up を活用し、その動作に慣れていきましょう。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール