2011-01-31 8 views
15

Io lavoro in una squadra dove abbiamo un codice in un repository Mercurial con diversi subrepositories:Mercurial Subrepositories: prevenire commit ricorsive accidentali e spinge

main/ 
main/subrepo1/ 
main/subrepo1/subrepo2/ 

Il comportamento predefinito di Mercurial è che quando un hg commit viene eseguita in "main", anche tutte le modifiche in sospeso nei sottoregisti "subrepo1" e "subrepo2" saranno confermate. Allo stesso modo, quando viene premuto "main", vengono inviati anche tutti i commit in uscita in "subrepo1" e "subrepo2".

Troviamo che le persone spesso impegnano inavvertitamente e spingono le modifiche nei loro sottoregosti (perché hanno dimenticato di aver apportato modifiche, e hg status per impostazione predefinita non mostra modifiche ricorsive). Troviamo anche che tali impegni/spinte globali sono quasi sempre accidentali nella nostra squadra.

Mercurial 1.7 ha recentemente migliorato la situazione con hg status -S e hg outgoing -S, che mostrano le modifiche nei sottoregisti; ma ancora, questo richiede che le persone prestino attenzione.

C'è un modo in Mercurial per fare hg commit e hg push interrompere se ci sono modifiche/impegna in subrepostories che altrimenti sarebbero commessi/spinto?

+0

La soluzione di Ry4an sembra saggia in molte circostanze, ma l'approccio basato su script della risposta accettata è stato alla fine quello che ho usato; Fin qui tutto bene. – davidg

risposta

7

Mercurial 2.0 impedisce automaticamente di inviare sottorappresentazioni a meno che non venga specificato manualmente l'argomento --subrepos (o, in alternativa, -S) su commit.

Ad esempio, si tenta di eseguire un commit mentre ci sono modifiche in sospeso in un subrepository, si ottiene il seguente messaggio:

# hg commit -m 'change main repo' 
abort: uncommitted changes in subrepo hello 
(use --subrepos for recursive commit) 

È possibile eseguire correttamente il commit, tuttavia, con l'aggiunta di --subrepos al comando :

# hg commit --subrepos -m 'commit subrepos' 
committing subrepository hello 

Alcune cose di essere ancora attenti a: Se è stato modificato il revisione un subrepository è attualmente a, ma non i contenuti del sottorepository, Mercurial impegnerà felicemente la modifica della versione senza il flag --subrepos. Inoltre, le spinte ricorsive vengono ancora eseguite senza preavviso.

2

può essere un gancio pre-commit (not precommit) potrebbe fare il hg status -S per voi, e bloccare il commit se rileva eventuali modifiche?

+1

Urgh. La distinzione in Mercurial tra 'precommit' e' pre-commit' è terribile. Avevo provato il primo senza molta fortuna, ma il secondo sembra più promettente. – davidg

+0

Sì, la somiglianza dei nomi è sfortunata. C'è un pre-X e post-X per ogni comando e poi c'è un hook precommit indipendente che viene eseguito prima del commit effettivo. –

4

Una nozione consiste nell'utilizzare gli URL per i quali si dispone dell'accesso in sola lettura nei file .hgsub. Quindi, quando in realtà vuoi spingere il sottorepo, puoi semplicemente inserirvi un CD e fare un hg push THE_READ_WRITE_URL.

+0

Idea interessante. Questo ha il vantaggio (e il problema) di essere un cambiamento che riguarda tutti gli utenti. Immagino che un modo per farlo sia quello di servire hg su http per la sola lettura e consentire l'accesso standard ssh per la lettura/scrittura. – davidg

+0

Questa è sempre stata la mia preferenza comunque. In un ambiente aziendale ho impostato un repository http: // di sola lettura in modo che le persone possano navigare sul Web o clonare senza preoccuparsi dei controlli di accesso e quindi utilizzare ssh: // per qualsiasi requisito di accesso in scrittura con accesso selettivo. –

2

Una possibile soluzione, utilizzando l'idea di "pre-commit" di VonC.

Impostare due script; la prima 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 

Il secondo, 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 

Aggiungere il seguente alla .hgrc:

[hooks] 
pre-commit.subrepo = check_subrepo_commit.sh 
pre-push.subrepo = check_subrepo_push.sh 

Per impostazione predefinita, hg push e hg commit interrompe se ci sono cambiamenti in sospeso in sotto-territori. L'esecuzione di un comando in questo modo:

SUBREPO=1 hg commit 

avrà la precedenza sul controllo, consentendo di eseguire il commit globale/push se si vuole veramente.

8

Da Mercurial 1.8 è disponibile un'impostazione di configurazione pari a disables recursive commits. Nei repository genitore .hg/hgrc è possibile aggiungere:

[ui] 
commitsubrepos = no 

Se un commit nel repository genitore trova modifiche non in un subrepository tutta la conferma è abortita, invece di impegnarsi in silenzio le subrepositories.

+2

L'impostazione predefinita è cambiata per questa opzione in Mercurial 2.0, quindi 'hg commit' non si interromperà di default se c'è un subrepository sporco. –

Problemi correlati