Простейший рабочий цикл

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

Типичный рабочий цикл выглядит примерно так:

Обновление рабочей копии

При командной работе над проектом обновление рабочей копии необходимо для получения любых изменений, внесенных другими разработчиками проекта с момента вашего последнего обновления. Используйте svn update для синхронизации вашей рабочей копии с последней правкой в хранилище.

$ svn update
U  foo.c
U  bar.c
Updated to revision 2.

В данном случае, кто-то другой зафиксировал изменения в файлах foo.c и bar.c после вашего последнего обновления, и Subversion обновила вашу рабочую копию, включив эти изменения.

Рассмотрим поподробнее информацию, выводимую командой svn update. Когда сервер отправляет изменения в вашу рабочую копию, для каждого элемента выводится латинская буква — код, определяющий действие, выполненное Subversion для приведения вашей рабочей копии в актуальное состояние:

U foo

Файл foo был Updated — обновлен (получил изменения с сервера).

A foo

Файл или каталог foo был Added — добавлен в рабочую копию.

D foo

Файл или каталог foo был Deleted — удален из рабочей копии.

R foo

Файл или каталог foo был Replaced — заменен в рабочей копии; это значит, что foo был удален, а новый элемент с таким же именем был добавлен. Несмотря на то, что они могут иметь одинаковое имя, хранилище рассматривает их как разные объекты с отдельной историей.

G foo

Файл foo получил новые изменения из хранилища, однако ваша локальная копия в то же время содержит ваши собственные изменения. Изменения, полученные из хранилища, либо не пересекаются, либо они точно такие же как ваши локальные изменения, поэтому Subversion успешно выполнила merGed — слияние изменений хранилища с файлом.

C foo

Файл foo получил от сервера Conflicting — конфликтующие изменения. Изменения с сервера пересекаются с вашими изменениями файла. Однако это не повод для паники. Такое перекрытие просто нуждается в разрешении человеком (вами); мы обсудим эту ситуацию позднее в этой главе.

Внесение изменений в рабочую копию

Теперь вы можете приступать к делу и вносить изменения в рабочую копию. Как правило, целесообразнее всего работать отдельно по каждому частному изменению (или набору изменений), такому как реализация новой функциональной возможности, исправление ошибки и т. п. Здесь вы будете пользоваться такими командами Subversion как svn add, svn delete, svn copy и svn move. Однако, если вы просто редактируете файлы, которые уже находятся под контролем Subversion, ни одна из этих команд вам не нужна. В своей рабочей копии вы можете делать следующие изменения:

Изменения файлов

Это самый простой вид изменений. Вам не нужно сообщать Subversion о своем намерении изменить файл; просто берите и вносите изменения. Subversion сможет автоматически определить измененные файлы.

Изменения в структуре

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

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

Рассмотрим четыре подкоманды Subversion, которые вы чаще всего будете использовать при внесении изменений в структуру (команды svn import и svn mkdir мы рассмотрим позже).

[Внимание] Внимание

Хотя вы можете редактировать файлы любыми программными средствами, не следует менять структуру рабочей копии, не проинформировав о своих действиях Subversion. Для изменения структуры рабочей копии используйте команды svn copy, svn delete и svn move, а для добавления новых файлов и каталогов под контроль версий используйте svn add.

svn add foo

Запланировать файл, каталог или символьную ссылку foo для добавления в хранилище. При следующей фиксации foo станет компонентом своего родительского каталога. Обратите внимание на то, что если foo является каталогом, то все содержащееся в foo будет запланировано для добавления. Чтобы добавить отдельно только сам каталог foo, воспользуйтесь параметром --non-recursive (-N).

svn delete foo

Запланировать удаление из хранилища файла, каталога или символьной ссылки foo. Если foo является файлом или ссылкой, он сразу же удаляется из вашей рабочей копии. Если foo является каталогом, он не удаляется, но Subversion запланирует его удаление. foo будет удален из рабочей копии и хранилища при фиксации изменений.[8]

