SVN - Краткое руководство

Что такое система контроля версий?

Version Control System (VCS) - это программное обеспечение, которое помогает разработчикам программного обеспечения работать вместе и вести полную историю своей работы.

Following are the goals of a Version Control System.

  • Разрешить разработчикам работать одновременно.
  • Не перезаписывайте изменения друг друга.
  • Сохраняйте историю каждой версии всего.

A VCS is divided into two categories.

  • Централизованная система контроля версий (CVCS) и
  • Распределенная / децентрализованная система контроля версий (DVCS).

В этом руководстве мы сосредоточимся только на Централизованной системе контроля версий и особенно Subversion. Subversion подпадает под централизованную систему контроля версий, что означает, что он использует центральный сервер для хранения всех файлов и обеспечивает совместную работу команды.

Терминология контроля версий

Давайте начнем с обсуждения некоторых терминов, которые мы будем использовать в этом руководстве.

  • Repository:Репозиторий - это сердце любой системы контроля версий. Это центральное место, где разработчики хранят всю свою работу. В репозитории хранятся не только файлы, но и история. Доступ к репозиторию осуществляется по сети, он действует как сервер и инструмент контроля версий, выступая в роли клиента. Клиенты могут подключаться к репозиторию, а затем они могут сохранять / извлекать свои изменения в / из репозитория. Сохраняя изменения, клиент делает эти изменения доступными для других людей, а, получая изменения, клиент принимает чужие изменения в качестве рабочей копии.

  • Trunk: Магистраль - это каталог, в котором происходит вся основная разработка, который обычно проверяется разработчиками для работы над проектом.

  • Tags: Каталог тегов используется для хранения именованных снимков проекта. Операция с тегами позволяет давать описательные и запоминающиеся имена конкретной версии в репозитории.

    Например, LAST_STABLE_CODE_BEFORE_EMAIL_SUPPORT запоминается лучше, чем

    UUID репозитория: 7ceef8cb-3799-40dd-a067-c216ec2e5247 и

    Редакция: 13

  • Branches:Операция ветвления используется для создания еще одного направления развития. Это полезно, когда вы хотите, чтобы процесс разработки разделился на два разных направления. Например, когда вы выпускаете версию 5.0, вы можете захотеть создать ветвь, чтобы можно было отделить разработку функций 6.0 от исправлений ошибок 5.0.

  • Working copy:Рабочая копия - это снимок репозитория. Репозиторий используется всеми командами, но люди не изменяют его напрямую. Вместо этого каждый разработчик проверяет рабочую копию. Рабочая копия - это личное рабочее место, где разработчики могут выполнять свою работу, оставаясь изолированными от остальной команды.

  • Commit changes:Фиксация - это процесс сохранения изменений с личного рабочего места на центральный сервер. После фиксации изменения становятся доступными для всей команды. Другие разработчики могут получить эти изменения, обновив свою рабочую копию. Фиксация - это атомарная операция. Либо вся фиксация выполняется успешно, либо выполняется откат. Пользователи никогда не видят наполовину завершенную фиксацию.

Установка SVN

Subversion - популярный инструмент контроля версий с открытым исходным кодом. Он имеет открытый исходный код и доступен бесплатно через Интернет. По умолчанию он входит в состав большинства дистрибутивов GNU / Linux, поэтому может быть уже установлен в вашей системе. Чтобы проверить, установлен ли он, используйте следующую команду.

[jerry@CentOS ~]$ svn --version

Если клиент Subversion не установлен, команда сообщит об ошибке, в противном случае будет отображена версия установленного программного обеспечения.

[jerry@CentOS ~]$ svn --version
-bash: svn: command not found

Если вы используете GNU / Linux на основе RPM, используйте 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

И если вы используете GNU / Linux на основе Debian, используйте 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

Мы видели, как установить клиент Subversion в GNU / Linux. Давайте посмотрим, как создать новый репозиторий и разрешить доступ пользователям.

На сервере мы должны установить 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. Параметры '-c' создают файл паролей , если файл паролей уже существует, он перезаписывается. Поэтому используйте опцию '-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 каталоги непосредственно в корневом каталоге проекта.

Ствол представляет собой каталог , в котором все основное развитие происходит , и, как правило , Выдан разработчиками для работы над проектом.

Теги каталог используются для хранения имени снимок проекта. При создании производственной версии команда помечает код, который входит в выпуск.

Ветви каталог используется , когда вы хотите проводить различные линии развития.

Давайте создадим структуру каталогов ствола, тегов и ветвей в репозитории проекта.

