Я являюсь сторонником системы контроля версий Git, но на работе приходится использовать Mercurial он же hg. При переключении с git на hg некоторые вещи кажутся неочевидными. Хочу изложить свои ежедневные незамысловатые действия при работе c mercurial.
После того, как вы изменили файлы, я настоятельно рекомендую сделать перед коммитом
hg pull -u
Mercurial (далее hg) почему-то не умеет fast-forward, как git, и если кто-то менял какие-то файлы до вас, которые вы даже не трогали, то если вы закоммитите, а потом попробуете запушить изменения при устаревшей копии репозитория, то hg откажется пушить, ссылаясь на то, что вы создаете новый head. По-моему это полный бред, но приходится мерджить чужие изменения отдельным коммитом. Еще из минусов работы с hg хочу подметить совсем неочевидную и неудобную работу с ветками и модулями hg. Главная ветка называется default. Во-первых, находясь в ветке default и выполняя команду hg log, вы зачем-то видите историю других веток, хотя они еще не вмерджены в default, которая перемешивается и путает, приходится вызывать команду log с ключом -b default. Во-вторых, вы не можете без лишнего геморроя сделать локальную ветку, казалось бы, что проще, чем создать локальную ветку с какой-то фичей/фиксом, потом слить ее с default, смерджить и запушить, но не тут-то было. Зачем-то разработчики hg все усложнили и вместо локальных веток сделали «секретные» изменения. Например, вы хотите создать а-ля локальную ветку, что-то там наговнокодить, потом переключиться на дефолтную и продолжить работу с ней, но, чтоб ваш говнокод не залился в репу. Ваши действия в git:
git checkout -b govnocode
git commit -am 'my local changes'
git checkout master
git commit -am 'my public changes'
git push
Ваши действия в hg:
hg branch govnocode
hg commit -m 'my local changes'
hg phase --force --secret .
hg update default
hg pull -u
hg commit -m 'my public changes'
hg push
Как видите, действий получается больше, это не учитывая то, что вам еще нужно включить модуль phase в hgrc. Ниже я приведу свой hgrc, в котором будет понятно, как его включить. Если вы, не дай бог, захотите смреджить свои изменения из секретной ветки, то вам придется рассекретить ее и все коммиты в ней, что доставит вам немного боли.
Как посмотреть изменения между ревизиями:
hg diff -r 1:2
Как посмотреть изменения, сделанные в ревизии 2:
hg di -c 2
Как посмотреть изменения, сделанные две ревизии назад:
hg di -c tip~2
Как узнать, кто наговнокодил в файле:
hg blame -nud some/file
Если файл слишком большой, то перенаправьте вывод в less/vim, т.к. по умолчанию hg выводит все тупо на stdout.
Как посмотреть информацию о текущей репе:
hg paths
Как сравнить локальную копию репы с удаленной:
hg summary --remote
Как посмотреть номер текущей ревизии:
hg identify --num
Как закоммитить только часть локальных изменений:
hg record
Опять же, модуль record надо включать.
Как откатить локальные незакомиченные изменения:
hg revert .
Как полностью удалить все незакомиченные изменения и вернуться к последней ревизии:
hg update --clean .
hg зачем-то создает .orig файлы с вашими откачеными изменениями.
Как откатить последний коммит, который еще не запушен:
hg rollback
Как откатить коммит, который был запушен:
hg backout -r 2
2 — это номер ревизии. При этом нельзя откатить коммит, в котором был мердж, трам пам пам.
Ну и при merge вас ждет увлекательное приключение с vimdiff и хер поймешь что где тремя окнами в нем. В моем hgrc более логичная разбивка окон vimdiff: всего три окна, в левом локальная копия, в центральном то, что получится после merge, а в правом то, откуда мерджится.
Как удалить недобавленные файлы:
hg purge
Ну, а вот и мой hgrc, может кому-то пригодится.
[ui]
merge = vimdiff
username = insider <insider@prolinux.org>
[merge-tools]
vimdiff.executable = vim
vimdiff.args = -d -c "wincmd l" $local $output $other
vimdiff.premerge = keep
[auth]
bb.prefix = https://hg.somecompany.net/
bb.username = insider
bb.password = hgadmincantsshkeys
[alias]
uu = !hg pull && hg up
lg = log --template '{node|short} | {date|isodatesec} | {author|user}: {desc|strip|firstline}\n'
[extensions]
strip =
record =
convert =
purge =
На этом всё, переходите на git!