svn copy foo bar

Создать новый элемент bar как копию foo. bar будет автоматически запланирован для добавления. Когда при следующей фиксации bar будет добавлен в хранилище, в его истории будет отмечено копирование (то, что первоисточником является foo). svn copy не создает промежуточных каталогов.

svn move foo bar

Эта команда полностью аналогична выполнению svn copy foo bar; svn delete foo. Поэтому, bar будет запланирован для добавления как копия foo, а foo будет запланирован для удаления. svn move не создает промежуточных каталогов.

Анализ изменений

После внесения изменений вы должны зафиксировать их в хранилище, но перед этим было бы неплохо посмотреть, что же, собственно, вы изменили. Проанализировав перед фиксацией свои изменения, вы сможете составить более аккуратное лог-сообщение. Кроме того, вы можете обнаружить, что изменили файл непреднамеренно, что позволит еще до фиксации вернуть файл к предыдущему состоянию. К тому же, это хорошая возможность пересмотреть и проверить изменения перед их публикацией. Чтобы увидеть все сделанные изменения, вы можете воспользоваться svn status, svn diff и svn revert. Первые две команды вы можете использовать для того, чтобы найти измененные файлы рабочей копии, а затем, при помощи третьей, отменить некоторые (или все) изменения.

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

svn status

Наверное, команду svn status вы будете использовать чаще, чем любую другую команду Subversion.