[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. Теперь они могут выполнять все поддерживаемые операции с репозиторием.

В этой главе обсуждается жизненный цикл системы контроля версий. В следующих главах мы увидим команду Subversion для каждой операции.

Создать репозиторий:

Репозиторий - это центральное место, где разработчики хранят всю свою работу. В репозитории хранятся не только файлы, но и история изменений. Это означает, что он поддерживает историю изменений, внесенных в файлы.

Операция «создать» используется для создания нового репозитория. В большинстве случаев эта операция выполняется только один раз. Когда вы создаете новый репозиторий, ваша VCS будет ожидать, что вы скажете что-то, чтобы идентифицировать его, например, где вы хотите его создать или какое имя следует дать репозиторию.

Проверять, выписываться

Операция «Оформить заказ» используется для создания рабочей копии из репозитория. Рабочая копия - это личное рабочее место, где разработчики вносят свои изменения, а затем отправляют эти изменения в репозиторий.

Обновить

Как следует из названия, операция «обновление» используется для обновления рабочей копии. Эта операция синхронизирует рабочую копию с репозиторием. Поскольку репозиторий используется всеми командами, другие разработчики могут фиксировать свои изменения, и ваша рабочая копия становится старше.

Предположим, что Том и Джерри - два разработчика, работающих над проектом. Оба извлекают последнюю версию из репозитория и начинают работать. На этом этапе их рабочие копии полностью синхронизированы с репозиторием. Джерри очень эффективно завершает свою работу и фиксирует свои изменения в репозитории.

Теперь рабочая копия Тома устарела. Операция обновления извлечет последние изменения Джерри из репозитория и обновит рабочую копию Тома .

Выполнить изменения

После оформления заказа можно выполнять различные операции для внесения изменений. Правка - самая распространенная операция. Можно отредактировать существующий файл, чтобы добавить / удалить содержимое из файла.

Можно добавлять файлы / каталоги. Но сразу эти файлы / каталоги не становятся частью репозитория, вместо этого они добавляются в список ожидающих изменений и становятся частью репозитория после операции фиксации.

Аналогичным образом можно удалять файлы / каталоги. Операция удаления немедленно удаляет файл из рабочей копии, но фактическое удаление файла добавляется в список ожидающих изменений, и изменения вносятся в репозиторий после операции фиксации.

Операция «Переименовать» изменяет имя файла / каталога. Операция «Перемещение» используется для перемещения файлов / каталогов из одного места в другое в дереве репозитория.

Просмотреть изменения

Когда вы извлекаете рабочую копию или обновляете рабочую копию, ваша рабочая копия полностью синхронизируется с репозиторием. Но по мере того, как вы вносите изменения в свою рабочую копию, она становится новее, чем репозиторий. И рекомендуется проверять свои изменения перед операцией «фиксации».

Операция «Статус» отображает изменения, внесенные в рабочую копию. Как мы упоминали ранее, всякий раз, когда вы вносите изменения в рабочую копию, все эти изменения становятся частью ожидающего списка изменений. А операция «статус» используется для просмотра списка ожидающих изменений.

Операция «Статус» предоставляет только список изменений, но не подробную информацию о них. Можно использовать операцию diff для просмотра деталей изменений, внесенных в рабочую копию.

Исправить ошибки

Предположим, кто-то внес изменения в свою рабочую копию, но теперь он хочет выбросить эти изменения. В этой ситуации поможет операция «возврат».

Операция возврата отменяет изменения, внесенные в рабочую копию. Можно вернуть один или несколько файлов / каталогов. Также можно вернуть всю рабочую копию. В этом случае операция «возврат» уничтожит список ожидающих изменений и вернет рабочую копию в исходное состояние.

Разрешить конфликты:

Во время слияния могут возникнуть конфликты. Операция «Слияние» автоматически обрабатывает все, что можно сделать безопасно. Все остальное считается конфликтом. Например, файл hello.c был изменен в ветке и удален в другой ветке. Такая ситуация требует от человека принятия решения. Операция «разрешение» используется, чтобы помочь пользователю разобраться в проблемах и сообщить VCS о способах разрешения конфликтов.

Зафиксировать изменения

Операция «Зафиксировать» используется для применения изменений из рабочей копии в репозитории. Эта операция изменяет репозиторий, и другие разработчики могут видеть эти изменения, обновляя свою рабочую копию.

Перед фиксацией необходимо добавить файлы / каталоги в список ожидающих изменений. Это место, где изменения ждут своей фиксации. При фиксации мы обычно предоставляем сообщение журнала, чтобы объяснить, почему кто-то внес изменения. Это сообщение журнала становится частью истории репозитория. Фиксация - это атомарная операция, что означает либо успешное выполнение всей фиксации, либо откат. Пользователи никогда не видят незавершенную фиксацию.

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]$

Джерри проверяет последнюю версию репозитория и начинает работу над проектом. Он создает файл 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@CentOS trunk]$ svn add array.c 
A         array.c

Проверим это с помощью операции «статус». Subversion показываетAперед array.c , это означает, что файл успешно добавлен в список ожидающих изменений.

[jerry@CentOS trunk]$ svn status
?       array
A       array.c

Чтобы сохранить файл array.c в репозитории, используйте команду фиксации с параметром -m, за которым следует сообщение фиксации. Если вы опустите опцию -m, Subversion вызовет текстовый редактор, где вы можете ввести многострочное сообщение.

