Продолжение. Начало в № 2 2010
Основы систем управления версиями файлов
на примере Subversion (SVN)
Денис ШЕхалев
в предыдущей части мы познакомились с основой основ SVN — репозиторием и научились с ним работать. Теперь рассмотрим операции с файлами проекта, с которыми разработчики сталкиваются чаще всего. Как мы помним, наши программисты вася и Петя создали локальный репозиторий, импортировали туда проект и создали рабочую копию проекта demo_project1. Оба наших программиста работают в своих собственных рабочих копиях.
Работа с рабочей копией
Добавление файлов в рабочую копию
Вася создает программу приветствия hello.py и работает над ней. Для этого с помощью любимого редактора он создает файл и добавляет в него рабочий код. Для того чтобы поместить этот файл под контроль SVN, Вася использует команду Add (рис. 20).
Перед выполнением команды SVN предоставит возможность проверить список добавляемых файлов (рис. 21). В том случае если файл добавляется ошибочно, его добавление
можно исключить. В результате выполнения команды файл помечается как кандидат на добавление к проекту и сопровождается соответствующей иконкой (рис. 22).
Для фиксации изменений Васе необходимо выполнить команду Commit (рис. 23). Как правильный программист, Вася не забывает оставлять комментарий (рис. 24). После выполнения фиксации иконка на файле показывает, что файл находится под контролем SVN и в него не было внесено изменений (рис. 25). Точно так же, только с файлом bye.py, поступает и Петя. Теперь текущее состояние репозитория таково (рис. 26).
Подсказка. Для добавления директории с файлами команда Add сначала используется для директории. При добавлении TortoiseSVN предложит автоматически добавить файлы, которые находятся в директории, в список на добавление.
Рис. 24. Диалоговое окно для задания комментария при фиксации изменений в рабочей копии
Рис. 22. Состояние рабочей копии перед фиксацией добавления файла в репозиторий SVN
Рис. 25. Состояние рабочей копии
после фиксации добавления файла в репозиторий
Рис. 21. Диалоговое окно проверки списка папок и файлов, добавляемых под контроль SVN
Рис. 23. Фиксация изменений,
сделанных в рабочей копии, в репозитории SVN
Рис. 26. Состояние репозитория
после добавления файлов из рабочих копий в проект
Синхронизация рабочей копии с репозиторием
Вася и Петя независимо друг от друга добавили свои файлы в проект и зафиксировали добавление в репозитории. Для того чтобы воспользоваться результатами работы друг друга, они должны синхронизировать свои рабочие копии. В SVN это делается через репозиторий с помощью команды Update (рис. 27). Вася в своей рабочей копии выполняет команду Update (рис. 28). В результате у него в рабочей копии появляется файл Пети bye.py, который находится под контролем SVN (рис. 29).
Рис. 27. Синхронизация рабочей копии с репозиторием SVN
Рис. 28. Окно протокола синхронизации рабочей копии с репозиторием SVN
нит, что именно и где он менял. Для того чтобы вспомнить, он выполняет команду Diff над нужным файлом (рис. 31).
Программа сравнения файлов ТоНокеМе^е показывает строки файла, которые были изменены (рис. 32). Петя удаляет часть своих изменений, но тут понимает, что все внесенные им изменения были ошибочны, и хочет
восстановить начальное состояние файла hello.py. Он делает Update, но состояние файла не изменяется (рис. 33).
Это связано с тем, что изменения файла в рабочей копии имеют приоритет перед файлом в репозитории. Для того чтобы восстановить начальное состояние файла (сделать откат), нужно воспользоваться командой Revert (рис. 34). В результате файл вернется в то состояние (рис. 35), в котором он был при создании рабочей копии или последней синхронизации рабочей копии с репозиторием. При этом информация о состоянии файла для команд Diff/Revert берется не с репозитория SVN, а из служебных папок .svn, то есть наличие постоянно подключенного сервера не обязательно.
Рис. 29. Состояние рабочей копии Васи после синхронизации с репозиторием SVN
Важное замечание. При работе над проектами, особенно если это делает команда разработчиков, регулярно выполняйте синхронизацию рабочей копии с репозиторием.
Изменение и откат файлов
После синхронизации своей рабочей копии Петя решил, что функциональность модуля hello.py, который сделал Вася, его не устраивает, и внес в нее изменения. TortoiseSVN отслеживает внесение изменений в файл и информирует об этом в виде иконки (рис. 30). Поработав, Петя понял, что не все его изменения были правильные, и хочет убрать неправильные изменения из файла. Но он не пом-
Рис. 31. Сравнение версии файла Ью^^у в рабочей копии с версией в репозитории SVN
Рис. 34. Откат версии файла Ь^Ь^у до состояния версии в репозитории SVN
Рис. 33. Окно протокола синхронизации рабочей копии с репозиторием SVN
Примечание. Альтернативный, но неправильный вариант отката изменения — это удаление рабочей копии и новый Checkout.
Важное замечание. Будьте крайне внимательны при откатах изменений, после отката восстановить сделанные модификации рабочей копии невозможно.
Переименование файлов
В процессе работы над проектом Вася и Петя поняли, что имя файла документации readme.txt не отражает его содержание. И приняли решение о том, что файл нужно переименовать в documentation.txt. Вася выполняет команду Rename (рис. 36) и задает новое имя файла (рис. 37).
В результате выполнения команды файл помечается иконкой добавления (рис. 38). Тут возникает вопрос: почему при переименовании добавляется файл с новым именем? Дело в том, что в SVN команда Rename реализована с помощью механизма Copy-Delete. Это позволяет сохранять историю изменений файла при переименованиях.
Переименование изменяет файл в рабочей копии. Для того чтобы зафиксировать это изменение в репозитории, нужно выполнить Commit (рис. 39). Чтобы отменить переименование, нужно выполнить команду Revert. Петя, для того чтобы файл был переименован и в его рабочей копии, должен выполнить команду Update для синхронизации своей рабочей копии с репозиторием.
Рис. 36. Переименование файла readme.txt в рабочей копии
Рис. 39. Диалоговое окно для задания комментария при фиксации переименования файла readme.txt в репозитории SVN
Перемещение файлов
Петя с Васей решили выделить файлы документации в отдельную папку. Для этого Петя создает в своей рабочей копии папку doc (рис. 40). Добавляет ее под контроль SVN (рис. 41). Затем, используя технологию Drag-and-Drop и правую кнопку мыши, Петя выполняет перенос файла documentation.txt в папку doc (рис. 42). В результате папка doc выглядит следующим образом (рис. 43). Как видите, механизм переноса реализован через уже знакомый нам механизм Copy-Delete. После фиксации изменений проект в репозитории выглядит следующим образом (рис. 44).
Важное замечание. Переименовывать, перемещать и удалять файлы, находящиеся под контролем SVN, с помощью средств операционной системы нельзя. Данную операцию нужно делать только средствами SVN. Только в этом случае файл будет переименован, перемещен в репозитории или удален из него с сохранением его истории.
Важное замечание. Любые операции с файлами ведут к изменению рабочей копии, поэтому обязательно нужно фиксировать изменения в репозитории, если хотите сохранить эти изменения.
Разрешение конфликтов
В заключение работы Вася и Петя решили внестивфайлдокументации documentation.txt информацию о себе. Вася зафиксировал изменения на долю секунды раньше, чем Петя. Петя хочет зафиксировать свои изменения (рис. 45). Но ему не удается это сделать (рис. 46). Возникает конфликт версий файла, то есть файл, который находится в данный момент в репозитории, отличается от файла, который был в репозитории при создании рабочей копии Пети.
TortoiseSVN предлагает Пете синхронизировать его рабочую копию с репозиторием командой Update (рис. 47). Петя получает
Рис. 41. Установка метки папки для ее помещения под контроль SVN
Рис. 42. Перенос файла documentation.txt, находящегося под контролем SVN, в папку doc, которая тоже находится под контролем SVN
Рис. 43. Состояние папки doc в рабочей копии после переноса файла documentation.txt
конфликт файлов в своей рабочей копии. Для каждого конфликтного файла это выглядит следующим образом (рис. 48).
Рис. 45. Диалоговое окно для задания комментария при фиксации изменений в файле documentation.txt
Рис. 49. Просмотр конфликта версий файла documentation.txt
Сам файл помечен иконкой конфликтного файла. У Пети есть два варианта, как поступить:
1. Неправильный вариант — откатить файл до исходного состояния, синхронизировать его с репозиторием и заново внести в него все свои изменения.
2. Правильный вариант — разрешить конфликт средствами SVN. Дополнительные файлы, которые появились в директории, создаются как раз для помощи в этом.
Для разрешения конфликта Петя с помощью команды Edit Conflicts (рис. 49) и программы TortoiseMerge, идущей в составе клиента TortoiseSVN, смотрит, где именно возник конфликт (рис. 50). В TortoiseMerge видно 3 окна:
1. Mine («мой») — в окне представлен файл Пети, который находится в рабочей копии.
2. Theirs («их») — в окне представлен файл Васи, который находится в репозитории. Этот файл не дает Пете зафиксировать изменения, так как файлы находятся в кон-
3. Merged («слитый») — в окне представлен итоговый файл, который останется после слияния файлов mine и theirs и будет зафиксирован в репозитории.
Красные строки в окнах — это и есть конфликтующие строки, видно, что в файлах Васи и Пети они разные. Оранжевые перечеркнутые строки — это строки, которые были в файле при создании рабочей копии или последней синхронизации ее с репозиторием, но были удалены из файла. Окна просмотра файлов синхронизированы между собой, что очень удобно для просмотра и разрешения конфликтов.
Для устранения конфликта Петя должен в окне Merged сформировать итоговый файл. Сделать это он может как с помощью контекстного меню окна, в котором находится (доступно по нажатию правой кнопки мыши), так и набирая в окне Merged текст в конфликтующих строках.
Конфликт также можно просмотреть и устранить напрямую в файле documentation.txt (рис. 51). В файле видно 3 метки:
1. <<<<<<<.mine — это изменения, сделанные Петей в рабочей копии.
2. >>>>>>>.r16 — это изменения, зафиксированные Васей.
3. ======= — строка-разделитель между
конфликтующими строками в файле.
Для разрешения конфликта вручную, без
применения средств автоматизации, нужно исправить текст в файле, убрав из него все
Рис. 51. Детали конфликта версий файла documentation.txt
фликте.
Рис. 48. Состояние рабочей копии в случае конфликта версий файла documentation.txt
В директории появились дополнительные
3 файла:
1. documentation.txt.mine — исходный файл Пети, изменения в котором он собирался зафиксировать в репозитории.
2. documentation.txt.r13 — начальное состояние файла в репозитории, который модифицировал Петя в своей рабочей копии. Цифры означают номер ревизии файла.
3. documentation.txt.r14 — текущее состояние файла в репозитории, которое содержит изменения, сделанные Васей (поэтому номер ревизии и отличается).
Рис. 50. Детали конфликта версий файла documentation.txt в программе TortoiseMerge
Рис. 52. Устранение конфликта строк в файле documentation.txt в программе TortoiseMerge в автоматическом режиме
Рис. 53. Устранение конфликта строк в файле documentation.txt в программе TortoiseMerge в ручном режиме
метки. Сделать это можно в любом текстовом редакторе. Но лучше для этого воспользоваться программой TortoiseMerge. Петя решает использовать команду Edit conflicts и программу TortoiseMerge для слияния файлов.
Контекстное меню окна Merged предлагает варианты использования строк из окон Theirs и Mine. Петя выбирает команду Use text block from ‘theirs’, чтобы вставить в итоговый файл строку из файла Васи (рис. 52), и вручную дописывает строку Васи в итоговом файле. Устранив все конфликты (рис. 53) (теперь в окне Merged больше нет строк красного цвета), Петя сохраняет итоговый файл и выходит из TortoiseMerge.
Чтобы конфликт окончательно считался разрешенным, нужно удалить все файлы, автоматически созданные для разрешения конфликта. Это можно сделать средствами операционной системы, но лучше всего это делать с помощью команды Resolved (рис. 54).
Всё, конфликт разрешен, Петя может фиксировать изменения в репозитории.
Важное замечание. Конфликт возникает только в том случае, если авторы изменяют строки с одинаковыми номерами. Что и продемонстрировано в данном примере. В случае если изменяются разные строки файла, конфликта не будет. Произойдет слияние двух файлов в один (то есть результирующий файл будет содержать строки из обоих файлов). Не спешите сразу фиксировать изменения: лишний раз сравнить, какие изменения вы фиксируете, не помешает. Также надо помнить, что если бинарный файл будет обрабатываться как текстовый (а SVN по умолчанию считает, что все файлы текстовые), то, естественно, в результате будет нерабочий бинарный файл. Разделение бинарных и текстовых файлов рассмотрено ниже.
Использование конкретного номера ревизии файлов и папок
Если в проекте потребуется временно откатить некоторые папки и файлы назад, то необязательно создавать новую рабочую копию со старым номером ревизии всех файлов. Достаточно откатить только те файлы, которые нужны, с помощью команды Update to revision (рис. 55). Для этого с помощью кнопки Show log можно посмотреть историю изменений файла (рис. 56) и выбрать нужную ревизию файлов или папок для работы (рис. 57).
Рис. 55. Откат файла до нужной ревизии в репозитории SVN
Рис. 54. Разрешение конфликта версий файлов, возникшее при синхронизации рабочей копии с репозиторием
Рис. 56. Диалоговое окно выбора параметров отката файла до нужной ревизии
Рис. 59. Диалоговое окно для комментария при фиксации изменений о блокировке папки
Блокировка папок и файлов
Вообще блокировку использовать не рекомендуется, так как это может вызвать остановку работы ваших коллег. Но иногда возникают случаи, когда нужно, чтобы папки и файлы были доступны для изменения только одному человеку. В таком случае их можно заблокировать командой Get lock (рис. 58). Не забывайте оставлять комментарий ваших
Рис. 58. Блокировка папки в рабочей копии
действий (рис. 59). В результате выполнения команды любые попытки ваших коллег зафиксировать изменения в репозитории будут блокироваться (рис. 60).
Важное замечание. Помните, пока вы не разблокируете папки и файлы командой Release lock, ваши коллеги не смогут их модифицировать, и результат их труда может пропасть.
Продолжение следует