Mercurial Subrepositories: предотвращать случайные рекурсивные коммиты и толкает
Я работаю над командой, где у нас есть код в ртутном репозитории с несколькими субрепозиториями:
main/
main/subrepo1/
main/subrepo1/subrepo2/
Поведение Mercurial по умолчанию заключается в том, что когда a hg commit
выполняется в "main", любые выдающиеся изменения в субрепозиториях "subrepo1" и "subrepo2" также будут зафиксированы. Точно так же, когда нажата клавиша "main", любые исходящие транзакции в "subrepo1" и "subrepo2" также будут нажаты.
Мы обнаруживаем, что люди часто непреднамеренно фиксируют и нажимают изменения в своих субрепозиториях (потому что они забыли, что они внесли изменения, а hg status
по умолчанию не показывают рекурсивных изменений). Мы также обнаруживаем, что такие глобальные коммиты/толкания практически всегда случайны в нашей команде.
Mercurial 1.7 недавно улучшил ситуацию с hg status -S
и hg outgoing -S
, которые показывают изменения в субрепозиториях; но все же это требует от людей внимания.
Есть ли способ в Mercurial сделать hg commit
и hg push
отменять, если есть изменения/коммиты в подрепостах, которые иначе были бы сделаны/нажаты?
Ответы
Ответ 1
Mercurial 2.0 автоматически запрещает вам выполнять субрепозитории, если вы вручную не укажете аргумент --subrepos
(или, альтернативно, -S
) commit
.
Например, вы пытаетесь выполнить фиксацию во время ожидающих изменений в субрепозитории, вы получаете следующее сообщение:
# hg commit -m 'change main repo'
abort: uncommitted changes in subrepo hello
(use --subrepos for recursive commit)
Вы можете успешно выполнить фиксацию, добавив --subrepos
к команде:
# hg commit --subrepos -m 'commit subrepos'
committing subrepository hello
Некоторые вещи по-прежнему будут осторожны: если вы изменили ревизию, в данный момент находится подредактор, но не содержимое подрепозитория, Mercurial с радостью совершит изменение версии без флага --subrepos
. Кроме того, рекурсивные нажатия все еще выполняются без предупреждения.
Ответ 2
Так как Mercurial 1.8 установлен параметр конфигурации, отключает рекурсивные коммиты. В родительских репозиториях .hg/hgrc
вы можете добавить:
[ui]
commitsubrepos = no
Если фиксация в родительском репозитории обнаруживает незавершенные изменения в подрепозитории, вся фиксация прерывается, вместо того, чтобы молча выполнять субрепозитории.
Ответ 3
Одно из них - использовать URL-адреса, к которым у вас есть доступ только для чтения в ваших файлах .hgsub
. Затем, когда вы действительно хотите нажать в подрепо, вы можете просто вставить его в него и сделать hg push THE_READ_WRITE_URL
.
Ответ 4
Одно возможное решение, используя идею VonC "pre-commit".
Настройте два сценария; первый check_subrepo_commit.sh
:
#!/bin/bash
# If the environment variable "SUBREPO" is set, allow changes.
[ "x$SUBREPO" != "x" ] && exit 0
# Otherwise, ensure that subrepositories have not changed.
LOCAL_CHANGES=`hg status -a -m`
GLOBAL_CHANGES=`hg status -S -a -m`
if [ "x${LOCAL_CHANGES}" != "x$GLOBAL_CHANGES" ]; then
echo "Subrepository changes exist!"
exit 1
fi
exit 0
Второй, check_subrepo_push.sh
:
#!/bin/bash
# If the environment variable "SUBREPO" is set, allow changes.
[ "x$SUBREPO" != "x" ] && exit 0
# Otherwise, ensure that subrepositories have not changed.
LOCAL_CHANGES=`hg outgoing | grep '^changeset:'`
GLOBAL_CHANGES=`hg outgoing -S | grep '^changeset:'`
if [ "x${LOCAL_CHANGES}" != "x$GLOBAL_CHANGES" ]; then
echo "Global changes exist!"
exit 1
fi
exit 0
Добавьте в свой .hgrc
следующее:
[hooks]
pre-commit.subrepo = check_subrepo_commit.sh
pre-push.subrepo = check_subrepo_push.sh
По умолчанию hg push
и hg commit
будут прерваны, если в субрепозиториях будут обнаружены неполадки. Выполнение такой команды:
SUBREPO=1 hg commit
переопределит проверку, позволяя вам выполнить глобальный фиксатор/нажатие, если вы действительно этого хотите.
Ответ 5
Может быть крючок pre-commit
(not precommit
) может сделать hg status -S
для вас и заблокировать фиксацию, если он обнаружит какие-либо изменения?