Это статья для начинающих, постараюсь объяснить непонятные моменты (подразумеваю, что базовые вещи всетаки уже известны) работы в HG.
Когда человек работает с репозиторием один - проблем, как правило, не возникает. Непонятки начинаются, когда с репозиторием работают 2 или более человек. Добавляет бардака "визуальный" софт - TortoiseHg, например. Люди привыкли тыкать одну кнопочку и чтобы "всё было хорошо". А тут куча кнопочек, еще и с невнятным переводом (если используется руссифицированная версия).
Поэтому для обучения категорически рекомендую начинать с работы в консоли.
Самая основная концепция, которую необходимо понять: HG - это децентрализованная система контроля версий. В любой момент времени есть, как минимум, два полноценных репозитория: на удаленном сервере и локальный, в папке проекта. Все изменения, в первую очередь, происходят в локальном репозитории. Чтобы обновить репозиторий на сервере необходимы дополнительные шаги.
Итак, рабочий процесс.
Пришли утром на работу, начинаем работать и выполняем в консоли из директории проекта (подразумеваю, что проект уже есть и вечером предыдущего дня нормально положили всё на сервер):
hg pull -u
Командой hg pull мы обновляем с сервера наш локальный репозиторий (только репозиторий! файлы проекта не трогаются). За обновление файлов проекта отвечает флаг -u. Это всё делается на случай, если были какие-то изменения в коде.
Теперь мы начинаем работать: пишем код, по завершению каждого логического блока выполняем коммит (и сразу пишем комментарий к нему):
hg commit -m "Исправил ошибку #58"
Этой командой мы зафиксировали изменения кода в локальном репозитории. Другим разработчиком ваши изменения пока недоступны! Они хранятся только у вас.
К концу рабочего дня у нас имеется локальный репозиторий с несколькими коммитами в нём.
Теперь нам надо отправить всё наше добро на удаленный сервер - чтобы наши правки были доступны остальным разработчикам. Выполняем команду:
hg push
Этой командой мы отправляем все изменения из локального репозитория в удаленный. Если в удаленном репозитории с утра не было никаких изменений - то все проходит нормально.
Но мы рассмотрим случай с конфликтом. Поэтому в ответ мы получаем:
pushing to ...
searching for changes
abort: push creates new remote heads on branch 'default'!
(you should pull and merge or use push -f to force)
Не надо пугаться такого сообщения - это лишь значит, что в удаленном репозитории произошли изменения и нам необходимо обновить свой локальный репозиторий и произвести слияние своих изменений с другими изменениями.
Для этого выполняем:
hg pull
Этой командой обновляем локальный репозиторий из удаленного. Получаем сообщение:
pulling from ...
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
Теперь у нас в локальном репозитории интересная ситуация - у нас получилось 2 ветки. Одна ветка - изменения с сервера, вторая ветка - наши изменения.
Но нам необходимо из этих двух веток сделать одну, в которой были бы все изменения. Для этого выполяем команду:
hg merge
И если слияние произошло без конфликтов - у нас получается код проекта, к которому применены все изменения.
Мы должны зафиксировать эти изменения:
hg commit -m "Слияние"
И протолкнуть их на сервер:
hg push
Если же при слиянии были конфликты - то открывается программа слияния с тремя версиями конфликтного файла. Это окно всех начинающих повергает в шок :)
Если окно не отрывается, то, возможно, у вас не настроена или не установлена утилита слияния. Рекомендую установить и настроить - интернете множество статей по этой теме.
Утилит слияния много, не буду останавливаться на какой-то конкретно, расскажу общие принципы.
Все они отличаются немного внешним видом, управлением, некоторые отличаются кривостью (встроенная мержилка в NetBeans 6.9.1 выводит меня из себя своим неудобством, поэтому использую meld).
Итак, отображаются 3 версии файла: local, base, remote (в некоторых есть еще и 4 версия - merged). Именно BASE/MERGED вводит всех в ступор.
Расшифрую, что к чему:
LOCAL - файл с вашими правками
REMOTE - файл с сервера
BASE - исходный файл, "не правленный", к которому была попытка применения изменений (локальных и с сервера).
Тут мы подходим к очень деликатному моменту. Как я говорил выше - у нас есть две ветки. В данном случае ветви анонимные - то есть у них нет названия и возникли они из-за конфликта. После слияния ветвление исчезнет и ветви сольются в один "ствол". Поэтому все изменения вносим в файл LOCAL - то есть в наш текущий проект.
Как именно решить конфликт - тут уже разработчик сам прикладывает голову, как модифицировать код, чтобы были и те и другие изменения в итоговом файле.
Смотрим и исправляем все конфликты, сохраняемся и выходим из программы.
После всех исправлений смотрим на работоспособность кода (актуально, если изменения были нетривиальные). После чего коммитим наше слияние и проталкиваем на сервер командами:
hg commit -m "Слияние"
hg push
Рабочий день закончен, с чистой совестью идём домой. Всем спасибо!
PS: Обсудить, задать вопросы по HG можно в специальной теме на нашем форуме.