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 для вас и заблокировать фиксацию, если он обнаружит какие-либо изменения?