Svn 简明教程
SVN Basic Concepts
What is Version Control System?
Version Control System (VCS) 是一款软件,可以帮助软件开发人员共同工作并维护其工作的完整历史记录。
Version Control System (VCS) is a software that helps software developers to work together and maintain a complete history of their work.
Following are the goals of a Version Control System.
Following are the goals of a Version Control System.
-
Allow developers to work simultaneously.
-
Do not overwrite each other’s changes.
-
Maintain history of every version of everything.
A VCS is divided into two categories.
A VCS is divided into two categories.
-
Centralized Version Control System (CVCS), and
-
Distributed/Decentralized Version Control System (DVCS).
在本教程中,我们将仅关注集中式版本控制系统,尤其是 Subversion 。Subversion 属于集中式版本控制系统,这意味着它使用中央服务器来存储所有文件并支持团队协作。
In this tutorial, we will concentrate only on the Centralized Version Control System and especially Subversion. Subversion falls under centralized version control system, meaning that it uses central server to store all files and enables team collaboration.
Version Control Terminologies
让我们首先讨论本教程中将使用的一些术语。
Let us start by discussing some of the terms that we will be using in this tutorial.
-
Repository: A repository is the heart of any version control system. It is the central place where developers store all their work. Repository not only stores files but also the history. Repository is accessed over a network, acting as a server and version control tool acting as a client. Clients can connect to the repository, and then they can store/retrieve their changes to/from repository. By storing changes, a client makes these changes available to other people and by retrieving changes, a client takes other people’s changes as a working copy.
-
Trunk: The trunk is a directory where all the main development happens and is usually checked out by developers to work on the project.
-
Tags : The tags directory is used to store named snapshots of the project. Tag operation allows to give descriptive and memorable names to specific version in the repository. For example, LAST_STABLE_CODE_BEFORE_EMAIL_SUPPORT is more memorable than Repository UUID: 7ceef8cb-3799-40dd-a067-c216ec2e5247 and Revision: 13
-
Branches: Branch operation is used to create another line of development. It is useful when you want your development process to fork off into two different directions. For example, when you release version 5.0, you might want to create a branch so that development of 6.0 features can be kept separate from 5.0 bug-fixes.
-
Working copy: Working copy is a snapshot of the repository. The repository is shared by all the teams, but people do not modify it directly. Instead each developer checks out the working copy. The working copy is a private workplace where developers can do their work remaining isolated from the rest of the team.
-
Commit changes: Commit is a process of storing changes from private workplace to central server. After commit, changes are made available to all the team. Other developers can retrieve these changes by updating their working copy. Commit is an atomic operation. Either the whole commit succeeds or is rolled back. Users never see half finished commit.
SVN Environment Setup
SVN Installation
Subversion 是一个流行的开源版本控制工具。它开源且可以通过互联网免费获得。它默认附带在大多数的 GNU/Linux 发行版中,所以它可能已经在你的系统中安装。要检查它是否已安装,可使用以下命令。
Subversion is a popular open-source version control tool. It is open-source and available for free over the internet. It comes by default with most of the GNU/Linux distributions, so it might be already installed on your system. To check whether it is installed or not use following command.
[jerry@CentOS ~]$ svn --version
如果没有安装 Subversion 客户端,那么这个命令将报告错误,否则它将显示已安装软件的版本。
If Subversion client is not installed, then command will report error, otherwise it will display the version of the installed software.
[jerry@CentOS ~]$ svn --version
-bash: svn: command not found
如果你正在使用基于 RPM 的 GNU/Linux,那么使用 yum 命令进行安装。成功安装之后,执行 svn --version 命令。
If you are using RPM-based GNU/Linux, then use yum command for installation. After successful installation, execute the svn --version command.
[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 命令进行安装。
And if you are using Debian-based GNU/Linux, then use apt command for installation.
[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 Setup
我们已经看到了如何在 GNU/Linux 上安装 Subversion 客户端。让我们看看如何创建一个新的仓库并允许用户访问。
We have seen how to install Subversion client on GNU/Linux. Let us see how to create a new repository and allow access to the users.
我们必须在服务器上安装 Apache httpd * module and *svnadmin 工具。
On server we have to install Apache httpd * module and *svnadmin tool.
[jerry@CentOS ~]$ su -
Password:
[root@CentOS ~]# yum install mod_dav_svn subversion
这个 mod_dav_svn 包允许使用 HTTP 通过 Apache httpd 服务器访问仓库, subversion 包安装 svnadmin 工具。
The mod_dav_svn package allows access to a repository using HTTP, via Apache httpd server and subversion package installs svnadmin tool.
Subversion 从 /etc/httpd/conf.d/subversion.conf 文件读取它的配置。在添加配置之后, subversion.conf 文件看起来如下:
The subversion reads its configuration from /etc/httpd/conf.d/subversion.conf file. After adding configuration, subversion.conf file looks as follows:
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 用户的基本验证的用户名和密码。如果密码文件已存在,“-c”选项会创建密码文件,它将被覆盖。这就是为什么只在第一次使用“-c”选项。“-m”选项为密码启用 MD5 加密。
Let us create Subversion users and grant them access to the repository. htpasswd command is used to create and update the plain-text files which are used to store usernames and passwords for basic authentication of HTTP users. '-c' options creates password file, if password file already exists, it is overwritten. That is why use '-c' option only the first time. '-m' option enables MD5 encryption for passwords.
User Setup
让我们创建用户 tom 。
Let us create user tom.
[root@CentOS ~]# htpasswd -cm /etc/svn-users tom
New password:
Re-type new password:
Adding password for user tom
让我们创建用户 jerry 。
Let us create user 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)。
Create Subversion parent directory to store all the work (see /etc/httpd/conf.d/subversion.conf).
[root@CentOS ~]# mkdir /var/www/svn
[root@CentOS ~]# cd /var/www/svn/
Repository Setup
使用 Gemini 项目创建一个名为 project_repo 的项目存储库。svnadmin 命令将创建一个新的存储库以及存有元数据的一些其他目录。
Create a project repository named project_repo. svnadmin command will create a new repository and a few other directories inside that to store the metadata.
[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
让我们更改该存储库的用户和组所有权。
Let us change the user and group ownership of the repository.
[root@CentOS svn]# chown -R apache.apache project_repo/
使用 SELinux 状态工具检查 SELinux 是否启用。
Check whether SELinux is enabled or not using the SELinux status tool.
[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 安全环境。
For our server, SELinux is enabled, so we have to change the SELinux security context.
[root@CentOS svn]# chcon -R -t httpd_sys_content_t /var/www/svn/project_repo/
若允许通过 HTTP 执行提交,请执行以下命令。
To allow commits over HTTP, execute the following command.
[root@CentOS svn]# chcon -R -t httpd_sys_rw_content_t /var/www/svn/project_repo/
重启 Apache 服务器,完成 Apache 服务器配置。
Restart the Apache server and we are done with the configuration of Apache server.
[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 文件中。
We have configured the Apache server successfully, now we will configure the repository. To provide repository access to only authentic users and to use the default authorization file; append the following lines to project_repo/conf/svnserve.conf file.
anon-access = none
authz-db = authz
按照惯例,每个 Subversion 项目都有 trunk, tags, 和 branches 目录,直接位于项目根目录下方。
Conventionally, every Subversion project has trunk, tags, and branches directories directly under the project’s root directory.
主干是所有主要开发发生的地方,开发人员通常将其检出以处理该项目。
The trunk is a directory where all the main development happens and is usually checked out by the developers to work on the project.
tags 目录用于存储项目命名的快照。在创建正式发行版时,团队将标记分配给发布版的代码。
The tags directory is used to store named snapshots of the project. When creating a production release, the team will tag the code that goes into the release.
branches 目录在您需要支持不同的开发线时使用。
The branches directory is used when you want to pursue different lines of development.
让我们在项目存储库下创建主干、标签和分支目录结构。
Let us create the trunk, tags, and branches directory structure under the project repository.
[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 导入目录到存储库中。
Now import the directories from /tmp/svn-template to the repository.
[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 访问。从现在开始,他们可以对该存储库执行所有受支持的操作。
This is done! We have successfully created the repository and allowed access to Tom and Jerry. From now, they can perform all the supported operations to the repository.
SVN Life Cycle
本章讨论了版本控制系统的生命周期。在之后的章节中,我们将了解每项操作的 Subversion 命令。
The life cycle of a Version Control System is discussed in this chapter. In later chapters, we will see the Subversion command for each operation.
Create Repository:
存储库是开发人员存储所有其工作的中心区域。存储库不仅存储文件,还存储有关更改的历史记录。这意味着它维护了对文件所做更改的历史记录。
The repository is a central place where developers store all their work. Repository not only stores files, but also the history about changes. Which means it maintains a history of the changes made in the files.
“创建”操作用于创建新的存储库。大多数情况下,该操作只执行一次。在您创建新的存储库时,您的 VCS 将期望您说出某些内容来识别它,例如您希望将它创建在哪里,或应该为该存储库命名什么。
The 'create' operation is used to create a new repository. Most of the times this operation is done only once. When you create a new repository, your VCS will expect you to say something to identify it, such as where you want it to be created, or what name should be given to the repository.
Checkout
“签出”操作用于从存储库创建工作副本。工作副本是开发人员进行更改的私人工作空间,稍后将这些更改提交到存储库中。
'Checkout' operation is used to create a working copy from the repository. Working copy is a private workplace where developers do their changes, and later on, submit these changes to the repository.
Update
顾名思义,“更新”操作用于更新工作副本。该操作使工作副本与存储库同步。由于存储库由所有团队共享,其他开发人员可以提交其更改,而您的工作副本变得旧了。
As the name suggests, 'update' operation is used to update working copy. This operation synchronizes the working copy with the repository. As repository is shared by all the teams other developers can commit their changes and your working copy becomes older.
让我们假设 Tom 和 Jerry 是正在进行一个项目的两位开发人员。两人从存储库检出最新版本并开始工作。此时,他们的工作副本与存储库完全同步。Jerry 非常有效率地完成了他的工作并将他的更改提交到了存储库。
Let us suppose Tom and Jerry are the two developers working on a project. Both check out the latest version from the repository and start working. At this point, their working copies are completely synchronized with the repository. Jerry completes his work very efficiently and commits his changes to the repository.
现在,Tom 的工作副本已过时。更新操作将从存储库拉取 Jerry 的最新更改,并将更新 Tom 的工作副本。
Now Tom’s working copy is out of date. Update operation will pull Jerry’s latest changes from the repository and will update Tom’s working copy.
Perform Changes
在签出后,可以执行各种操作来执行更改。编辑是最常见的操作。可以编辑现有文件以添加/删除文件中的内容。
After the checkout, one can do various operations to perform changes. Edit is the most common operation. One can edit the existing file to add/remove contents from the file.
可以添加文件/目录。但是,这些文件/目录不会立即成为存储库的一部分,而是会被添加至待定更改列表,并在提交操作后成为存储库的一部分。
One can add files/directories. But immediately these files/directories do not become a part of the repository, instead they are added to the pending change-list and become a part of the repository after the commit operation.
同样,可以删除文件/目录。删除操作会立即从工作副本中删除文件,但文件的实际删除将被添加到待定更改列表,并在提交操作后对存储库进行更改。
Similarly one can delete files/directories. Delete operation immediately deletes file from the working copy, but actual deletion of the file is added to the pending change-list and changes are made to the repository after the commit operation.
“重命名”操作会更改文件/目录的名称。“移动”操作用于在存储库树中将文件/目录从一个位置移动到另一个位置。
'Rename' operation changes the name of the file/directory. 'Move' operation is used to move files/directories from one place to another in a repository tree.
Review Changes
在签出工作副本或更新工作副本时,工作副本将与存储库完全同步。但是,在对工作副本进行更改时,它将比存储库更新。在“提交”操作之前,最好检查你的更改。
When you check out the working copy or update the working copy, then your working copy is completely synchronized with the repository. But as you do changes to your working copy, it becomes newer than the repository. And it is a good practice to review your changes before the 'commit' operation.
“状态”操作会列出已对工作副本进行的修改。“状态”操作用于查看待定更改列表。
'Status' operation lists the modifications that have been made to the working copy. As we have mentioned before, whenever you do changes in the working copy all these changes become a part of the pending change-list. And the 'status' operation is used to see the pending change-list.
“状态”操作仅提供更改列表,但不提供详细信息。可以使用 diff 操作查看对工作副本所做的修改的详细信息。
'Status' operation only provides a list of changes but not the details about them. One can use diff operation to view the details of the modifications that have been made to the working copy.
Fix Mistakes
让我们假设你已对工作副本进行了更改,但现在,你想放弃这些更改。在这种情况下,“还原”操作将有所帮助。
Let us suppose one has made changes to his working copy, but now, he wants to throw away these changes. In this situation, 'revert' operation will help.
还原操作会还原对工作副本所做的修改。可以还原一个或多个文件/目录。也可以还原整个工作副本。在这种情况下,“还原”操作将销毁待定更改列表,并将工作副本恢复到其原始状态。
Revert operation reverts the modifications that have been made to the working copy. It is possible to revert one or more files/directories. Also it is possible to revert the whole working copy. In this case, the 'revert' operation will destroy the pending change-list and will bring the working copy back to its original state.
Resolve Conflicts:
冲突可能发生在合并时。“合并”操作会自动处理所有可以安全完成的操作。其他所有内容都被视为冲突。例如,“hello.c”文件在一个分支中被修改,而在另一个分支中删除。这种情况下,需要一个人做出决定。“解决”操作用于帮助用户理清思路,并通知 VCS 关于处理冲突的方法。
Conflicts can occur at the time of merging. 'Merge' operation automatically handles everything that can be done safely. Everything else is considered as conflict. For example, "hello.c" file was modified in branch and deleted in another branch. Such a situation requires a person to make the decision. The 'resolve' operation is used to help the user figure out things and to inform VCS about the ways of handling the conflicts.
Commit Changes
“提交”操作用于将工作副本中的更改应用到存储库。此操作会修改存储库,其他开发人员可以通过更新其工作副本来查看这些更改。
'Commit' operation is used to apply changes from the working copy to the repository. This operation modifies the repository and other developers can see these changes by updating their working copy.
在提交之前,必须将文件/目录添加到待定更改列表。这是更改等待提交的地方。在提交时,我们通常会提供一条日志消息以解释某人为何进行更改。此日志消息成为存储库历史的一部分。提交是一个原子操作,这意味着整个提交要么成功,要么回滚。用户永远不会看到半成品提交。
Before commit, one has to add files/directories to the pending change-list. This is the place where changes wait to be committed. With commit, we usually provide a log message to explain why someone made changes. This log message becomes a part of the history of the repository. Commit is an atomic operation, which means either the entire commit succeeds or it is rolled back. Users never see half-finished commit.
SVN Checkout Process
Subversion 提供检出命令以从存储库检出一个工作副本。以下命令将在当前工作目录中创建一个新目录,名为 project_repo。不必担心存储库 URL,因为大多数情况下,它已由具有适当访问权限的 subversion 管理员提供了。
Subversion provides the checkout command to check out a working copy from a repository. Below command will create a new directory in the current working directory with the name project_repo. Don’t bother about the repository URL, as most of the time, it is already provided by the subversion administrator with appropriate access.
[tom@CentOS ~]$ svn checkout http://svn.server.com/svn/project_repo --username=tom
上述命令将产生以下结果。
The above command will produce the following result.
A project_repo/trunk
A project_repo/branches
A project_repo/tags
Checked out revision 1.
每次成功检出操作后,都会打印出修订号。如果你想查看有关存储库的更多信息,请执行 info 命令。
After every successful checkout operation, the revision number will get printed. If you want to view more information about the repository, then execute the info command.
[tom@CentOS trunk]$ pwd
/home/tom/project_repo/trunk
[tom@CentOS trunk]$ svn info
上述命令将产生以下结果。
The above command will produce the following result.
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 Perform Changes
Jerry 检出了存储库的最新版本,并开始了一个项目。他在 trunk 目录中创建了 array.c 文件。
Jerry checks out the latest version of the repository and starts working on a project. He creates array.c file inside the trunk directory.
[jerry@CentOS ~]$ cd project_repo/trunk/
[jerry@CentOS trunk]$ cat array.c
上述命令将产生以下结果。
The above command will produce the following result.
#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;
}
他在提交前想要测试他的代码。
He wants to test his code before commit.
[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|
他已经编译并测试了他的代码,一切按预期工作,现在是时候提交更改了。
He compiled and tested his code and everything is working as expected, now it is time to commit changes.
[jerry@CentOS trunk]$ svn status
? array.c
? array
Subversion 在文件名之前显示“?”,因为不知道如何处理这些文件。
Subversion is showing '?' in front of filenames because it doesn’t know what to do with these files.
在提交之前,Jerry 需要将此文件添加到挂起的变更列表中。
Before commit, Jerry needs to add this file to the pending change-list.
[jerry@CentOS trunk]$ svn add array.c
A array.c
让我们使用“status”操作进行检查。Subversion 在 array.c 之前显示 A ,即该文件已成功添加到挂起的变更列表中。
Let us check it with the 'status' operation. Subversion shows A before array.c, it means, the file is successfully added to the pending change-list.
[jerry@CentOS trunk]$ svn status
? array
A array.c
若要将 array.c 文件存储到代码库中,请使用带有 -m 选项和后续提交消息的 commit 命令。如果省略 -m 选项,Subversion 会调出文本编辑器,您可以在其中键入多行消息。
To store array.c file to the repository, use the commit command with -m option followed by commit message. If you omit -m option Subversion will bring up the text editor where you can type a multi-line message.
[jerry@CentOS trunk]$ svn commit -m "Initial commit"
Adding trunk/array.c
Transmitting file data .
Committed revision 2.
现在,array.c 文件已成功添加到代码库中,并且版本号增加了 1。
Now array.c file is successfully added to the repository, and the revision number is incremented by one.
SVN Review Changes
Jerry 已将 array.c 文件添加到代码库中。Tom 也签出了最新代码并开始工作。
Jerry already added array.c file to the repository. Tom also checks out the latest code and starts working.
[tom@CentOS ~]$ svn co http://svn.server.com/svn/project_repo --username=tom
上述命令将产生以下结果。
Above command will produce the following result.
A project_repo/trunk
A project_repo/trunk/array.c
A project_repo/branches
A project_repo/tags
Checked out revision 2.
但他发现,有人已添加了代码。因此,他很好奇是谁这样做的,于是使用以下命令查看日志消息以了解详细信息:
But, he found that someone has already added the code. So he is curious about who did that and he checks the log message to see more details using the following command:
[tom@CentOS trunk]$ svn log
上述命令将产生以下结果。
Above command will produce the following result.
------------------------------------------------------------------------
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 的代码时,他立即注意到其中的一个 bug。Jerry 未检查数组溢出,这可能导致严重问题。因此,Tom 决定修复此问题。修改后,array.c 如下所示。
When Tom observes Jerry’s code, he immediately notices a bug in that. Jerry was not checking for array overflow, which could cause serious problems. So Tom decides to fix this problem. After modification, array.c will look like this.
#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 希望使用 status 操作 查看挂起的变更列表。
Tom wants to use the status operation to see the pending change-list.
[tom@CentOS trunk]$ svn status
M array.c
array.c 文件已修改,这就是为什么 Subversion 在文件名之前显示 M 字符的原因。接下来,Tom 编译并测试了他的代码,且该代码运行良好。在提交更改之前,他想通过查看他所做的更改来仔细检查。
array.c file is modified, that’s why Subversion shows M letter before file name. Next Tom compiles and tests his code and it is working fine. Before committing changes, he wants to double-check it by reviewing the changes that he made.
[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 has added a few lines in the array.c file, that’s why Subversion shows * + * sign before new lines. Now he is ready to commit his changes.
[tom@CentOS trunk]$ svn commit -m "Fix array overflow problem"
上述命令将产生以下结果。
The above command will produce the following result.
Sending trunk/array.c
Transmitting file data .
Committed revision 3.
Tom 的更改已成功提交到代码库中。
Tom’s changes are successfully committed to the repository.
SVN Update Process
Jerry 已提交第一个版本的代码。但他认为他应该编写两个函数来接受输入并显示数组内容。修改后,array.c 如下所示。
Jerry had committed the first version of the code. But he thinks that he should write two functions to accept input and to display array contents. After modification, array.c looks as follows.
#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 compiles and tests his code and is ready to commit changes. Before that, he wants to review the changes using the following command.
[jerry@CentOS trunk]$ svn diff
上述命令将产生以下结果。
The above command will produce the following result.
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 尝试使用以下命令提交更改:
For the new added lines, Subversion shows + sign before line and for removed line it shows - sign. Now, Jerry tries to commit the changes using the following command:
[jerry@CentOS trunk]$ svn commit -m "Add function to accept input and to display array contents"
上述命令将产生以下结果。
The above command will produce the following result.
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
Subversion 不允许提交 Jerry 的更改,因为 Tom 已修改代码库,而 Jerry 的工作副本已过时。为避免相互覆盖更改,Subversion 会使此操作失败。Jerry 必须在提交他的更改之前更新工作副本。因此,他按照以下所示使用 update 命令。
Subversion is not allowing to commit Jerry’s changes, because Tom has already modified the repository and Jerry’s working copy is out of date. To avoid overwriting each other’s changes, Subversion fails this operation. Jerry must update working copy before committing his changes. So he uses update command as shown below.
[jerry@CentOS trunk]$ svn update
G array.c
Updated to revision 3.
Subversion 在文件名之前显示字母 G ,表示此文件已合并。
Subversion is showing the letter G before filename, which means this file has been merged.
[jerry@CentOS trunk]$ svn diff
上述命令将产生以下结果。
The above command will produce the following result.
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 的更改,但 array.c 文件已合并。如果您仔细观察,Subversion 现在显示版本号 3。在之前的输出中,显示的是版本号 2。只需查看是谁对该文件进行了更改以及出于什么目的。
Subversion is showing only Jerry’s changes, but array.c file is merged. If you observe carefully, Subversion is now showing revision number 3. In the previous output, it was showing revision number 2. Just review who made changes in the file and for what purpose.
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 的工作副本已与存储库同步,他可以安全地提交更改。
Now Jerry’s working copy is synchronized with the repository and he can safely commit his changes.
[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 Fix Mistakes
假设 Jerry 意外修改了 array.c 文件,并且出现了编译错误。现在他要抛弃更改。在这种情况下,“恢复”操作将有所帮助。“恢复”操作将撤销对文件或目录的任何本地更改,并解决任何冲突的状态。
Suppose Jerry accidently modifies array.c file and he is getting compilation errors. Now he wants to throw away the changes. In this situation, 'revert' operation will help. Revert operation will undo any local changes to a file or directory and resolve any conflicted states.
[jerry@CentOS trunk]$ svn status
上述命令将产生以下结果。
Above command will produce the following result.
M array.c
让我们尝试按照以下方式创建数组:
Let’s try to make array as follows:
[jerry@CentOS trunk]$ make array
上述命令将产生以下结果。
Above command will produce the following result.
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 performs 'revert' operation on array.c file.
[jerry@CentOS trunk]$ svn revert array.c
Reverted 'array.c'
[jerry@CentOS trunk]$ svn status
[jerry@CentOS trunk]$
现在编译代码。
Now compile the code.
[jerry@CentOS trunk]$ make array
cc array.c -o array
在恢复操作之后,他的工作副本将恢复到其初始状态。“恢复”操作可以恢复单个文件以及完整的目录。要恢复目录,请使用 -R 选项,如下所示。
After the revert operation, his working copy is back to its original state. Revert operation can revert a single file as well as a complete directory. To revert a directory, use -R option as shown below.
[jerry@CentOS project_repo]$ pwd
/home/jerry/project_repo
[jerry@CentOS project_repo]$ svn revert -R trunk
到目前为止,我们已经了解了如何恢复已对工作副本进行的更改。但是,如果你想要恢复已提交的修订版本该怎么办呢!版本控制系统工具不允许从存储库中删除历史记录。我们只能追加历史记录。即使从存储库中删除文件,也会发生这种情况。要撤消旧版本,我们必须还原旧版本中所做的所有更改,然后提交一个新版本。这称为反向合并。
Till now, we have seen how to revert changes, which has been made to the working copy. But what if you want to revert a committed revision! Version Control System tool doesn’t allow to delete history from the repository. We can only append history. It will happen even if you delete files from the repository. To undo an old revision, we have to reverse whatever changes were made in the old revision and then commit a new revision. This is called a reverse merge.
让我们假设 Jerry 添加了线性搜索操作的代码。验证后,他提交了自己的更改。
Let us suppose Jerry adds a code for linear search operation. After verification he commits his changes.
[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.
Jerry 很想知道 Tom 在做什么。于是他检查了 Subversion 日志消息。
Jerry is curious about what Tom is doing. So he checks the Subversion log messages.
[jerry@CentOS trunk]$ svn log
上述命令将产生以下结果。
The above command will produce the following result.
------------------------------------------------------------------------
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
查看日志消息后,Jerry 意识到自己犯了一个严重的错误。因为 Tom 已经实现了二进制搜索操作,它比线性搜索更好;他的代码是多余的,现在 Jerry 必须将他的更改还原到以前的修订版本。因此,首先找到存储库的当前修订版本。当前,存储库位于修订版本 22,我们必须将其恢复到以前的修订版本,即修订版本 21。
After viewing the log messages, Jerry realizes that he did a serious mistake. Because Tom already implemented binary search operation, which is better than the linear search; his code is redundant, and now Jerry has to revert his changes to the previous revision. So, first find the current revision of the repository. Currently, the repository is at revision 22 and we have to revert it to the previous revision, i.e. revision 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.
Tom 决定为他们的项目添加一个 README 文件。于是,他创建了 README 文件并在其中添加了待办事项列表。添加此内容后,文件存储库位于修订版本 6。
Tom decides to add a README file for their project. So he creates the README file and adds TODO list into that. After adding this, the file repository is at revision 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 将如下所示。
Jerry checks out the latest code which is at revision 6. And immediately he starts working. After a few hours, Tom updates README file and commits his changes. The modified README will look like this.
[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 的工作副本已过期。Jerry 还更新了 README 文件并尝试提交他的更改。
Now, the repository is at revision 7 and Jerry’s working copy is out of date. Jerry also updates the README file and tries to commit his changes.
Jerry 的 README 文件如下所示。
Jerry’s README file looks like this.
[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
Step 1: View Conflicts
Subversion 检测到自上次更新以来 README 文件已更改。因此,Jerry 必须更新他的工作副本。
Subversion has detected that the README file has changed since last updated. So, Jerry has to update his working copy.
[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 选项来查看冲突。
Subversion is complaining that there is a conflict with the README file, and Subversion does not know how to solve this. So Jerry chooses the df option to review the conflict.
[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:
Step 2: Postpone Conflicts
接下来,Jerry 选择了延期 (p) 选项,以便他可以解决冲突。
Next Jerry chooses the postpone(p) options, so that he can resolve the conflict.
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 的代码和他的代码以及冲突标记。
After opening the README in text editor he realizes that Subversion has included both Tom’s code and his code with conflict markers.
[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 的更改以及他的更改,于是他只删除了包含冲突标记的行。
Jerry wants Tom’s changes as well as his, so he just removes the lines containing the conflict markers.
因此,修改后的 README 看起来像这样。
So, the modified README will look like this.
[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 resolved the conflict and he retries commit.
[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
Step 3: Resolve Conflicts
在上述提交中,字母 C 指示 README 文件中存在冲突。Jerry 解决了冲突,但没有告诉 Subversion 他已解决冲突。他使用 resolve 命令通知 Subversion 关于冲突解决。
In the above commit, the letter C indicates that there is a conflict in the README file. Jerry resolved the conflict but didn’t tell Subversion that he had resolved the conflict. He uses the resolve command to inform Subversion about the conflict resolution.
[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 Tags
版本控制系统通过使用可以对特定版本的代码指定有意义的名称的概念来支持标签操作。标签允许为特定版本的代码提供描述性和易记性。例如, BASIC_ARRAY_OPERATIONS 比 revision 4 更容易记住。
Version Control System supports the tag operation by using that concept that one can give meaningful name to a specific version of the code. Tag allows to give descriptive and memorable names to specific version of code. For example BASIC_ARRAY_OPERATIONS is more memorable than revision 4.
让我们通过一个示例来看看标签操作。Tom 决定创建一个标签,以便他可以更轻松地访问代码。
Let us see tag operation with an example. Tom decides to create a tag so that he can access the code more easily.
[tom@CentOS project_repo]$ svn copy --revision=4 trunk/ tags/basic_array_operations
上述命令将产生以下结果。
Above command will produce the following result.
A tags/basic_array_operations/array.c
Updated to revision 4.
A tags/basic_array_operations
成功完成后,将在 tags 目录内创建一个新目录。
Upon successful completion, the new directory will be created inside the tags directory.
[tom@CentOS project_repo]$ ls -l tags/
total 4
drwxrwxr-x. 3 tom tom 4096 Aug 24 18:18 basic_array_operations
Tom 在提交之前希望再次检查一下。状态操作显示标签操作成功,因此他可以安全地提交自己的更改。
Tom wants to double-check it before commit. Status operation is showing that the tag operation is successful, so he can safely commit his changes.
[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 Branching
分支操作创建另一条开发线。当有人希望开发过程分支到两个不同的方向时,它非常有用。假设你发布了 1.0 版本的产品,你可能希望创建一个新分支,以便 2.0 的开发可以与 1.0 的错误修复分开进行。
Branch operation creates another line of development. It is useful when someone wants the development process to fork off into two different directions. Let us suppose you have released a product of version 1.0, you might want to create new branch so that development of 2.0 can be kept separate from 1.0 bug fixes.
在本节中,我们将看到如何创建、遍历和合并分支。Jerry 对冲突不满意,因此他决定创建一个新的私有分支。
In this section, we will see how to create, traverse and merge branch. Jerry is not happy because of the conflict, so he decides to create a new private branch.
[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 修改后的代码看起来像这样。
Now Jerry is working in his private branch. He adds sort operation for the array. Jerry’s modified code looks like this.
[jerry@CentOS project_repo]$ cd branches/jerry_branch/
[jerry@CentOS jerry_branch]$ cat array.c
上述命令将产生以下结果。
The above command will produce the following result.
#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 compiles and tests his code and is ready to commit his changes.
[jerry@CentOS jerry_branch]$ make array
cc array.c -o array
[jerry@CentOS jerry_branch]$ ./array
上述命令将产生以下结果。
The above command will produce the following result.
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 决定实现搜索操作。Tom 添加了搜索操作的代码,他的代码看起来像这样。
Meanwhile, over in the trunk, Tom decides to implement search operation. Tom adds code for search operation and his code looks like this.
[tom@CentOS trunk]$ svn diff
上述命令将产生以下结果。
The above command will produce the following result.
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;
}
审阅后,他提交了自己的更改。
After reviewing, he commits his changes.
[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 好奇 Jerry 在他的私有分支中做了什么。
But Tom is curious about what Jerry has been doing in his private branch.
[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 的日志消息,Tom 发现 Jerry 实现了“排序”操作。Tom 使用二分查找算法实现了搜索操作,它总是期望数据按已排序顺序显示。但如果用户提供未排序顺序的数据会怎样?在这种情况下,二分查找操作将会失败。因此,他决定在搜索操作之前使用 Jerry 的代码对数据进行排序。因此,他要求 Subversion 将代码从 Jerry 的分支合并到主干中。
By viewing the Subversion’s log message, Tom found that Jerry implemented 'sort' operation. Tom implemented search operation using binary search algorithm, it always expects data in sorted order. But what if the user provides data in an unsorted order? In that situation, binary search operation will fail. So he decides to take Jerry’s code to sort data before search operation. So he asks Subversion to merge code from Jerry’s branch into trunk.
[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 将看起来像这样。
After merging, array.c will look like this.
[tom@CentOS trunk]$ cat array.c
上述命令将产生以下结果。
The above command will produce the following result.
#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 将更改提交到存储库。
After compilation and testing, Tom commits his changes to the repository.
[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]$