[jerry@CentOS trunk]$ svn commit -m "Initial commit"
Adding         trunk/array.c
Transmitting file data .
Committed revision 2.

Теперь файл array.c успешно добавлен в репозиторий, а номер ревизии увеличен на единицу.

Джерри уже добавил файл array.c в репозиторий. Том также проверяет последний код и начинает работать.

[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
------------------------------------------------------------------------

Когда Том наблюдает за кодом Джерри , он сразу же замечает в нем ошибку. Джерри не проверял переполнение массива, что могло вызвать серьезные проблемы. Итак, Том решает исправить эту проблему. После модификации 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;
}

Том хочет использовать операцию status, чтобы увидеть список ожидающих изменений.

[tom@CentOS trunk]$ svn status
M       array.c

файл array.c изменен, поэтому Subversion показываетMбуква перед именем файла. Затем Том компилирует и тестирует свой код, и он работает нормально. Перед фиксацией изменений он хочет перепроверить, просмотрев внесенные им изменения.

[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)

Том добавил несколько строк в файл array.c , поэтому Subversion показывает + знак перед новыми строками. Теперь он готов зафиксировать свои изменения.

[tom@CentOS trunk]$ svn commit -m "Fix array overflow problem"

Приведенная выше команда даст следующий результат.

Sending        trunk/array.c
Transmitting file data .
Committed revision 3.

Изменения Тома успешно зафиксированы в репозитории.

Джерри зафиксировал первую версию кода. Но он думает, что ему следует написать две функции для приема ввода и отображения содержимого массива. После модификации 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@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

Subversion не позволяет фиксировать изменения Джерри , потому что Том уже изменил репозиторий, а рабочая копия Джерри устарела. Чтобы избежать перезаписи изменений друг друга, Subversion не выполняет эту операцию. Джерри должен обновить рабочую копию перед фиксацией своих изменений. Поэтому он использует команду обновления, как показано ниже.

[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 показывает только изменения Джерри , но файл 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@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.

Предположим, Джерри случайно изменяет файл 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

Джерри выполняет операцию возврата к файлу 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

После операции возврата его рабочая копия возвращается в исходное состояние. Операция возврата может вернуть как отдельный файл, так и весь каталог. Чтобы вернуть каталог, используйте параметр -R, как показано ниже.

[jerry@CentOS project_repo]$ pwd
/home/jerry/project_repo

[jerry@CentOS project_repo]$ svn revert -R trunk

До сих пор мы видели, как отменить изменения, внесенные в рабочую копию. Но что, если вы хотите отменить зафиксированную ревизию! Инструмент Система контроля версий не позволяет удалять историю из репозитория. Мы можем только добавить историю. Это произойдет, даже если вы удалите файлы из репозитория. Чтобы отменить старую ревизию, мы должны отменить все изменения, внесенные в старую ревизию, а затем зафиксировать новую ревизию. Это называется обратным слиянием.

Предположим, Джерри добавляет код для операции линейного поиска. После проверки он фиксирует свои изменения.

[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.

Том решает добавить файл 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.

Джерри проверяет последний код версии 6. И сразу же начинает работать. Через несколько часов Том обновляет файл 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, а рабочая копия Джерри устарела. Джерри также обновляет файл README и пытается зафиксировать свои изменения.

Файл 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@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 не знает, как его решить. Поэтому Джерри выбирает опцию 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. Отложите конфликты

Затем Джерри выбирает вариант отложить (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 включила и код Тома, и его код с маркерами конфликтов.

[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

Джерри хочет, чтобы Том и его изменения были изменены, поэтому он просто удаляет строки, содержащие маркеры конфликта.

Итак, модифицированный 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@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. Джерри разрешил конфликт, но не сказал Subversion, что он разрешил конфликт. Он использует команду разрешения, чтобы сообщить 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.

Система управления версиями поддерживает операции с тегами , используя концепцию, позволяющую дать осмысленное имя конкретной версии кода. Тег позволяет давать описательные и запоминающиеся имена конкретной версии кода. НапримерBASIC_ARRAY_OPERATIONS более запоминающийся, чем revision 4.

Рассмотрим работу тега на примере. Том решает создать тег, чтобы упростить доступ к коду.

[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

После успешного завершения внутри каталога тегов будет создан новый каталог.

[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.

Работа филиала создает еще одно направление развития. Это полезно, когда кто-то хочет, чтобы процесс разработки разделился на два разных направления. Предположим, вы выпустили продукт версии 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@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@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, Том обнаружил, что Джерри реализовал операцию «сортировки». Том реализовал операцию поиска, используя алгоритм двоичного поиска, он всегда ожидает данные в отсортированном порядке. Но что, если пользователь предоставляет данные в несортированном порядке? В этой ситуации операция двоичного поиска завершится ошибкой. Поэтому он решает использовать код Джерри для сортировки данных перед операцией поиска. Поэтому он просит Subversion объединить код из ветки Джерри в ствол.

[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]$