При запуске svn status без параметров из корневого каталога рабочей копии будут найдены все сделанные вами изменения файлов и структуры. Ниже приведены примеры различных буквенных кодов, возвращаемых svn status. (Обратите внимание, что текст, следующий за #, на самом деле svn status не печатает.)

  L     some_dir            # svn оставила блокировку в .svn-области для some_dir
M       bar.c               # содержимое bar.c имеет локальные изменения
 M      baz.c               # в baz.c есть изменения в свойствах, а в содержимом нет
X       3rd_party           # каталог является частью внешней зависимости
?       foo.o               # svn не управляет foo.o
!       some_dir            # svn управляет этим элементом, но он отсутствует или поврежден
~       qux                 # элемент версионировался как файл/каталог/ссылка, но тип был изменен
I       .screenrc           # svn не управляет этим элементом и настроена на его игнорирование
A  +    moved_dir           # добавлен с историей своего происхождения
M  +    moved_dir/README    # добавлен с историей и имеет локальные изменения
D       stuff/fish.c        # файл запланирован для удаления
A       stuff/loot/bloo.h   # файл запланирован для добавления
C       stuff/loot/lump.c   # файл имеет текстовый конфликт с момента обновления
 C      stuff/loot/glub.c   # файл имеет конфликт в свойствах с момента обновления
R       xyz.c               # файл запланирован для замены
    S   stuff/squawk        # файл или каталог были переключены на ветку
     K  dog.jpg             # файл заблокирован локально; присутствует маркер блокирования
     O  cat.jpg             # файл заблокирован в хранилище другим пользователем
     B  bird.jpg            # файл заблокирован локально, но блокировка была нарушена
     T  fish.jpg            # файл заблокирован локально, но блокировка была снята

svn status печатает пять колонок букв, затем несколько пробелов, затем имя файла или каталога. Первая колонка показывает статус файла или каталога и/или ее содержимого. При этом используются следующие коды:

A item

Файл, каталог или символьная ссылка item был запланирован для добавления в хранилище.

C item

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

D item

Файл, каталог или символьная ссылка item запланирован для удаления из хранилища.

M item

Содержимое файла item было изменено.

R item

Файл, каталог или символьная ссылка запланирован для замены item в хранилище. Это значит, что сначала объект был удален, а затем другой объект с таким же именем был добавлен, все в одной правке.

X item

Каталог item не версионирован, но относится к внешним зависимостям Subversion. Более подробно о внешних зависимостях см. в «Внешние зависимости».

? item

Файл, каталог или символьная ссылка не находится под контролем версий. Вы можете убрать знаки вопроса либо воспользовавшись параметром --quiet (-q) команды svn status, либо установив свойство svn:ignore родительского каталога. Дополнительную информацию об игнорировании файлов см. в «Пропуск неверсионированных элементов».

! item

Файл, каталог или символьная ссылка item находится под контролем версий, но отсутствует в рабочей копии или поврежден. Элемент может отсутствовать, если он был удален без использования команд Subversion. В частном случае, каталог может оказаться поврежденным, если вы прервали создание рабочей копии или обновление. Быстрый запуск svn update заново вытащит файл или каталог из хранилища, либо svn revert file восстановит отсутствующий файл.

~ item

Файл, каталог или символьная ссылка item в хранилище является объектом одного типа, а то, что на самом деле находится в рабочей копии, является чем-то другим. Например, в хранилище Subversion может иметь файл, а вы удалили файл и создали на его месте каталог, не используя для этого команды svn delete или svn add.

I item

Файл, каталог или символьная ссылка item находится под контролем версий, и Subversion настроена на его игнорирование при операциях svn add, svn import и svn status. Дополнительную информацию об игнорированных файлах см. в «Пропуск неверсионированных элементов». Обратите внимание на то, что этот символ появляется при использовании опции --no-ignore для svn status — иначе файл игнорируется и не показывается вообще!

Вторая колонка показывает статус свойств файлов и каталогов (подробнее о свойствах см. в «Свойства»). Если во второй колонке показывается M, свойства были изменены. Если в этой колонке показывается C, то это означает, что свойства файла находятся в состоянии конфликта, который должен быть разрешен до фиксации изменений в хранилище. Во всех других случаях будет выведен пробел.

Третья колонка может содержать только пробел или L, это значит, что у каталога заблокирована рабочая область .svn. Вы увидите L, если запустите svn status в каталоге, в котором выполняется svn commit — например, когда вы редактируете лог-сообщение.

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

Пятая колонка может содержать только пробел или S. Это означает, что файл или каталог был переключен с пути остальной рабочей копии на ветку (используя svn switch).

Шестая колонка показывает информацию о блокировках, которые подробно рассмотрены в «Locking». (Это не те блокировки, которые отмечаются L в третьей колонке; см. Three meanings of «lock»)

Если вы укажете конкретный путь для svn status, то получите информацию только об этом элементе:

$ svn status stuff/fish.c
D      stuff/fish.c

Кроме того, svn status имеет параметр --verbose (-v), который покажет вам статус каждого элемента в рабочей копии, даже если он не менялся:

$ svn status --verbose
M               44        23    sally     README
                44        30    sally     INSTALL
M               44        20    harry     bar.c
                44        18    ira       stuff
                44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
                44        21    sally     stuff/things
A                0         ?     ?        stuff/things/bloo.h
                44        36    harry     stuff/things/gloo.c

Это «длинная форма» представления вывода svn status. Первая колонка осталась та же самая, а вот вторая колонка показывает рабочую правку элемента. Третья и четвертая колонки показывают правку, в которой элемент последний раз изменялся и автора этих изменений.

Ни один из указанных выше вызовов svn status не обращается к хранилищу, они работают только локально, сравнивая метаданные каталога .svn с рабочей копией. Отметим, что есть параметр --show-updates (-u), указывающий на соединение с хранилищем и добавляющий информацию об устаревании элементов:

$ svn status --show-updates --verbose
M      *        44        23    sally     README
M               44        20    harry     bar.c
       *        44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
A                0         ?     ?        stuff/things/bloo.h
Status against revision:   46

Обратите внимание на две звездочки: если сейчас вы запустите svn update вы получите изменения для README и trout.c. Это очень полезная информация — перед фиксацией вам необходимо обновить и получить изменения с сервера для README, или же хранилище отклонит вашу фиксацию как не соответствующую актуальному состоянию. (Подробнее об этом чуть позже.)

svn diff

Еще один механизм для анализа изменений — это команда svn diff. Запустив svn diff без аргументов, можно увидеть, какие именно изменения вы внесли, в результате будут выведены изменения файлов в едином формате представления различий:[9]

$ svn diff
Index: bar.c
===================================================================
--- bar.c (revision 3)
+++ bar.c (working copy)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>

 int main(void) {
-  printf("Sixty-four slices of American Cheese...\n");
+  printf("Sixty-five slices of American Cheese...\n");
 return 0;
 }

Index: README
===================================================================
--- README  (revision 3)
+++ README  (working copy)
@@ -193,3 +193,4 @@
+Note to self:  pick up laundry.

Index: stuff/fish.c
===================================================================
--- stuff/fish.c  (revision 1)
+++ stuff/fish.c  (working copy)
-Welcome to the file known as 'fish'.
-Information on fish will be here soon.

Index: stuff/things/bloo.h
===================================================================
--- stuff/things/bloo.h (revision 8)
+++ stuff/things/bloo.h (working copy)
+Here is a new file to describe
+things about bloo.

Команда svn diff формирует свой вывод, сравнивая ваши рабочие файлы с кэшированными «нетронутыми» копиями из .svn. Весь текст запланированных для добавления файлов показывается как добавленный, а весь текст запланированных для удаления файлов показывается как удаленный.

Вывод происходит в едином формате представления различий. При этом удаленные строки предваряются знаком -, а добавленные — знаком +. Кроме этого svn diff печатает имена файлов и информацию о сдвиге информации, которая необходима программе patch, и, следовательно, вы можете получать «патчи», перенаправив вывод различий в файл:

$ svn diff > patchfile

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

svn revert

Теперь предположим, что, просмотрев вывод команды diff, вы обнаружили, что изменения в README ошибочны — к примеру, потому, что в своем редакторе вы случайно набрали текст, предназначавшийся для другого файла.

В такой ситуации как нельзя кстати окажется команда svn revert.

$ svn revert README
Reverted 'README'

Subversion возвращает файл в состояние, предшествующее модификации, путем замены файла его кэшированной «первоначальной» копией из .svn-области. Кроме того, обратите внимание, что svn revert может отменить любые запланированные операции — например, вы можете прийти к решению всё-таки не добавлять новый файл:

$ svn status foo
?      foo

$ svn add foo
A         foo

$ svn revert foo
Reverted 'foo'

$ svn status foo
?      foo
[Замечание] Замечание

svn revert ITEM будет иметь точно такой же эффект, как и удаление ITEM из вашей рабочей копии, а затем выполнение svn update -r BASE ITEM. Однако, если вы отменяете изменения для файла, svn revert будет иметь одно значительное отличие — для восстановления файла не происходит соединения с хранилищем.

Или, допустим, вы ошибочно удалили файл из-под контроля версий:

$ svn status README
       README

$ svn delete README
D         README

$ svn revert README
Reverted 'README'

$ svn status README
       README

Разрешение конфликтов (при слиянии с чужими изменениями)

Мы уже видели, как svn status -u может предупредить о конфликтах. Предположим, вы запустили svn update и увидели кое-что интересное:

$ svn update
U  INSTALL
G  README
C  bar.c
Updated to revision 46.

Коды U и G интереса не представляют; эти файлы без проблем поглотили изменения из хранилища. Файлы, отмеченные U, локальных изменений не содержат и были Updated — обновлены изменениями из хранилища. Отмеченные G были merGed — слиты, это значит, что файл имел локальные изменения, но изменения, пришедшие из хранилища, не перекрываются с локальными изменениями.

А вот файлы, отмеченные C, имеют конфликт. Это значит, что изменения с сервера пересеклись с вашими личными, и теперь вам нужно вручную сделать между ними выбор.

Всякий раз, когда возникает конфликт, в его обнаружении и разрешении вам, как правило, помогают три вещи:

  • Subversion печатает C во время обновления и запоминает, что файл в состоянии конфликта.

  • Если Subversion считает, что тип файла допускает слияние изменений, она включает в него маркеры конфликта — специальные текстовые строки, отделяющие «стороны» конфликта — чтобы визуально показать пересекающиеся области. (Subversion использует свойство svn:mime-type для определения возможности контекстного, построчного слияния. См. «Тип содержимого файла» для более подробной информации.)

  • Для каждого конфликтного файла Subversion добавляет в рабочую копию до трех не версионированных дополнительных файлов:

    filename.mine

    Это ваш файл в том виде, в каком он присутствовал в рабочей копии до обновления — без маркеров конфликта. Этот файл содержит в себе только ваши изменения и ничего больше. (Если Subversion решает, что файл не пригоден для слияния изменений, то файл .mine не создается, так как он будет идентичным рабочему файлу.)

    filename.rOLDREV

    Это файл правки BASE, где BASE — правка, которая была до обновления рабочей копии. Иными словами, это файл, который был у вас до внесения изменений.

    filename.rNEWREV

    Это файл, который ваш Subversion-клиент получил с сервера при обновлении рабочей копии. Этот файл соответствует правке HEAD хранилища.

    Здесь OLDREV — это номер правки файла в каталоге .svn, а NEWREV — номер правки HEAD хранилища.

Например, Салли внесла изменения в файл sandwich.txt из хранилища. Одновременно Гарри изменил файл в своей рабочей копии и зафиксировал его. Салли обновляет свою рабочую копию перед фиксацией и получает конфликт:

$ svn update
C  sandwich.txt
Updated to revision 2.
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2

Теперь Subversion не позволит зафиксировать файл sandwich.txt, пока не будут удалены три временных файла.

$ svn commit --message "Add a few more things"
svn: Commit failed (details follow):
svn: Aborting commit: '/home/sally/svn-work/sandwich.txt' remains in conflict

Для разрешения конфликта у вас есть три варианта:

  • Объединить конфликтующий текст «вручную» (путем анализа и редактирования маркеров конфликта в файле).

  • Скопировать один из временных файлов поверх своего рабочего файла.

  • Выполнить svn revert <filename> для отказа от всех ваших локальных изменений.

После разрешения конфликта вам нужно известить об этом Subversion, выполнив svn resolved. Эта команда удалит три временных файла, и Subversion больше не будет считать, что файл находится в состоянии конфликта. [10]

$ svn resolved sandwich.txt
Resolved conflicted state of 'sandwich.txt'

Слияние конфликтов вручную

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

Возьмем пример. По недоразумению вы и ваш соразработчик Салли одновременно редактируете файл sandwich.txt. Салли зафиксировала свои изменения, и поэтому при обновлении своей рабочей копии вы получите конфликт, для разрешения которого вам необходимо отредактировать sandwich.txt. Для начала посмотрим на файл:

$ cat sandwich.txt
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2
Creole Mustard
Bottom piece of bread

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

<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======

Текст между вторым и третьим маркером конфликта — это текст из фиксации Салли:

=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2

Скорее всего вы не захотите просто удалить маркеры конфликта и изменения, сделанные Салли, — она ужасно удивится, когда дойдет до сандвича и не увидит того, что ожидала. Это как раз тот случай, когда вы снимаете трубку или пересекаете офис и объясняете Салли, что не можете получить из итальянского гастронома квашеную капусту. [11] После того, как вы согласуете изменения, нужно будет выполнить фиксацию. Для этого отредактируйте ваш файл и удалите маркеры конфликта.

Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
Salami
Mortadella
Prosciutto
Creole Mustard
Bottom piece of bread

Теперь выполните svn resolved, и вы готовы к фиксации изменений:

$ svn resolved sandwich.txt
$ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."

Обратите внимание на то, что svn resolved, в отличие от большинства команд, с которыми мы имели дело в этой главе, требует аргумент. В любом случае будьте осторожны и выполняйте svn resolved тогда, когда вы убеждены, что исправили конфликт в файле. После того как временные файлы будут удалены, Subversion позволит вам зафиксировать файл, даже если он все еще содержит маркеры конфликта.

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

Копирование файла поверх вашего рабочего файла

Если вы получили конфликт и решили отказаться от своих изменений, вы можете просто скопировать один из временных файлов, созданных Subversion, поверх файла в рабочей копии:

$ svn update
C  sandwich.txt
Updated to revision 2.
$ ls sandwich.*
sandwich.txt  sandwich.txt.mine  sandwich.txt.r2  sandwich.txt.r1
$ cp sandwich.txt.r2 sandwich.txt
$ svn resolved sandwich.txt

Использование svn revert

Если вы получили конфликт и, проанализировав, решили отбросить изменения и начать сначала, просто отмените ваши изменения:

$ svn revert sandwich.txt
Reverted 'sandwich.txt'
$ ls sandwich.*
sandwich.txt

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

Фиксация изменений

Наконец-то! Вы закончили с редактированием, слили все изменения с сервера и готовы к тому, чтобы зафиксировать их в хранилище.

Команда svn commit отправляет все ваши изменения в хранилище. При фиксации изменений необходимо описать ваши изменения в тексте лог-сообщения. Лог-сообщение будет присоединено к созданной правке. Если ваше лог-сообщение короткое, вы можете указать его в командной строке, используя опцию --message (или -m):

$ svn commit --message "Corrected number of cheese slices."
Sending        sandwich.txt
Transmitting file data .
Committed revision 3.

Однако, если вы заранее составляли лог-сообщение в процессе работы, можно попросить Subversion взять его из файла, передав имя этого файла в параметре --file:

$ svn commit --file logmsg
Sending        sandwich.txt
Transmitting file data .
Committed revision 4.

Если вы не укажете ни опции --message, ни опции --file, для составления лог сообщения Subversion автоматически запустит ваш любимый редактор (см. editor-cmd в разделе «Config»).

[Подсказка] Подсказка

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

$ svn commit
Waiting for Emacs...Done

Log message unchanged or not specified
a)bort, c)ontinue, e)dit
a
$

