Svn-quick-guide
SVN-基本概念
バージョン管理システムとは何ですか?
バージョン管理システム(VCS)は、ソフトウェア開発者が協力して作業の完全な履歴を維持するのに役立つソフトウェアです。
以下はバージョン管理システムの目標です
- 開発者が同時に作業できるようにします。
- 互いの変更を上書きしないでください。
- すべてのすべてのバージョンの履歴を維持します。
- VCSは2つのカテゴリに分かれています。*
- 集中型バージョン管理システム(CVCS)、および
- 分散/分散バージョン管理システム(DVCS)。
このチュートリアルでは、集中型バージョン管理システム、特に Subversion のみに集中します。 Subversionは中央集中型バージョン管理システムに該当します。つまり、中央サーバーを使用してすべてのファイルを保存し、チームのコラボレーションを可能にします。
バージョン管理の用語
このチュートリアルで使用する用語のいくつかについて説明することから始めましょう。
- *リポジトリ:*リポジトリは、バージョン管理システムの中核です。 開発者がすべての作業を保存する中心的な場所です。 リポジトリには、ファイルだけでなく履歴も保存されます。 リポジトリはネットワーク経由でアクセスされ、サーバーとして機能し、クライアントとして機能するバージョン管理ツールです。 クライアントはリポジトリに接続でき、リポジトリへ/から変更を保存/取得できます。 クライアントは、変更を保存することで、これらの変更を他の人が利用できるようにし、変更を取得することで、他の人の変更を作業コピーとして取得します。
- *トランク:*トランクは、すべての主要な開発が行われるディレクトリであり、通常、プロジェクトで作業するために開発者によってチェックアウトされます。
- タグ:タグディレクトリは、プロジェクトの名前付きスナップショットを保存するために使用されます。 タグ操作により、リポジトリ内の特定のバージョンに説明的で覚えやすい名前を付けることができます。 +たとえば、LAST_STABLE_CODE_BEFORE_EMAIL_SUPPORTは、リポジトリUUID:7ceef8cb-3799-40dd-a067-c216ec2e5247および+リビジョン:13よりも記憶に残ります。
- *分岐:*分岐操作は、別の開発ラインを作成するために使用されます。 開発プロセスを2つの異なる方向に分岐させる場合に役立ちます。 たとえば、バージョン5.0をリリースするときに、6.0機能の開発を5.0バグ修正とは別に維持できるように、ブランチを作成することができます。
- *作業コピー:*作業コピーはリポジトリのスナップショットです。 リポジトリはすべてのチームで共有されますが、人々はそれを直接変更しません。 代わりに、各開発者は作業コピーをチェックアウトします。 作業コピーは、開発者が他のチームから隔離されたまま作業を行うことができるプライベートな職場です。
- *変更のコミット:*コミットは、プライベートな職場から中央サーバーへの変更を保存するプロセスです。 コミット後、すべてのチームが変更を利用できるようになります。 他の開発者は、作業コピーを更新することでこれらの変更を取得できます。 コミットはアトミック操作です。 コミット全体が成功するか、ロールバックされます。 ユーザーは、コミットの半分が完了したことを確認しません。
SVN-環境設定
SVNのインストール
Subversionは、人気のあるオープンソースのバージョン管理ツールです。 オープンソースであり、インターネット経由で無料で利用できます。 ほとんどのGNU/Linuxディストリビューションにはデフォルトで付属しているため、すでにシステムにインストールされている可能性があります。 インストールされているかどうかを確認するには、次のコマンドを使用します。
[jerry@CentOS ~]$ svn --version
Subversionクライアントがインストールされていない場合、コマンドはエラーを報告します。そうでない場合、インストールされたソフトウェアのバージョンを表示します。
[jerry@CentOS ~]$ svn --version
-bash: svn: command not found
RPMベースのGNU/Linuxを使用している場合は、インストールに yum コマンドを使用します。 インストールが正常に完了したら、 _ svn --version_ コマンドを実行します。
[jerry@CentOS ~]$ su -
Password:
[root@CentOS ~]# yum install subversion
[jerry@CentOS ~]$ svn --version
svn, version 1.6.11 (r934486)
compiled Jun 23 2012, 00:44:03
DebianベースのGNU/Linuxを使用している場合は、インストールに apt コマンドを使用します。
[jerry@Ubuntu]$ sudo apt-get update
[sudo] password for jerry:
[jerry@Ubuntu]$ sudo apt-get install subversion
[jerry@Ubuntu]$ svn --version
svn, version 1.7.5 (r1336830)
compiled Jun 21 2013, 22:11:49
Apacheセットアップ
GNU/LinuxにSubversionクライアントをインストールする方法を見てきました。 新しいリポジトリを作成し、ユーザーへのアクセスを許可する方法を見てみましょう。
サーバーに Apache httpd モジュールと svnadmin ツールをインストールする必要があります。
[jerry@CentOS ~]$ su -
Password:
[root@CentOS ~]# yum install mod_dav_svn subversion
*_mod_dav_svn_* パッケージを使用すると、HTTPを使用して、Apache httpdサーバー経由でリポジトリにアクセスでき、 *_ subversion_* パッケージによってsvnadminツールがインストールされます。
Subversionは、その構成を /etc/httpd/conf.d/subversion.conf ファイルから読み取ります。 設定を追加すると、 _ subversion.conf_ ファイルは次のようになります。
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
<Location/svn>
DAV svn
SVNParentPath/var/www/svn
AuthType Basic
AuthName "Authorization Realm"
AuthUserFile/etc/svn-users
Require valid-user
</Location>
Subversionユーザーを作成して、リポジトリへのアクセスを許可します。 _htpasswd_コマンドは、HTTPユーザーの基本認証のために_usernames_および_passwords_を保存するために使用されるプレーンテキストファイルを作成および更新するために使用されます。 '-c’オプションは_password_ファイルを作成します。_password_ファイルが既に存在する場合は上書きされます。 これが、 '-c’オプションを初めて使用する理由です。 「-m」オプションは、パスワードのMD5暗号化を有効にします。
ユーザー設定
ユーザー tom を作成しましょう。
[root@CentOS ~]# htpasswd -cm/etc/svn-users tom
New password:
Re-type new password:
Adding password for user tom
ユーザー jerry を作成しましょう
[root@CentOS ~]# htpasswd -m/etc/svn-users jerry
New password:
Re-type new password:
Adding password for user jerry
[root@CentOS ~]#
すべての作業を保存するSubversion親ディレクトリを作成します(_/etc/httpd/conf.d/subversion.conf_を参照)。
[root@CentOS ~]# mkdir/var/www/svn
[root@CentOS ~]# cd/var/www/svn/
リポジトリのセットアップ
_project_repo_という名前のプロジェクトリポジトリを作成します。 _svnadmin_コマンドは、メタデータを格納するための新しいリポジトリとその中にいくつかの他のディレクトリを作成します。
[root@CentOS svn]# svnadmin create project_repo
[root@CentOS svn]# ls -l project_repo
total 24
drwxr-xr-x. 2 root root 4096 Aug 4 22:30 conf
drwxr-sr-x. 6 root root 4096 Aug 4 22:30 db
-r--r--r--. 1 root root 2 Aug 4 22:30 format
drwxr-xr-x. 2 root root 4096 Aug 4 22:30 hooks
drwxr-xr-x. 2 root root 4096 Aug 4 22:30 locks
-rw-r--r--. 1 root root 229 Aug 4 22:30 README.txt
リポジトリのユーザーとグループの所有権を変更しましょう。
[root@CentOS svn]# chown -R apache.apache project_repo/
SELinuxステータスツールを使用して、_SELinux_が有効になっているかどうかを確認します。
[root@CentOS svn]# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 24
Policy from config file: targeted
サーバーでは、SELinuxが有効になっているため、SELinuxセキュリティコンテキストを変更する必要があります。
[root@CentOS svn]# chcon -R -t httpd_sys_content_t/var/www/svn/project_repo/
HTTP経由のコミットを許可するには、次のコマンドを実行します。
[root@CentOS svn]# chcon -R -t httpd_sys_rw_content_t/var/www/svn/project_repo/
Apacheサーバーを再起動すると、Apacheサーバーの構成が完了します。
[root@CentOS svn]# service httpd restart
Stopping httpd: [FAILED]
Starting httpd: httpd: apr_sockaddr_info_get() failed for CentOS
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
[ OK ]
[root@CentOS svn]# service httpd status
httpd (pid 1372) is running...
[root@CentOS svn]#
Apacheサーバーを正常に構成しました。次にリポジトリーを構成します。 正規のユーザーのみにリポジトリへのアクセスを提供し、デフォルトの認証ファイルを使用するには、 _project_repo/conf/svnserve.conf_ファイルに次の行を追加します。
anon-access = none
authz-db = authz
従来、すべてのSubversionプロジェクトには、プロジェクトのルートディレクトリの直下に trunk、tags、 および branches ディレクトリがあります。
_trunk_は、すべての主要な開発が行われるディレクトリであり、通常、開発者がプロジェクトに取り組むためにチェックアウトします。
_tags_ディレクトリは、プロジェクトの名前付きスナップショットを保存するために使用されます。 実稼働リリースを作成するとき、チームはリリースに入るコードにタグを付けます。
_branches_ディレクトリは、さまざまな開発ラインを追求するときに使用されます。
プロジェクトリポジトリの下に、トランク、タグ、およびブランチのディレクトリ構造を作成します。
[root@CentOS svn]# mkdir/tmp/svn-template
[root@CentOS svn]# mkdir/tmp/svn-template/trunk
[root@CentOS svn]# mkdir/tmp/svn-template/branches
[root@CentOS svn]# mkdir/tmp/svn-template/tags
ここで、ディレクトリを /tmp/svn-template からリポジトリにインポートします。
[root@CentOS svn]# svn import -m 'Create trunk, branches, tags directory structure'/tmp/svn-template/
Adding /tmp/svn-template/trunk
Adding /tmp/svn-template/branches
Adding /tmp/svn-template/tags
Committed revision 1.
[root@CentOS svn]#
これは完了です! リポジトリが正常に作成され、 _ Tom_ および Jerry へのアクセスが許可されました。 これ以降、サポートされているすべての操作をリポジトリに対して実行できます。
SVN-ライフサイクル
この章では、バージョン管理システムのライフサイクルについて説明します。 後の章で、各操作のSubversionコマンドを確認します。
リポジトリを作成:
リポジトリは、開発者がすべての作業を保存する中心的な場所です。 リポジトリには、ファイルだけでなく、変更に関する履歴も保存されます。 つまり、ファイルに加えられた変更の履歴を保持します。
「作成」操作は、新しいリポジトリを作成するために使用されます。 ほとんどの場合、この操作は1回だけ実行されます。 新しいリポジトリを作成するとき、VCSは、リポジトリを作成する場所やリポジトリに付ける名前など、リポジトリを識別するために何かを言うことを期待します。
チェックアウト
「チェックアウト」操作は、リポジトリから作業コピーを作成するために使用されます。 作業コピーは、開発者が変更を行い、後でこれらの変更をリポジトリに送信するプライベートな職場です。
更新
名前が示すように、「更新」操作は作業コピーを更新するために使用されます。 この操作により、作業コピーとリポジトリが同期されます。 リポジトリはすべてのチームで共有されるため、他の開発者は変更をコミットでき、作業コピーは古くなります。
_Tom_と_Jerry_がプロジェクトに取り組んでいる2人の開発者であるとします。 どちらもリポジトリから最新バージョンをチェックアウトし、作業を開始します。 この時点で、それらの作業コピーはリポジトリと完全に同期されます。 _Jerry_は作業を非常に効率的に完了し、変更をリポジトリにコミットします。
_Tom’s_作業コピーは古くなっています。 更新操作により、_Jerryの最新の変更がリポジトリから取得され、_Tomの作業コピーが更新されます。
変更を実行
チェックアウト後、さまざまな操作を行って変更を実行できます。 編集は最も一般的な操作です。 既存のファイルを編集して、ファイルの内容を追加/削除できます。
ファイル/ディレクトリを追加できます。 ただし、これらのファイル/ディレクトリはすぐにリポジトリの一部にはならず、代わりに保留中の変更リストに追加され、コミット操作後にリポジトリの一部になります。
同様に、ファイル/ディレクトリを削除できます。 削除操作は、作業コピーからファイルをすぐに削除しますが、ファイルの実際の削除は保留中の変更リストに追加され、コミット操作後にリポジトリに変更が加えられます。
「名前変更」操作は、ファイル/ディレクトリの名前を変更します。 「移動」操作は、リポジトリツリー内のある場所から別の場所にファイル/ディレクトリを移動するために使用されます。
変更を確認
作業コピーをチェックアウトするか、作業コピーを更新すると、作業コピーはリポジトリと完全に同期されます。 しかし、作業コピーに変更を加えると、リポジトリよりも新しくなります。 また、「コミット」操作の前に変更を確認することをお勧めします。
「ステータス」操作には、作業コピーに加えられた変更がリストされます。 前述したように、作業コピーで変更を行うと、これらの変更はすべて保留中の変更リストの一部になります。 また、「ステータス」操作は、保留中の変更リストを表示するために使用されます。
「ステータス」操作では、変更のリストのみが提供され、それらの詳細は提供されません。 _diff_操作を使用して、作業コピーに加えられた変更の詳細を表示できます。
間違いを修正
作業コピーに変更を加えたが、今、彼はこれらの変更を破棄したいとします。 この状況では、「元に戻す」操作が役立ちます。
元に戻す操作は、作業コピーに加えられた変更を元に戻します。 1つ以上のファイル/ディレクトリを元に戻すことができます。 また、作業コピー全体を元に戻すこともできます。 この場合、「元に戻す」操作は保留中の変更リストを破棄し、作業コピーを元の状態に戻します。
競合の解決:
マージ時に競合が発生する可能性があります。 「マージ」操作は、安全に実行できるすべてを自動的に処理します。 それ以外はすべて競合と見なされます。 たとえば、_ "hello.c" _ファイルはブランチで変更され、別のブランチで削除されました。 このような状況では、人が決定を下す必要があります。 「解決」操作は、ユーザーが状況を把握し、競合を処理する方法についてVCSに通知するために使用されます。
変更をコミット
「コミット」操作は、作業コピーからリポジトリに変更を適用するために使用されます。 この操作によりリポジトリが変更され、他の開発者は作業コピーを更新することでこれらの変更を確認できます。
コミットする前に、ファイル/ディレクトリを保留中の変更リストに追加する必要があります。 これは、変更がコミットされるのを待つ場所です。 コミットでは、通常、誰かが変更を加えた理由を説明するログメッセージが提供されます。 このログメッセージは、リポジトリの履歴の一部になります。 コミットはアトミック操作です。つまり、コミット全体が成功するか、ロールバックされます。 ユーザーは、コミットの途中で終了することはありません。
SVN-チェックアウトプロセス
Subversionには、リポジトリから作業コピーをチェックアウトする_checkout_コマンドが用意されています。 以下のコマンドは、_project_repo_という名前で現在の作業ディレクトリに新しいディレクトリを作成します。 ほとんどの場合、リポジトリURLは気にしないでください。Subversion管理者によって適切なアクセス権が既に提供されています。
[tom@CentOS ~]$ svn checkout http://svn.server.com/svn/project_repo --username=tom
上記のコマンドは、次の結果を生成します。
A project_repo/trunk
A project_repo/branches
A project_repo/tags
Checked out revision 1.
チェックアウト操作が成功するたびに、リビジョン番号が印刷されます。 リポジトリに関する詳細情報を表示するには、_info_コマンドを実行します。
[tom@CentOS trunk]$ pwd
/home/tom/project_repo/trunk
[tom@CentOS trunk]$ svn info
上記のコマンドは、次の結果を生成します。
Path: .
URL: http://svn.server.com/svn/project_repo/trunk
Repository Root: http://svn.server.com/svn/project_repo
Repository UUID: 7ceef8cb-3799-40dd-a067-c216ec2e5247
Revision: 1
Node Kind: directory
Schedule: normal
Last Changed Author: jerry
Last Changed Rev: 0
Last Changed Date: 2013-08-24 18:15:52 +0530 (Sat, 24 Aug 2013)
[tom@CentOS trunk]$
SVN-変更の実行
_Jerry_は、リポジトリの最新バージョンをチェックアウトし、プロジェクトの作業を開始します。 彼は、トランクディレクトリ内に_array.c_ファイルを作成します。
[jerry@CentOS ~]$ cd project_repo/trunk/
[jerry@CentOS trunk]$ cat array.c
上記のコマンドは、次の結果を生成します。
#include <stdio.h>
#define MAX 16
int main(void) {
int i, n, arr[MAX];
printf("Enter the total number of elements: ");
scanf("%d", &n);
printf("Enter the elements\n");
for (i = 0; i < n; ++i) scanf("%d", &arr[i]);
printf("Array has following elements\n");
for (i = 0; i < n; ++i) printf("|%d| ", arr[i]);
printf("\n");
return 0;
}
彼はコミットする前にコードをテストしたいと考えています。
[jerry@CentOS trunk]$ make array
cc array.c -o array
[jerry@CentOS trunk]$ ./array
Enter the total number of elements: 5
Enter the elements
1
2
3
4
5
Array has following elements
|1| |2| |3| |4| |5|
彼は自分のコードをコンパイルしてテストし、すべてが期待どおりに機能しているので、今度は変更をコミットします。
[jerry@CentOS trunk]$ svn status
? array.c
? array
Subversionはファイル名の前に_ '?' _を表示しています。これは、これらのファイルをどうするかわからないためです。
コミットする前に、_Jerry_はこのファイルを保留中の変更リストに追加する必要があります。
[jerry@CentOS trunk]$ svn add array.c
A array.c
「status」操作で確認しましょう。 Subversionは、_array.c_の前に A を示します。つまり、ファイルは保留中の変更リストに正常に追加されます。
[jerry@CentOS trunk]$ svn status
? array
A array.c
_array.c_ファイルをリポジトリに保存するには、commitコマンドの後に-mオプションを指定して、コミットメッセージを続けます。 -mオプションを省略すると、Subversionはテキストエディターを起動し、複数行のメッセージを入力できます。
[jerry@CentOS trunk]$ svn commit -m "Initial commit"
Adding trunk/array.c
Transmitting file data .
Committed revision 2.
これで、_array.c_ファイルがリポジトリに正常に追加され、リビジョン番号が1ずつ増加します。
SVN-変更の確認
_Jerry_はすでに_array.c_ファイルをリポジトリに追加しました。 _Tom_は、最新のコードもチェックアウトし、動作を開始します。
[tom@CentOS ~]$ svn co http://svn.server.com/svn/project_repo --username=tom
上記のコマンドは次の結果を生成します。
A project_repo/trunk
A project_repo/trunk/array.c
A project_repo/branches
A project_repo/tags
Checked out revision 2.
しかし、彼は誰かがすでにコードを追加していることを発見しました。 そこで、彼は誰がそれをしたのか興味があり、次のコマンドを使用してログメッセージをチェックして詳細を確認します。
[tom@CentOS trunk]$ svn log
上記のコマンドは次の結果を生成します。
------------------------------------------------------------------------
r2 | jerry | 2013-08-17 20:40:43 +0530 (Sat, 17 Aug 2013) | 1 line
Initial commit
------------------------------------------------------------------------
r1 | jerry | 2013-08-04 23:43:08 +0530 (Sun, 04 Aug 2013) | 1 line
Create trunk, branches, tags directory structure
------------------------------------------------------------------------
_Tom_が_Jerry’s_のコードを観察すると、彼はすぐにバグに気付きます。 Jerryは配列のオーバーフローをチェックしていなかったため、深刻な問題を引き起こす可能性がありました。 そこで、トムはこの問題を解決することにしました。 変更後、_array.c_は次のようになります。
#include <stdio.h>
#define MAX 16
int main(void)
{
int i, n, arr[MAX];
printf("Enter the total number of elements: ");
scanf("%d", &n);
/*handle array overflow condition*/
if (n > MAX) {
fprintf(stderr, "Number of elements must be less than %d\n", MAX);
return 1;
}
printf("Enter the elements\n");
for (i = 0; i < n; ++i)
scanf("%d", &arr[i]);
printf("Array has following elements\n");
for (i = 0; i < n; ++i)
printf("|%d| ", arr[i]);
printf("\n");
return 0;
}
_Tom_は、ステータス操作を使用して、保留中の変更リストを表示したいと考えています。
[tom@CentOS trunk]$ svn status
M array.c
_array.c_ファイルが変更されているため、Subversionはファイル名の前に M の文字を表示します。 次に_Tom_は彼のコードをコンパイルおよびテストし、正常に動作しています。 変更をコミットする前に、彼は自分が加えた変更を確認して、それを再確認したいと考えています。
[tom@CentOS trunk]$ svn diff
Index: array.c
===================================================================
--- array.c (revision 2)
+++ array.c (working copy)
@@ -9,6 +9,11 @@
printf("Enter the total number of elements: ");
scanf("%d", &n);
+ if (n > MAX) {
+ fprintf(stderr, "Number of elements must be less than %d\n", MAX);
+ return 1;
+ }
printf("Enter the elements\n");
for (i = 0; i < n; ++i)
_Tom_は_array.c_ファイルに数行追加しました。そのため、Subversionは新しい行の前に + 記号を表示します。 これで、彼は変更をコミットする準備ができました。
[tom@CentOS trunk]$ svn commit -m "Fix array overflow problem"
上記のコマンドは、次の結果を生成します。
Sending trunk/array.c
Transmitting file data .
Committed revision 3.
_Tom’s_の変更はリポジトリに正常にコミットされました。
SVN-更新プロセス
_Jerry_はコードの最初のバージョンをコミットしました。 しかし、彼は、入力を受け入れ、配列の内容を表示するために2つの関数を作成する必要があると考えています。 変更後、_array.c_は次のようになります。
#include <stdio.h>
#define MAX 16
void accept_input(int *arr, int n) {
int i;
for (i = 0; i < n; ++i)
scanf("%d", &arr[i]);
}
void display(int *arr, int n) {
int i;
for (i = 0; i < n; ++i)
printf("|%d| ", arr[i]);
printf("\n");
}
int main(void) {
int i, n, arr[MAX];
printf("Enter the total number of elements: ");
scanf("%d", &n);
printf("Enter the elements\n");
accept_input(arr, n);
printf("Array has following elements\n");
display(arr, n);
return 0;
}
_Jerry_は彼のコードをコンパイルしてテストし、変更をコミットする準備ができています。 その前に、彼は次のコマンドを使用して変更を確認したいと考えています。
[jerry@CentOS trunk]$ svn diff
上記のコマンドは、次の結果を生成します。
Index: array.c
===================================================================
--- array.c (revision 2)
+++ array.c (working copy)
@@ -2,6 +2,24 @@
#define MAX 16
+void accept_input(int *arr, int n)
+{
+ int i;
+ for (i = 0; i & n; ++i)
+ scanf("%d", &arr[i]);
+}
+void display(int *arr, int n)
+{
+ int i;
+ for (i = 0; i < n; ++i)
+ printf("|%d| ", arr[i]);
+ printf("\n");
+}
int main(void)
{
int i, n, arr[MAX];
@@ -10,15 +28,10 @@
scanf("%d", &n);
printf("Enter the elements\n");
+ accept_input(arr, n);
- for (i = 0; i < n; ++i)
- scanf("%d", &arr[i]);
-
printf("Array has following elements\n");
- for (i = 0; i < n; ++i)
- printf("|%d| ", arr[i]);
-
- printf("\n");
+ display(arr, n);
return 0;
}
新しく追加された行については、Subversionは行の前に _ + ' 記号を表示し、削除された行については '-_ 記号を表示します。 現在、ジェリーは次のコマンドを使用して変更をコミットしようとします。
[jerry@CentOS trunk]$ svn commit -m "Add function to accept input and to display array contents"
上記のコマンドは、次の結果を生成します。
Sending trunk/array.c
svn: Commit failed (details follow):
svn: File or directory 'array.c' is out of date; try updating
svn: resource out of date; try updating
_Tom_はすでにリポジトリを変更しており、_Jerry’s_の作業コピーは古いため、Subversionは_Jerry’s_の変更をコミットできません。 互いの変更を上書きしないように、Subversionはこの操作に失敗します。 _Jerry_は、変更をコミットする前に作業コピーを更新する必要があります。 そこで、以下に示すように、更新コマンドを使用します。
[jerry@CentOS trunk]$ svn update
G array.c
Updated to revision 3.
Subversionは、ファイル名の前に G という文字を表示しています。これは、このファイルがマージされたことを意味します。
[jerry@CentOS trunk]$ svn diff
上記のコマンドは、次の結果を生成します。
Index: array.c
===================================================================
--- array.c (revision 3)
+++ array.c (working copy)
@@ -2,6 +2,24 @@
#define MAX 16
+void accept_input(int *arr, int n)
+{
+ int i;
+ for (i = 0; i < n; ++i)
+ scanf("%d", &arr[i]);
+}
+void display(int *arr, int n)
+{
+ int i;
+ for (i = 0; i < n; ++i)
+ printf("|%d| ", arr[i]);
+ printf("\n");
+}
int main(void)
{
int i, n, arr[MAX];
@@ -15,15 +33,10 @@
}
printf("Enter the elements\n");
+ accept_input(arr, n);
- for (i = 0; i < n; ++i)
- scanf("%d", &arr[i]);
-
printf("Array has following elements\n");
- for (i = 0; i < n; ++i)
- printf("|%d| ", arr[i]);
-
- printf("\n");
+ display(arr, n);
return 0;
}
Subversionは_Jerry’s_の変更のみを表示しますが、_array.c_ファイルはマージされます。 注意深く観察すると、Subversionはリビジョン番号3を表示しています。 前の出力では、リビジョン番号2が表示されていました。 ファイルを誰がどのような目的で変更したかを確認してください。
jerry@CentOS trunk]$ svn log
------------------------------------------------------------------------
r3 | tom | 2013-08-18 20:21:50 +0530 (Sun, 18 Aug 2013) | 1 line
Fix array overflow problem
------------------------------------------------------------------------
r2 | jerry | 2013-08-17 20:40:43 +0530 (Sat, 17 Aug 2013) | 1 line
Initial commit
------------------------------------------------------------------------
r1 | jerry | 2013-08-04 23:43:08 +0530 (Sun, 04 Aug 2013) | 1 line
Create trunk, branches, tags directory structure
------------------------------------------------------------------------
これで、_Jerry’s_作業コピーがリポジトリと同期され、安全に変更をコミットできます。
[jerry@CentOS trunk]$ svn commit -m "Add function to accept input and to display array contents"
Sending trunk/array.c
Transmitting file data .
Committed revision 4.
SVN-間違いを修正
_Jerry_が誤って_array.c_ファイルを変更し、コンパイルエラーが発生しているとします。 今、彼は変更を破棄したいと考えています。 この状況では、「元に戻す」操作が役立ちます。 元に戻す操作は、ファイルまたはディレクトリへのローカル変更を取り消し、競合状態を解決します。
[jerry@CentOS trunk]$ svn status
上記のコマンドは次の結果を生成します。
M array.c
次のように配列を作成してみましょう。
[jerry@CentOS trunk]$ make array
上記のコマンドは次の結果を生成します。
cc array.c -o array
array.c: In function ‘main’:
array.c:26: error: ‘n’ undeclared (first use in this function)
array.c:26: error: (Each undeclared identifier is reported only once
array.c:26: error: for each function it appears in.)
array.c:34: error: ‘arr’ undeclared (first use in this function)
make: ** *[array] Error 1
_Jerry_は、_array.c_ファイルで「元に戻す」操作を実行します。
[jerry@CentOS trunk]$ svn revert array.c
Reverted 'array.c'
[jerry@CentOS trunk]$ svn status
[jerry@CentOS trunk]$
次に、コードをコンパイルします。
[jerry@CentOS trunk]$ make array
cc array.c -o array
復帰操作の後、彼の作業コピーは元の状態に戻ります。 元に戻す操作では、1つのファイルとディレクトリ全体を元に戻すことができます。 ディレクトリを元に戻すには、以下に示すように-Rオプションを使用します。
[jerry@CentOS project_repo]$ pwd
/home/jerry/project_repo
[jerry@CentOS project_repo]$ svn revert -R trunk
これまで、作業コピーに加えられた変更を元に戻す方法を見てきました。 しかし、コミットされたリビジョンを元に戻したい場合はどうでしょう! バージョン管理システムツールでは、リポジトリから履歴を削除できません。 履歴のみを追加できます。 リポジトリからファイルを削除しても発生します。 古いリビジョンを元に戻すには、古いリビジョンで行われた変更をすべて元に戻し、新しいリビジョンをコミットする必要があります。 これは逆マージと呼ばれます。
Jerryが線形検索操作のコードを追加すると仮定します。 確認後、彼は変更をコミットします。
[jerry@CentOS trunk]$ svn diff
Index: array.c
===================================================================
--- array.c (revision 21)
+++ array.c (working copy)
@@ -2,6 +2,16 @@
#define MAX 16
+int linear_search(int* arr, int n, int key)
+{
+ int i;
+ for (i = 0; i < n; ++i)
+ if (arr[i] == key)
+ return i;
+ return -1;
+}
void bubble_sort(int *arr, int n)
{
int i, j, temp, flag = 1;
[jerry@CentOS trunk]$ svn status
? array
M array.c
[jerry@CentOS trunk]$ svn commit -m "Added code for linear search"
Sending trunk/array.c
Transmitting file data .
Committed revision 22.
ジェリーはトムが何をしているのか興味があります。 そこで、彼はSubversionログメッセージをチェックします。
[jerry@CentOS trunk]$ svn log
上記のコマンドは、次の結果を生成します。
------------------------------------------------------------------------
r5 | tom | 2013-08-24 17:15:28 +0530 (Sat, 24 Aug 2013) | 1 line
Add binary search operation
------------------------------------------------------------------------
r4 | jerry | 2013-08-18 20:43:25 +0530 (Sun, 18 Aug 2013) | 1 line
Add function to accept input and to display array contents
ログメッセージを表示した後、ジェリーは自分が重大な間違いをしたことに気付きます。 トムはすでにバイナリ検索操作を実装しているため、線形検索よりも優れています。彼のコードは冗長であり、ジェリーは変更を前のリビジョンに戻す必要があります。 そのため、まずリポジトリの現在のリビジョンを見つけます。 現在、リポジトリはリビジョン22にあり、以前のリビジョンに戻す必要があります。 リビジョン21。
[jerry@CentOS trunk]$ svn up
At revision 22.
[jerry@CentOS trunk]$ svn merge -r 22:21 array.c
--- Reverse-merging r22 into 'array.c':
U array.c
[jerry@CentOS trunk]$ svn commit -m "Reverted to revision 21"
Sending trunk/array.c
Transmitting file data .
Committed revision 23.
SVN-競合の解決
_Tom_は、プロジェクトのREADMEファイルを追加することにしました。 そこで彼は_README_ファイルを作成し、それにTODOリストを追加します。 これを追加すると、ファイルリポジトリはリビジョン6になります。
[tom@CentOS trunk]$ cat README
/*TODO: Add contents in README file*/
[tom@CentOS trunk]$ svn status
? README
[tom@CentOS trunk]$ svn add README
A README
[tom@CentOS trunk]$ svn commit -m "Added README file. Will update it's content in future."
Adding trunk/README
Transmitting file data .
Committed revision 6.
_Jerry_は、リビジョン6にある最新のコードをチェックアウトします。 そしてすぐに彼は働き始めます。 数時間後、_Tom_はREADMEファイルを更新し、変更をコミットします。 変更されたREADMEは次のようになります。
[tom@CentOS trunk]$ cat README
* Supported operations:
1) Accept input
2) Display array elements
[tom@CentOS trunk]$ svn status
M README
[tom@CentOS trunk]$ svn commit -m "Added supported operation in README"
Sending trunk/README
Transmitting file data .
Committed revision 7.
現在、リポジトリはリビジョン7にあり、_Jerry’s_作業コピーは古くなっています。 _Jerry_はREADMEファイルも更新し、変更をコミットしようとします。
Jerry’s READMEファイルは次のようになります。
[jerry@CentOS trunk]$ cat README
* File list
1) array.c Implementation of array operation.
2) README Instructions for user.
[jerry@CentOS trunk]$ svn status
M README
[jerry@CentOS trunk]$ svn commit -m "Updated README"
Sending trunk/README
svn: Commit failed (details follow):
svn: File or directory 'README' is out of date; try updating
svn: resource out of date; try updating
ステップ1:競合を表示する
Subversionは、READMEファイルが最後に更新されてから変更されたことを検出しました。 そのため、_Jerry_は作業コピーを更新する必要があります。
[jerry@CentOS trunk]$ svn up
Conflict discovered in 'README'.
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options:
SubversionはREADMEファイルとの競合があると不平を言っており、Subversionはこれを解決する方法を知りません。 したがって、_Jerry_は_df_オプションを選択して競合を確認します。
[jerry@CentOS trunk]$ svn up
Conflict discovered in 'README'.
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: df
--- .svn/text-base/README.svn-base Sat Aug 24 18:07:13 2013
+++ .svn/tmp/README.tmp Sat Aug 24 18:13:03 2013
@@ -1 +1,11 @@
-/*TODO: Add contents in README file*/
+<<<<<<< .mine
+* File list
+1) array.c Implementation of array operation.
+2) README Instructions for user.
+=======
+* Supported operations:
+1) Accept input
+2) Display array elements
+>>>>>>> .r7
Select: (p) postpone, (df) diff-full, (e) edit, (r) resolved,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options:
ステップ2:競合を延期する
次に、_Jerry_は_postpone(p)_オプションを選択し、競合を解決できるようにします。
Select: (p) postpone, (df) diff-full, (e) edit, (r) resolved,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: p
C README
Updated to revision 7.
Summary of conflicts:
Text conflicts: 1
テキストエディターでREADMEを開いた後、彼はSubversionに_Tom’s_コードと競合マーカー付きのコードの両方が含まれていることに気付きました。
[jerry@CentOS trunk]$ cat README
<<<<<<< .min
* File list
1) array.c Implementation of array operation.
2) README Instructions for user.
=======
* Supported operations:
1) Accept input
2) Display array elements
>>>>>>> .r7
_Jerry_は彼と同様に_Tom’s_の変更を望んでいるため、競合マーカーを含む行を削除するだけです。
したがって、変更されたREADMEは次のようになります。
[jerry@CentOS trunk]$ cat README
* File list
1) array.c Implementation of array operation.
2) README Instructions for user.
* Supported operations:
1) Accept input
2) Display array elements
_Jerry_は競合を解決し、コミットを再試行しました。
[jerry@CentOS trunk]$ svn commit -m "Updated README"
svn: Commit failed (details follow):
svn: Aborting commit: '/home/jerry/project_repo/trunk/README' remains in conflict
[jerry@CentOS trunk]$ svn status
? README.r6
? README.r7
? README.mine
C README
ステップ3:競合を解決する
上記のコミットでは、文字 C はREADMEファイルに競合があることを示しています。 _Jerry_は競合を解決しましたが、Subversionに競合を解決したことを伝えませんでした。 彼はresolveコマンドを使用して、競合の解決についてSubversionに通知します。
[jerry@CentOS trunk]$ svn resolve --accept=working README
Resolved conflicted state of 'README'
[jerry@CentOS trunk]$ svn status
M README
[jerry@CentOS trunk]$ svn commit -m "Updated README"
Sending trunk/README
Transmitting file data .
Committed revision 8.
SVN-タグ
バージョン管理システムは、特定のバージョンのコードに意味のある名前を付けることができるという概念を使用して、_tag_操作をサポートしています。 タグを使用すると、コードの特定のバージョンに説明的で覚えやすい名前を付けることができます。 たとえば、 BASIC_ARRAY_OPERATIONS は revision 4 よりも記憶に残ります。
例で_tag_操作を見てみましょう。 トムは、より簡単にコードにアクセスできるようにタグを作成することにしました。
[tom@CentOS project_repo]$ svn copy --revision=4 trunk/tags/basic_array_operations
上記のコマンドは次の結果を生成します。
A tags/basic_array_operations/array.c
Updated to revision 4.
A tags/basic_array_operations
正常に完了すると、_tags_ディレクトリ内に新しいディレクトリが作成されます。
[tom@CentOS project_repo]$ ls -l tags/
total 4
drwxrwxr-x. 3 tom tom 4096 Aug 24 18:18 basic_array_operations
トムは、コミットする前にそれを再確認したいと考えています。 ステータス操作は、タグ操作が成功したことを示しているため、変更を安全にコミットできます。
[tom@CentOS project_repo]$ svn status
A + tags/basic_array_operations
[tom@CentOS project_repo]$ svn commit -m "Created tag for basic array operations"
Adding tags/basic_array_operations
Committed revision 5.
SVN-分岐
分岐操作は、別の開発ラインを作成します。 誰かが開発プロセスを2つの異なる方向に分岐させたい場合に役立ちます。 バージョン1.0の製品をリリースしたと仮定します。2.0の開発を1.0のバグ修正とは別に維持できるように、新しいブランチを作成することができます。
このセクションでは、ブランチを作成、トラバース、マージする方法を説明します。 ジェリーは紛争のために不満であるため、新しいプライベートブランチを作成することにしました。
[jerry@CentOS project_repo]$ ls
branches tags trunk
[jerry@CentOS project_repo]$ svn copy trunk branches/jerry_branch
A branches/jerry_branch
[jerry@CentOS project_repo]$ svn status
A + branches/jerry_branch
[jerry@CentOS project_repo]$ svn commit -m "Jerry's private branch"
Adding branches/jerry_branch
Adding branches/jerry_branch/README
Committed revision 9.
[jerry@CentOS project_repo]$
現在、ジェリーは私立支店で働いています。 彼は配列のソート操作を追加します。 Jerryの変更されたコードは次のようになります。
[jerry@CentOS project_repo]$ cd branches/jerry_branch/
[jerry@CentOS jerry_branch]$ cat array.c
上記のコマンドは、次の結果を生成します。
#include <stdio.h>
#define MAX 16
void bubble_sort(int *arr, int n)
{
int i, j, temp, flag = 1;
for (i = 1; i < n && flag == 1; ++i) {
flag = 0;
for (j = 0; j < n - i; ++j) {
if (arr[j] > arr[j + 1]) {
flag = 1;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void accept_input(int *arr, int n)
{
int i;
for (i = 0; i < n; ++i)
scanf("%d", &arr[i]);
}
void display(int *arr, int n)
{
int i;
for (i = 0; i < n; ++i)
printf("|%d| ", arr[i]);
printf("\n");
}
int main(void)
{
int i, n, key, ret, arr[MAX];
printf("Enter the total number of elements: ");
scanf("%d", &n);
/*Error handling for array overflow*/
if (n >MAX) {
fprintf(stderr, "Number of elements must be less than %d\n", MAX);
return 1;
}
printf("Enter the elements\n");
accept_input(arr, n);
printf("Array has following elements\n");
display(arr, n);
printf("Sorted data is\n");
bubble_sort(arr, n);
display(arr, n);
return 0;
}
Jerryはコードをコンパイルしてテストし、変更をコミットする準備ができています。
[jerry@CentOS jerry_branch]$ make array
cc array.c -o array
[jerry@CentOS jerry_branch]$ ./array
上記のコマンドは、次の結果を生成します。
Enter the total number of elements: 5
Enter the elements
10
-4
2
7
9
Array has following elements
|10| |-4| |2| |7| |9|
Sorted data is
|-4| |2| |7| |9| |10|
[jerry@CentOS jerry_branch]$ svn status
? array
M array.c
[jerry@CentOS jerry_branch]$ svn commit -m "Added sort operation"
Sending jerry_branch/array.c
Transmitting file data .
Committed revision 10.
一方、トランク上で、トムは検索操作を実装することにしました。 トムは検索操作用のコードを追加し、彼のコードは次のようになります。
[tom@CentOS trunk]$ svn diff
上記のコマンドは、次の結果を生成します。
Index: array.c
===================================================================
--- array.c (revision 10)
+++ array.c (working copy)
@@ -2,6 +2,27 @@
#define MAX 16
+int bin_search(int *arr, int n, int key)
+{
+ int low, high, mid;
+ low = 0;
+ high = n - 1;
+ mid = low + (high - low)/2;
+ while (low <= high) {
+ if (arr[mid] == key)
+ return mid;
+ if (arr[mid] > key)
+ high = mid - 1;
+ else
+ low = mid + 1;
+ mid = low + (high - low)/2;
+ }
+ return -1;
+}
void accept_input(int *arr, int n)
{
int i;
@@ -22,7 +43,7 @@
int main(void)
{
- int i, n, arr[MAX];
+ int i, n, ret, key, arr[MAX];
printf("Enter the total number of elements: ");
scanf("%d", &n);
@@ -39,5 +60,16 @@
printf("Array has following elements\n");
display(arr, n);
+ printf("Enter the element to be searched: ");
+ scanf("%d", &key);
+ ret = bin_search(arr, n, key);
+ if (ret < 0) {
+ fprintf(stderr, "%d element not present in array\n", key);
+ return 1;
+ }
+ printf("%d element found at location %d\n", key, ret + 1);
return 0;
}
確認した後、彼は変更をコミットします。
[tom@CentOS trunk]$ svn status
? array
M array.c
[tom@CentOS trunk]$ svn commit -m "Added search operation"
Sending trunk/array.c
Transmitting file data .
Committed revision 11.
しかし、トムはジェリーが私立支店で何をしていたのか興味があります。
[tom@CentOS trunk]$ cd ../branches/
[tom@CentOS branches]$ svn up
A jerry_branch
A jerry_branch/array.c
A jerry_branch/README
[tom@CentOS branches]$ svn log
------------------------------------------------------------------------
r9 | jerry | 2013-08-27 21:56:51 +0530 (Tue, 27 Aug 2013) | 1 line
Added sort operation
------------------------------------------------------------------------
Subversionのログメッセージを表示すると、トムはJerryが「ソート」操作を実装していることを発見しました。 トムはバイナリ検索アルゴリズムを使用して検索操作を実装しました。常にソートされた順序でデータを期待します。 しかし、ユーザーが並べ替えられていない順序でデータを提供した場合はどうなりますか? その場合、バイナリ検索操作は失敗します。 そこで彼は、検索操作の前にデータをソートするためにジェリーのコードを使用することにしました。 そこで、彼はSubversionにJerryのブランチのコードをトランクにマージするように依頼します。
[tom@CentOS trunk]$ pwd
/home/tom/project_repo/trunk
[tom@CentOS trunk]$ svn merge ../branches/jerry_branch/
--- Merging r9 through r11 into '.':
U array.c
マージ後、array.cは次のようになります。
[tom@CentOS trunk]$ cat array.c
上記のコマンドは、次の結果を生成します。
#include <stdio.h>
#define MAX 16
void bubble_sort(int *arr, int n)
{
int i, j, temp, flag = 1;
for (i = 1; i < n && flag == 1; ++i) {
flag = 0;
for (j = 0; j < n - i; ++j) {
if (arr[j] > arr[j + 1]) {
flag = 1;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int bin_search(int *arr, int n, int key)
{
int low, high, mid;
low = 0;
high = n - 1;
mid = low + (high - low)/2;
while (low <= high) {
if (arr[mid] == key)
return mid;
if (arr[mid] > key)
high = mid - 1;
else
low = mid + 1;
mid = low + (high - low)/2;
}
return -1;
}
void accept_input(int *arr, int n)
{
int i;
for (i = 0; i < n; ++i)
scanf("%d", &arr[i]);
}
void display(int *arr, int n)
{
int i;
for (i = 0; i < n; ++i)
printf("|%d| ", arr[i]);
printf("\n");
}
int main(void)
{
int i, n, ret, key, arr[MAX];
printf("Enter the total number of elements: ");
scanf("%d", &n);
/*Error handling for array overflow*/
if (n > MAX) {
fprintf(stderr, "Number of elements must be less than %d\n", MAX);
return 1;
}
printf("Enter the elements\n");
accept_input(arr, n);
printf("Array has following elements\n");
display(arr, n);
printf("Sorted data is\n");
bubble_sort(arr, n);
display(arr, n);
printf("Enter the element to be searched: ");
scanf("%d", &key);
ret = bin_search(arr, n, key);
if (ret < 0) {
fprintf(stderr, "%d element not present in array\n", key);
return 1;
}
printf("%d element found at location %d\n", key, ret + 1);
return 0;
}
コンパイルとテストの後、トムは自分の変更をリポジトリにコミットします。
[tom@CentOS trunk]$ make array
cc array.c -o array
[tom@CentOS trunk]$ ./array
Enter the total number of elements: 5
Enter the elements
10
-2
8
15
3
Array has following elements
|10| |-2| |8| |15| |3|
Sorted data is
|-2| |3| |8| |10| |15|
Enter the element to be searched: -2
-2 element found at location 1
[tom@CentOS trunk]$ svn commit -m "Merge changes from Jerry's code"
Sending trunk
Sending trunk/array.c
Transmitting file data .
Committed revision 12.
[tom@CentOS trunk]$