Можете ли вы закрыть филиал Mercurial, не обновляясь сначала?

Я знаю, что вы можете закрыть ветвь Mercurial с помощью:

hg update rev-number
hg commit --close-branch -m "Closing branch."

Однако некоторые из репозиториев я работаю с довольно большим, и после того, как многие годы назад я обнаружил свободную ветку, которую я хочу закрыть, обновление для нее сначала может занять много минут (если не часов), только для того, чтобы сделать одно коммит а затем обновить исходную версию, над которой я работал (больше минут, если не часов).

Итак, мой вопрос, есть ли способ закрыть ветвь Mercurial, не обновляя сначала рабочий каталог до ревизии ветки?

Ответ 1

Да, вы можете, но это нигде не документировано. Я использовал эту технику в течение длительного времени, не волнуйтесь, это безопасно.

Вместо обновления вы можете выпустить следующие команды

hg debugsetparent <revision>
hg branch <branchOfRevision>

Обратите внимание, что порядок важен. Это заставит ваше репо подумать, что оно находится в новой редакции, а все ваши файлы от исходного. После этого вы можете использовать фиксацию --close-branch, но используйте параметр -X *, чтобы сделать пустую фиксацию.

hg commit --close-branch -X * -m "Closing branch."

Теперь просто вернитесь к предыдущей голове, как будто ничего не произошло.

hg debugsetparent <InitialRevision>
hg branch <branchOfInitialRevision>

Наконец, если у вас есть субрепозиции, вы можете временно переименовать файл .hgsub, прежде чем совершать --close-branch, а затем переименовать обратно.

Ответ 2

Спасибо Винсу за подход. Я реализовал это как Python script - это была немного больше работы, чем я ожидал, поэтому, надеюсь, это сэкономит время на некоторое время. Протестировано на Windows 8.1 с помощью TortoiseHg 3.3 и Python 2.7.9.

Обратная связь приветствуется, возможно, это связано с некоторой утонченностью, особенно в отношении обработки ошибок.

#!/usr/bin/python

from subprocess import check_output

def close_branch( branch, message ):
    if not message:
        message = 'Closing branch "{}"'.format( branch )
    print( 'Closing branch "{}"'.format( branch ) )
    try:
        check_output( 'hg debugsetparent ' + branch )
        check_output( 'hg branch ' + branch )
        check_output( 'hg commit --close-branch -X * -m "' + message + '"' )
    except:
        print( 'Failed to close branch.' )

def main():
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('branch', help='branch name(s)', nargs = '+' )
    parser.add_argument('-m', '--message', help='message (defaults to "Closing branch <branch name>")' )
    args = parser.parse_args()

    status = check_output( 'hg status' )
    if len(status) > 0:
        print( 'Do not use this script with local changes. Commit/revert changes and try again' )
        exit(1)

    # Cache initial revision and branch.
    initial_revision = check_output( 'hg id -i -b' ).split()
    # print( 'Using: ' + initial_revision[0].decode("utf-8") )

    for branch in args.branch:
        close_branch( branch, args.message )

    # Return to original changeset
    check_output( 'hg debugsetparent ' + initial_revision[0].decode("utf-8") )
    check_output( 'hg branch ' + initial_revision[1].decode("utf-8") )

if __name__ == '__main__':
    main()

Ответ 3

Mercurial 4.8 и выше поставляется с расширенным ядром расширения ядра, который обеспечивает эту функциональность:

hg close-head <revision>

Из справки:

Это эквивалентно проверке каждой ревизии в чистом дереве и запуску "hg commit --close-branch", за исключением того, что она не меняет рабочий каталог.

На данный момент вам нужно явно включить это расширение в вашем [HGRC][]:

[extensions]
closehead =