Хранилище, в общем-то, не знает ничего о смысле ваших изменений; оно только контролирует, чтобы никто не изменил те же файлы, что и вы. Если это все-таки случилось, вся фиксация будет отклонена, и вы получите сообщение о том, что один или несколько файлов устарели:

$ svn commit --message "Add another rule"
Sending        rules.txt
svn: Commit failed (details follow):
svn: Out of date: 'rules.txt' in transaction 'g'

В таком случае вам нужно выполнить svn update, разобраться со всеми слияниями и конфликтами и попытаться выполнить фиксацию снова.

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



[8] Конечно, ничего полностью из хранилища не удаляется — удаление касается только HEAD правки хранилища. Вы можете восстановить все, что вы удалили, создав рабочую копию (или обновив существующую) на основе более ранней правки, чем та, в которой вы удалили элемент.

[9] Subversion использует свой внутренний механизм обнаружения различий, который по умолчанию использует для вывода единый формат представления различий. Если вы хотите получить различия в другом формате, укажите внешнюю программу поиска различий, используя --diff-cmd и передав любые аргументы, которые вы хотите использовать, в параметре --extensions. Например, для того чтобы увидеть контекстные локальные изменения в файле foo.c, игнорируя изменения в числе пробелов, запустите svn diff --diff-cmd /usr/bin/diff --extensions '-bc' foo.c.

[10] Вы можете удалить временные файлы самостоятельно — но стоит ли это делать, если можно переложить эту работу на Subversion? Нам так не кажется.

[11] А если вы их об этом попросите, они лишь посмеются над вами.