2014-04-16 8 views
22

Sono consapevole che si può chiudere un ramo Mercurial con:Puoi chiudere un ramo Mercurial senza aggiornarlo prima?

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

Tuttavia, alcuni dei repository con cui lavoro una piuttosto grande, e dopo aver scoperto un ramo sciolto da anni fa che voglio chiudere, l'aggiornamento ad esso in primo luogo può richiedere molti minuti (se non ore), solo per fare un commit e quindi aggiornare di nuovo alla revisione originale da cui stavo lavorando (più minuti, se non ore).

Quindi la mia domanda, c'è un modo per chiudere un ramo Mercurial senza aggiornare la directory di lavoro alla revisione del ramo prima?

risposta

35

Sì, è possibile, ma questo non è documentato da nessuna parte. Ho usato questa tecnica per molto tempo, non ti preoccupare, è sicuro.

Invece di aggiornamento, è possibile eseguire i seguenti comandi

hg debugsetparent <revision> 
hg branch <branchOfRevision> 

Nota che l'ordine è importante. Questo farà sì che il tuo repository pensi che sia sulla nuova revisione, mentre tutti i tuoi file sono quelli iniziali. Successivamente, è possibile utilizzare il commit --close-branch, ma utilizzare l'opzione -X * per eseguire un commit vuoto.

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

Ora, torna semplicemente alla tua testa precedente, come se nulla fosse accaduto.

hg debugsetparent <InitialRevision> 
hg branch <branchOfInitialRevision> 

Infine, se si dispone di sub-repos, si potrebbe desiderare di rinominare temporaneamente il file .hgsub prima di commettere il --close-branch, e rinominare indietro dopo.

+5

Intelligente! Come dev del Mercurial, questa tecnica mi sembra corretta. –

+0

@ MartinGeisler Grazie! Naturalmente, questo è usato in uno script e, se dovesse fallire in qualsiasi momento, tornerebbe automaticamente allo stato iniziale. Lascia che ti chieda, pensi che dovrebbe essere rilasciato un 'debugrebuildstate' prima di finire? – Vince

+0

Non sembra che sarebbe necessario. 'debugrebuilddirstate' cancella il file dirstate che costringe Mercurial a confrontare i file su disco con la sua rappresentazione interna. Dal momento che si aggiorna nuovamente al punto in cui è stato avviato, il file dirstate sarà corretto. –

1

Grazie a Vince per l'approccio. L'ho implementato come script Python: era un po 'più di lavoro di quanto mi aspettassi inizialmente, quindi spero che questo salvi altri un po' di tempo. Testato su Windows 8.1 con TortoiseHg 3.3 e Python 2.7.9.

Feedback benvenuto, potrebbe probabilmente fare con un po 'di finezza, in particolare per quanto riguarda la gestione degli errori.

#!/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()