2011-01-31 9 views
15

Yo trabajo en un equipo en el que tenemos un código en un repositorio mercurial con varios subrepositories:Mercurial Subrepositories: Prevenir compromete recursivas accidentales y empuja

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

El comportamiento predeterminado de Mercurial es que cuando un hg commit se realiza en "principal", también se confirmarán los cambios pendientes en los subrepositorios "subrepo1" y "subrepo2". De manera similar, cuando se presiona "main", también se presionarán las confirmaciones salientes en "subrepo1" y "subrepo2".

Encontramos que las personas con frecuencia involuntariamente confirman y presionan cambios en sus subrepositorios (porque olvidaron que habían realizado cambios, y hg status de manera predeterminada no muestra cambios recursivos). También encontramos que tales compromisos/empujes globales son casi siempre accidentales en nuestro equipo.

Mercurial 1.7 mejoró recientemente la situación con hg status -S y hg outgoing -S, que muestran cambios en los subrepositorios; pero aún así, esto requiere que la gente esté prestando atención.

¿Hay una manera de Mercurial para hacer hg commit y hg push abortar si hay cambios/compromete en subrepostories que de otro modo se cometerían/​​empujó?

+0

La solución de Ry4an suena sensata en muchas circunstancias, pero el enfoque basado en guiones de la respuesta aceptada fue finalmente lo que usé; Hasta aquí todo bien. – davidg

Respuesta

7

Mercurial 2.0 impide automáticamente la ejecución de subrepositorios a menos que especifique manualmente el argumento --subrepos (o, alternativamente, -S) en commit.

Por ejemplo, intenta realizar un commit mientras que hay cambios pendientes en un subrepository, se obtiene el siguiente mensaje:

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

Puede llevar a cabo con éxito el comprometerse, sin embargo, mediante la adición de --subrepos al comando :

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

Algunas cosas que todavía tenga cuidado acerca de: Si ha cambiado la revisión un subrepository se encuentra actualmente en, pero no los contenidos del subrepositorio, Mercurial se comprometerá felizmente a cambiar la versión sin el --subrepos. Además, los empujes recursivos todavía se realizan sin previo aviso.

2

puede ser un gancho pre-commit (not precommit) podría hacer el hg status -S para usted, y el bloque el commit si detecta algún cambio?

+1

Urgh. La distinción en Mercurial entre 'precommit' y' pre-commit' es terrible. Probé el primero sin mucha suerte, pero el segundo parece más prometedor. – davidg

+0

Sí, la similitud de nombres es desafortunada. Hay un pre-X y un post-X para cada comando y luego hay un enganche precommitido independiente que se ejecuta antes de la confirmación real. –

4

Una noción es utilizar las URL a las que tiene acceso de solo lectura en sus archivos .hgsub. Luego, cuando realmente desee insertar el subrepo, puede simplemente ingresarlo y hacer un hg push THE_READ_WRITE_URL.

+0

Interesante idea. Esto tiene el beneficio (y el problema) de ser un cambio que afecta a todos los usuarios. Supongo que una forma de hacerlo es servir hg en lugar de http para solo lectura, y permitir acceso ssh estándar para lectura/escritura. – davidg

+0

Eso siempre ha sido mi preferencia de todos modos. En una configuración corporativa configuré un http: // repo de solo lectura para que las personas puedan navegar o clonar sin preocuparse por los controles de acceso, y luego usar ssh: // para cualquier requisito de acceso de escritura de acceso selectivo. –

2

Una posible solución, usando la idea de "precompromiso" de VonC.

Configurar dos scripts; la primera 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 

La segunda, 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 

Añadir lo siguiente a su .hgrc:

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

Por defecto, hg push y hg commit abortará si hay cambios pendientes en subrepositorios. Ejecución de un comando de este modo:

SUBREPO=1 hg commit 

anulará el registro de entrada, lo que permite realizar el mundial comprometerse/push si realmente quiere.

8

Dado que Mercurial 1.8 hay un ajuste de configuración que disables recursive commits. En los repositorios de padres .hg/hgrc puede agregar:

[ui] 
commitsubrepos = no 

Si un commit en el repositorio padre encuentra cambios no confirmados en un subrepository el conjunto se aborta, en lugar de comprometerse en silencio los subrepositories.

+2

El valor predeterminado ha cambiado para esta opción en Mercurial 2.0, por lo que 'hg commit' no se cancelará por defecto si hay un subrepositorio sucio. –