Pull to refresh

Mercurial: как увидеть лес за деревьями?

Reading time 2 min
Views 2.4K
Mercurial (он же Hg) — весьма приятная распределенная система контроля версий (distributed VCS). Среди удобств DVCS вообще и Hg в частности можно особо выделить высокую гибкость. Репозиторий может называться как угодно, копироваться куда угодно, коммититься в продакшн по произвольным цепочкам (скажем, через QA или напрямую) и так далее.

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

Если два репозитория вложить один в другой, Mercurial будет рассматривать их изолированно. Команды, адресуемые внешнему репозиторию, не распространяются на вложенный. Но как же управляться с проектом, если он раздроблен на изолированные фрагменты — этакие пузырьки, один в другом? Или, другими словами, как нам за деревьями (репозиториями) увидеть лес (проект) и работать на его уровне? От мучений нас избавит ForestExtension — расширение для Mercurial. Этот Forest добавляет несколько команд, идентичных базовым, но учитывающих вложенность репозиториев.

Скажем, мы взяли на дом большой составной проект, наисправляли файлов во всех модулях и хотим их затолкать обратно. Команда fclone (forest clone) скопирует нам «лес» вложенных репозиториев (т.е. проект), команда fstatus (forest status) покажет состояние всего «леса» (надо ли что-то закоммитить?), а fpush (forest push) затолкает все измененные файлы обратно, причем сделает это для всего «леса» сразу, т.е. нам не придется ползать по каталогам. В данном случае «обратно» — это в исходный, публичный «лес» проекта. Если же захочется еще и оттуда протолкнуть изменения в какие-то сторонние репозитории, достаточно в рамках проекта повторить ту же fpush — и готово.

Создадим два репозитория, в каждом по текстовому файлу:

$ mkdir repo-one
$ cd repo-one
$ hg init
$ echo "hello" > hello.txt
$ hg ci -m"init one"
$ cd ..


$ mkdir repo-two
$ cd repo-two
$ hg init
$ echo "hello" > hello.txt
$ hg ci -m"init two"
$ cd ..


Копируем первый репозиторий внутрь второго:

$ hg clone repo-one repo-two/one

Не забываем, что repo-two/one не является частью repo-two, он просто вложен туда.

А теперь на сцену выходит Forest. Команда fclone аналогична команде clone, но, в отличие от нее, не игнорирует вложенные репозитории.

$ hg fclone repo-two wc-two

Мы только что сделали локальную копию repo-two, включая repo-two/one (копия repo-one).

Внесем какие-то изменения в repo-two/hello.txt и repo-two/one/hello.txt (листинг опустим).

Коммитим изменения в каждом из репозиториев отдельно (нетрудно догадаться, почему «лесного» аналога команды commit не существует):

$ cd wc-two/ && ls
one hello.txt
$ hg ci -m"edited hello.txt"
$ cd one/
$ hg ci -m"edited hello.txt"
$ cd ..


Толкаем результат обратно в repo-two:

$ hg fpush

Все, теперь в repo-two содержатся измененные файлы repo-two/hello.txt и repo-two/one/hello.txt.

Следующим этапом может быть проталкивание изменений дальше, т.е. в repo-one:

$ cd ../repo-two
$ hg fpush


Готово; теперь изменения из repo-two/one прошли в repo-one. Вот и всё.

Вместо repo-two/one может быть целый набор деревьев, и fpush обработает их все.

(оригинал топика сидит тут: http://neithere.livejournal.com/381205.html)
Tags:
Hubs:
+13
Comments 4
Comments Comments 4

Articles