Control Distribuido de Revisiones Con Mercurial
-
Upload
lenyn-alcantara -
Category
Documents
-
view
135 -
download
2
Transcript of Control Distribuido de Revisiones Con Mercurial
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 1/204
Control Distribuido de Revisiones con Mercurial
Bryan O’Sullivan
Copyright c 2006, 2007 Bryan O’Sullivan.
Este material puede distribuirse unicamente bajo los terminos y condiciones establecidos en la
version 1.0 de la Licencia de Publicacion Abierta (OPL). Refierase por favor al apendice D para
encontrar el texto de la licencia.
Este libro fue preparado a partir de rev fc4daaad6415, fechado 2009-02-10 00:28 -0500, usando
Mercurial rev Mercurial Distributed SCM (version 1.0.1) .
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 2/204
Indice general
Indice general I
Prefacio 2
0.1. Este libro es un trabajo en progreso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
0.2. Acerca de los ejemplos en este libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
0.3. Colof on—este libro es Libre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1. Introduccion 31.1. Acerca del control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1. ¿Por que usar control de revisiones? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2. La cantidad de nombres del control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2. Historia resumida del control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3. Tendencias en el control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4. Algunas ventajas del control distribuido de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4.1. Ventajas para proyectos de codigo abierto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4.2. Ventajas para proyectos comerciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.5. ¿Por que elegir Mercurial? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.6. Comparacion de Mercurial con otras herramientas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6.1. Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6.2. Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6.3. CVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.6.4. Herramientas comerciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6.5. Elegir una herramienta de control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.7. Migrar de otra herramienta hacia Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2. Una gira de Mercurial: lo basico 11
2.1. Instalar Mercurial en su sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.1. Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.2. Solaris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.3. Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.1.4. Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2. Arrancando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.1. Ayuda integrada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3. Trabajar con un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.3.1. Hacer una copia local de un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3.2. Que hay en un repositorio? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4. Vistazo rapido al historial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.1. Conjuntos de cambios, revisiones, y comunicandose con otras personas . . . . . . . . . . . . 15
2.4.2. Ver revisiones especıficas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.4.3. Informacion mas detallada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
I
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 3/204
2.5. Todo acerca de las opciones para comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.6. Hacer y repasar cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.7. Grabar cambios en un nuevo conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.7.1. Definir un nombre de usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.7.2. Escribir un mensaje de consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.7.3. Escribir un buen mensaje de consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.7.4. Cancelar una consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.7.5. Admirar nuestro trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.8. Compartir cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.8.1. Jalar cambios desde otro repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.8.2. Actualizar el directorio de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.8.3. Empujar cambios a otro repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.8.4. Compartir cambios a traves de una red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3. Una gira de Mercurial: fusionar trabajo 26
3.1. Fusionar lıneas de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.1.1. Conjuntos de cambios de frentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.1.2. Hacer la fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.1.3. Consignar los resultados de la fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2. Fusionar cambios con conflictos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303.2.1. Usar una herramienta grafica para fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2.2. Un ejemplo real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3. Simplificar el ciclo jalar-fusionar-consignar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4. Tras bambalinas 36
4.1. Registro del historial de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.1.1. Seguir el historial de un unico fichero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.1.2. Administracion de ficheros monitoreados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.1.3. Registro de informacion del conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . 36
4.1.4. Relaciones entre revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2. Almacenamiento seguro y eficiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.2.1. Almacenamiento eficiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.2.2. Operacion segura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384.2.3. Recuperacion rapida de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.2.4. Identificacion e integridad fuerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.3. Historial de revisiones, ramas y fusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.4. El directorio de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.4.1. Que pasa en una consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.4.2. Creacion de un nuevo frente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.4.3. Fusion de frentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.5. Otras caracterısticas de diseno interesantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.5.1. Compresion ingeniosa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.5.2. Reordenado de lectura/escritura y atomicidad . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.5.3. Acceso concurrente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.5.4. Evitar movimientos de brazo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.5.5. Otros contenidos del estado de directorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5. Mercurial dıa a dıa 49
5.1. Como indicarle a Mercurial que ficheros seguir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.1.1. Nombramiento explıcito e implıcito de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.1.2. Nota al margen: Mercurial trata ficheros, no directorios . . . . . . . . . . . . . . . . . . . . . 50
5.2. Como dejar de hacer seguimiento a un fichero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
II
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 4/204
5.2.1. Al eliminar un fichero no se afecta su historial . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.2.2. Ficheros perdidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.2.3. Nota al margen: ¿Por que decirle explıcitamente a Mercurial que elimine un fichero? . . . . . 52
5.2.4. Atajo util—agregar y eliminar ficheros en un solo paso . . . . . . . . . . . . . . . . . . . . . 52
5.3. Copiar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.3.1. Resultados de copiar un fichero durante una fusion . . . . . . . . . . . . . . . . . . . . . . . 53
5.3.2. ¿Por que los cambios se reflejan en las copias? . . . . . . . . . . . . . . . . . . . . . . . . . 545.3.3. Como hacer que los cambios no sigan a la copia? . . . . . . . . . . . . . . . . . . . . . . . . 54
5.3.4. Comportamiento de la orden “hg copy” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5.4. Renombrar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.4.1. Renombrar ficheros y fusionar cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.4.2. Cambios de nombre divergentes y fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.4.3. Cambios de nombre convergentes y fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.4.4. Otros casos lımite relacionados con renombramientos . . . . . . . . . . . . . . . . . . . . . . 57
5.5. Recuperarse de equivocaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6. Colaborar con otros 59
6.1. La interfaz web de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.2. Modelos de colaboracion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.2.1. Factores a tener en cuenta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606.2.2. Anarquıa informal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.2.3. Un repositorio central unico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.2.4. Trabajo con muchas ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.2.5. Ramas de caracterısticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.2.6. El tren de publicacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.2.7. El modelo del kernel Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.2.8. Solamente jalar frente a colaboracion publica . . . . . . . . . . . . . . . . . . . . . . . . . . 64
6.2.9. Cuando la colaboracion encuentra la administracion ramificada . . . . . . . . . . . . . . . . 64
6.3. Aspectos tecnicos de la colaboracion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.4. Compartir informalmente con “hg serve” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.4.1. Cuestiones adicionales para tener en cuenta . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.5. Uso del protocolo Secure Shell (ssh) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.5.1. Como leer y escribir URLs de ssh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666.5.2. Encontrar un cliente ssh para su sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
6.5.3. Generar un par de llaves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6.5.4. Uso de un agente de autenticacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6.5.5. Configurar el lado del servidor apropiadamente . . . . . . . . . . . . . . . . . . . . . . . . . 67
6.5.6. Compresion con ssh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6.6. Servir sobre HTTP usando CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6.6.1. Lista de chequeo de la configuracion del servidor web . . . . . . . . . . . . . . . . . . . . . 69
6.6.2. Configuracion basica de CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
6.6.3. Compartir varios repositorios con un guion CGI . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.6.4. Descarga de ficheros fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.6.5. Opciones de configuracion en Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
7. Nombres de ficheros y asociacion de patrones 757.1. Nombrado de ficheros simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.2. Ejecucion de comandos sin ningun nombre de fichero . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.3. Reportar que esta pasando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
7.4. Uso de patrones para identificar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
7.4.1. Patrones glob estilo interprete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
7.4.2. Asociacion con patrones de expresiones regulares re . . . . . . . . . . . . . . . . . . . . . . 78
II I
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 5/204
7.5. Filtrado de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7.6. Ignorar ficheros y directorios no deseados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7.7. Sensibilidad a mayusculas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7.7.1. Almacenamiento portable y seguro de repositorios . . . . . . . . . . . . . . . . . . . . . . . 80
7.7.2. Deteccion de conflictos de mayusculas/minusculas . . . . . . . . . . . . . . . . . . . . . . . 80
7.7.3. Arreglar un conflicto de mayusculas/minusculas . . . . . . . . . . . . . . . . . . . . . . . . 80
8. Administracion de versiones y desarrollo ramificado 81
8.1. Dar un nombre persistente a una revision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
8.1.1. Manejo de conflictos entre etiquetas durante una fusion . . . . . . . . . . . . . . . . . . . . . 83
8.1.2. Etiquetas y clonado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
8.1.3. Cuando las etiquetas permanentes son demasiado . . . . . . . . . . . . . . . . . . . . . . . . 84
8.2. El flujo de cambios—El gran cuadro vs. el pequeno . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
8.3. Administrar ramas en repositorios estilo gran cuadro . . . . . . . . . . . . . . . . . . . . . . . . . . 84
8.4. No repita trabajo: fusion entre ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
8.5. Nombrar ramas dentro de un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
8.6. Tratamiento de varias ramas nombradas en un repositorio . . . . . . . . . . . . . . . . . . . . . . . . 88
8.7. Nombres de ramas y fusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.8. Normalmente es util nombrar ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
9. Encontrar y arreglar sus equivocaciones 91
9.1. Borrar el historial local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
9.1.1. La consignacion accidental . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
9.1.2. Hacer rollback una transaccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
9.1.3. Erroneamente jalado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
9.1.4. Despues de publicar, un roll back es futil . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
9.1.5. Solamente hay un roll back . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
9.2. Revertir un cambio equivocado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
9.2.1. Errores al administrar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
9.3. Tratar cambios consignados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
9.3.1. Retroceder un conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
9.3.2. Retroceder el conjunto de cambios punta . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
9.3.3. Retroceso de un cambio que no es la punta . . . . . . . . . . . . . . . . . . . . . . . . . . . 969.3.4. Mas control sobre el proceso de retroceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
9.3.5. Por que “hg backout” hace lo que hace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
9.4. Cambios que nunca debieron ocurrir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
9.4.1. Como protegerse de cambios que han “escapado” . . . . . . . . . . . . . . . . . . . . . . . . 102
9.5. Al encuentro de la fuente de un fallo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
9.5.1. Uso de la orden “hg bisect” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
9.5.2. Limpieza despues de la busqueda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
9.6. Consejos para encontrar fallos efectivamente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9.6.1. Dar una entrada consistente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9.6.2. Automatizar tanto como se pueda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9.6.3. Verificar los resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9.6.4. Tener en cuenta la interferencia entre fallos . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9.6.5. Acotar la busqueda perezosamente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
10. Manejo de eventos en repositorios mediante ganchos 109
10.1. Vistazo general de ganchos en Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
10.2. Ganchos y seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
10.2.1. Los ganchos se ejecutan con sus privilegios de usuario . . . . . . . . . . . . . . . . . . . . . 110
10.2.2. Los ganchos no se propagan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
IV
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 6/204
10.2.3. Es posible hacer caso omiso de los ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
10.2.4. Asegurarse de que ganchos crıticos sean ejecutados . . . . . . . . . . . . . . . . . . . . . . . 111
10.3. Precauciones con ganchos pretxn en un repositorio de acceso compartido . . . . . . . . . . . . . . . 111
10.3.1. Ilustracion del problema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
10.4. Tutorial corto de uso de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
10.4.1. Llevar a cabo varias acciones por evento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
10.4.2. Controlar cuando puede llevarse a cabo una actividad . . . . . . . . . . . . . . . . . . . . . . 11310.5. Escribir sus propios ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
10.5.1. Escoger como debe ejecutarse su gancho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
10.5.2. Parametros para ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
10.5.3. Valores de retorno de ganchos y control de actividades . . . . . . . . . . . . . . . . . . . . . 114
10.5.4. Escribir un gancho externo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
10.5.5. Indicar a Mercurial que use un gancho interno . . . . . . . . . . . . . . . . . . . . . . . . . . 115
10.5.6. Escribir un gancho interno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
10.6. Ejemplos de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
10.6.1. Escribir mensajes de consignacion significativos . . . . . . . . . . . . . . . . . . . . . . . . 115
10.6.2. Comprobar espacios en blanco finales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
10.7. Ganchos adicionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
10.7.1. acl—control de acceso a partes de un repositorio . . . . . . . . . . . . . . . . . . . . . . . . 117
10.7.2. bugzilla—integracion con Bugzilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11910.7.3. notify—enviar notificaciones de correo electronico . . . . . . . . . . . . . . . . . . . . . . 122
10.8. Informacion para escritores de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
10.8.1. Ejecucion de ganchos internos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
10.8.2. Ejecucion de ganchos externos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
10.8.3. Averiguar de donde vienen los conjuntos de cambios . . . . . . . . . . . . . . . . . . . . . . 125
10.9. Referencia de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
10.9.1. changegroup—luego de anadir conjuntos de cambios remotos . . . . . . . . . . . . . . . . . 125
10.9.2. commit—luego de la creacion de un nuevo conjunto de cambios . . . . . . . . . . . . . . . . 126
10.9.3. incoming—luego de que un conjunto de cambios remoto es anadido . . . . . . . . . . . . . 126
10.9.4. outgoing—luego de la propagacion de los conjuntos de cambios . . . . . . . . . . . . . . . 126
10.9.5. prechangegroup—antes de empezar la adicion de conjuntos de cambios remotos . . . . . . 127
10.9.6. precommit—antes de iniciar la consignacion de un conjunto de cambios . . . . . . . . . . . 127
10.9.7. preoutgoing—antes de empezar la propagacion de conjuntos de cambios . . . . . . . . . . 12710.9.8. pretag—antes de etiquetar un conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . 128
10.9.9. pretxnchangegroup —antes de completar la adicion de conjuntos de cambios remotos . . . . 128
10.9.10.pretxncommit—antes de completar la consignacion de un nuevo conjunto de cambios . . . . 128
10.9.11.preupdate—antes de actualizar o fusionar el directorio de trabajo . . . . . . . . . . . . . . . 129
10.9.12.tag—luego de etiquetar un conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . 129
10.9.13.update—luego de actualizar o fusionar el directorio de trabajo . . . . . . . . . . . . . . . . . 129
11. Personalizar los mensajes de Mercurial 130
11.1. Usar estilos que vienen con Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
11.1.1. Especificar un estilo predeterminado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
11.2. Ordenes que soportan estilos y plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
11.3. Cuestiones basicas de plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
11.4. Palabras claves mas comunes en las plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
11.5. Secuencias de Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
11.6. Uso de filtros con palabras claves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
11.6.1. Combinar filtros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
11.7. De plantillas a estilos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
11.7.1. Los ficheros de estilo mas sencillos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
11.7.2. Sintaxis de ficheros de estilo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
V
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 7/204
11.8. Ejemplos de ficheros de estilos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
11.8.1. Identificar equivocaciones en ficheros de estilo . . . . . . . . . . . . . . . . . . . . . . . . . 137
11.8.2. Identificar de forma unica un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
11.8.3. Mostrando salida parecida a Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
12. Administracion de cambios con Colas de Mercurial 140
12.1. El problema de la administracion de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14012.2. La prehistoria de las Colas de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
12.2.1. Trabajar parches con quilt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
12.2.2. Pasar de trabajo con parches con Quilt hacia Colas de Mercurial . . . . . . . . . . . . . . . . 141
12.3. La gran ventaja de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
12.4. Entender los parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
12.5. Comenzar a usar Colas de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.5.1. Crear un nuevo parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.5.2. Refrescar un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
12.5.3. Aplicar un parche tras otro y dar seguimiento . . . . . . . . . . . . . . . . . . . . . . . . . . 145
12.5.4. Manipular la pila de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
12.5.5. Introducir y sustraer muchos parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
12.5.6. Medidas de seguridad y como saltarlas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
12.5.7. Trabajar con varios parches a la vez . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14712.6. Mas acerca de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
12.6.1. La cantidad de franjas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
12.6.2. Estrategias para aplicar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
12.6.3. Algunos detalles de la representacion de parches . . . . . . . . . . . . . . . . . . . . . . . . 150
12.6.4. Cuidado con los difusos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
12.6.5. Manejo de descartes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
12.7. maximizar el rendimiento de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
12.8. Actualiar los parches cuando el codigo cambia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
12.9. Identificar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
12.10.Otra informacion util . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
12.11.Administrar parches en un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
12.11.1.Soporte de MQ para repositorios de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
12.11.2.Detalles a tener en cuenta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15512.12.Otras herramientas para trabajar con parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
12.13.Buenas practicas de trabajo con parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
12.14.Recetas de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
12.14.1.Administrar parches “triviales” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
12.14.2.Combinar parches completos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
12.14.3.Fusionar una porcion de un parche dentro de otro . . . . . . . . . . . . . . . . . . . . . . . . 158
12.15.Diferencias entre quilt y MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
13. Usos avanzados de las Colas de Mercurial 160
13.1. El problema de multiples objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
13.1.1. Aproximaciones tentadoras que no funcionan adecuadamente . . . . . . . . . . . . . . . . . 160
13.2. Aplicar parches condicionalmente mediante guardias . . . . . . . . . . . . . . . . . . . . . . . . . . 161
13.3. Controlar los guardias de un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16113.4. Selecccionar los guardias a usar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
13.5. Reglas de MQ para aplicar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
13.6. Podar el entorno de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
13.7. Dividir el fichero series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
13.8. Mantener la serie de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
13.8.1. El arte de escribir parches de backport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
VI
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 8/204
13.9. Consejos utiles para hacer desarrollo con MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
13.9.1. Organizar parches en directorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
13.9.2. Ver el historial de un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14. A ˜ nadir funcionalidad con extensiones 168
14.1. Mejorar el desempeno con la extension inotify . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
14.2. Soporte flexible de diff con la extension extdiff . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17014.2.1. Definicion de alias de comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
14.3. Uso de la extension transplant para seleccionar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
14.4. Enviar cambios vıa correo electronico con la extension patchbomb . . . . . . . . . . . . . . . . . . . 172
14.4.1. Cambiar el comportamiento de las bombas de parches . . . . . . . . . . . . . . . . . . . . . 173
A. Referencia de Ordenes 175
A.1. “hg add”—Anade ficheros en la proxima consignacion . . . . . . . . . . . . . . . . . . . . . . . . . 175
A.2. “hg diff”—imprime los cambios en el historial o el directorio actual . . . . . . . . . . . . . . . . . 175
A.2.1. Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
A.3. “hg version”—imprime la informacion de version y derechos de reproduccion . . . . . . . . . . . . 177
A.3.1. Consejos y trucos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
B. Referencia de las Colas de Mercurial 179
B.1. Referencia de ordenes MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
B.1.1. “hg qapplied”—imprimir los parches aplicados . . . . . . . . . . . . . . . . . . . . . . . . 179
B.1.2. “hg qcommit”—consignar cambios en la cola del repositorio . . . . . . . . . . . . . . . . . 179
B.1.3. “hg qdelete”—eliminar un parche del fichero series . . . . . . . . . . . . . . . . . . . . 179
B.1.4. “hg qdiff”—imprimir la diferencia del ultimo parche aplicado . . . . . . . . . . . . . . . . 179
B.1.5. “hg qfold”—fusionar (“integrar”) varios parches en uno solo . . . . . . . . . . . . . . . . . 179
B.1.6. “hg qheader”—desplegar el encabezado/descripcion de un parche . . . . . . . . . . . . . . 180
B.1.7. “hg qimport”—importar el parche de un tercero en la cola . . . . . . . . . . . . . . . . . . 180
B.1.8. “hg qinit”—preparar un repositorio para trabajar con MQ . . . . . . . . . . . . . . . . . . 180
B.1.9. “hg qnew”—crear un parche nuevo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
B.1.10. “hg qnext”—imprimir el nombre del proximo parche . . . . . . . . . . . . . . . . . . . . . 180
B.1.11. “hg qpop”—sustraer parches de la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
B.1.12. “hg qprev”—imprimir el nombre del parche anterior . . . . . . . . . . . . . . . . . . . . . 181B.1.13. “hg qpush”—introducir parches a la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
B.1.14. “hg qrefresh”—actualiza el ultimo parche aplicado . . . . . . . . . . . . . . . . . . . . . . 182
B.1.15. “hg qrename”—renombrar un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
B.1.16. “hg qrestore”—restaurar el estado almacenado de la cola . . . . . . . . . . . . . . . . . . 182
B.1.17. “hg qsave”—almacena el estado actual de la cola . . . . . . . . . . . . . . . . . . . . . . . 182
B.1.18. “hg qseries”—imprime la serie completa de parches . . . . . . . . . . . . . . . . . . . . . 182
B.1.19. “hg qtop”—imprime el nombre del parche actual . . . . . . . . . . . . . . . . . . . . . . . 183
B.1.20. “hg qunapplied”—imprimir los parches que aun no se han aplicado . . . . . . . . . . . . . 183
B.1.21. “hg strip”—remover una revision y sus descendientes . . . . . . . . . . . . . . . . . . . . 183
B.2. Referencia de ficheros de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
B.2.1. El fichero series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
B.2.2. El fichero status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
C. Instalar Mercurial desde las fuentes 184
C.1. En un sistema tipo Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
C.2. En Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
VI I
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 9/204
D. Licencia de Publicacion Abierta 185
D.1. Requerimientos en versiones modificadas y no modificadas . . . . . . . . . . . . . . . . . . . . . . . 185
D.2. Derechos de reproduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
D.3. Alcance de la licencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
D.4. Requerimientos sobre trabajos modificados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
D.5. Recomendaciones de buenas practicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
D.6. Opciones de licencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Bibliograf ıa 188
Indice alfabetico 188
VIII
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 10/204
Indice de figuras
2.1. Historial grafico del repositorio hello . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1. Historial reciente divergente de los repositorios my-hello y my-new-hello . . . . . . . . . . . . . . 27
3.2. Contenidos del repositorio despues de jalar my-hello a my-new-hello . . . . . . . . . . . . . . . . 28
3.3. Directorio de trabajo y repositorio durante la fusion, y consignacion consecuente . . . . . . . . . . . 29
3.4. Cambios con conflictos a un documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.5. Usando kdiff3 para fusionar versiones de un fichero . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.1. Relacion entre ficheros en el directorio de trabajo y ficheros de registro en el repositorio . . . . . . . . 374.2. Relaciones entre metadatos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.3. Instantanea de un revlog, con deltas incrementales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.5. El directorio de trabajo puede tener dos padres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.6. El directorio de trabajo obtiene nuevos padres luego de una consignacion . . . . . . . . . . . . . . . 46
4.7. El directorio de trabajo, actualizado a un conjunto de cambios anterior . . . . . . . . . . . . . . . . . 47
4.8. Despues de una consignacion hecha mientras se usaba un conjunto de cambios anterior . . . . . . . . 47
4.9. Fusion de dos frentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.1. Simular un directorio vacıo con un fichero oculto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.1. Ramas de Caracterısticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
9.1. Retroceso de un cambio con la orden “hg backout” . . . . . . . . . . . . . . . . . . . . . . . . . . 97
9.2. Retroceso automatizado de un cambio a algo que no es la punta con la orden “hg backout” . . . . . 98
9.3. Retroceso usando la orden “hg backout” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
9.4. Fusion manual de un retroceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
10.1. Un gancho simple que se ejecuta al hacer la consignaci on de un conjunto de cambios . . . . . . . . . 112
10.2. Definicion de un segundo gancho commit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
10.3. Uso del gancho pretxncommit para controlar consignaciones . . . . . . . . . . . . . . . . . . . . . 114
10.4. Un gancho que prohıbe mensajes de consignacion demasiado cortos . . . . . . . . . . . . . . . . . . 116
10.5. Un gancho simple que revisa si hay espacios en blanco finales . . . . . . . . . . . . . . . . . . . . . 116
10.6. Un mejor gancho para espacios en blanco finales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
11.1. Template keywords in use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
11.2. Filtros de plantilla en accion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
12.1. Uso sencillo de las ordenes diff y patch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
12.2. Lıneas a anadir en ˜/.hgrc para habilitar la extension MQ . . . . . . . . . . . . . . . . . . . . . . . 143
12.3. Como verificar que MQ esta habilitado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.4. Preparar un repositorio para usar MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
12.5. Crear un nuevo parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
IX
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 11/204
12.6. Refrescar un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
12.7. Refrescar un parche muchas veces para acumular cambios . . . . . . . . . . . . . . . . . . . . . . . 146
12.8. Aplicar un parche despues del primero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
12.9. Entender la pila de parches con “hg qseries” y “hg qapplied” . . . . . . . . . . . . . . . . . . . 148
12.10.Parches aplicados y no aplicados en la pila de parches de MQ . . . . . . . . . . . . . . . . . . . . . . 148
12.11.Modificar la pila de parches aplicados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
12.12.Pushing all unapplied patches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14912.13.Crear un parche a la fuerza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
12.14.Uso de las caracterısticas de etiquetamiento al trabajar con MQ . . . . . . . . . . . . . . . . . . . . . 154
12.15.Las ordenes diffstat, filterdiff, y lsdiff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
1
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 12/204
Prefacio
El control distribuido de revisiones es un territorio relativamente nuevo, y ha crecido hasta ahora gracias a a la
voluntad que tiene la gente de salir y explorar territorios desconocidos.
Estoy escribiendo este libro acerca de control de revisiones distribuido porque creo que es un tema importante
que merece una guıa de campo. Escogı escribir acerca de Mercurial porque es la herramienta mas facil para explorar
el terreno, y sin embargo escala a las demandas de retadores ambientes reales donde muchas otras herramientas de
control de revisiones fallan.
0.1. Este libro es un trabajo en progresoEstoy liberando este libro mientras lo sigo escribiendo, con la esperanza de que pueda ser util a otros. Tambien
espero que los lectores contribuiran como consideren adecuado.
0.2. Acerca de los ejemplos en este libro
Este libro toma un enfoque inusual hacia las muestras de codigo. Cada ejemplo esta “en directo”—cada uno es
realmente el resultado de un script de shell que ejecuta los comandos de Mercurial que usted ve. Cada vez que una
copia del libro es construida desde su codigo fuente, todos los scripts de ejemplo son ejecutados automaticamente, y
sus resultados actuales son comparados contra los resultados esperados.
La ventaja de este enfoque es que los ejemplos siempre son precisos; ellos describen exactamente el compor-
tamiento de la version de Mercurial que es mencionada en la portada del libro. Si yo actualizo la version de Mercurialque estoy documentando, y la salida de algun comando cambia, la construccion falla.
Hay una pequena desventaja de este enfoque, que las fechas y horas que usted vera en los ejemplos tienden a
estar “aplastadas” juntas de una forma que no serıa posible si los mismos comandos fueran escritos por un humano.
Donde un humano puede emitir no mas de un comando cada pocos segundos, con cualquier marca de tiempo resultante
correspondientemente separada, mis scripts automatizados de ejemplos ejecutan muchos comandos en un segundo.
Como un ejemplo de esto, varios commits consecutivos en un ejemplo pueden aparecer como habiendo ocurrido
durante el mismo segundo. Usted puede ver esto en el ejemplo bisect en la seccion 9.5, por ejemplo.
Ası que cuando usted lea los ejemplos, no le d e mucha importancia a las fechas o horas que vea en las salidas de
los comandos. Pero tenga confianza en que el comportamiento que esta viendo es consistente y reproducible.
0.3. Colof on—este libro es Libre
Este libro esta licenciado bajo la Licencia de Publicacion Abierta, y es producido en su totalidad usando herramien-
tas de Software Libre. Es compuesto con LATEX; las ilustraciones son dibujadas y generadas con Inkscape.
Elcodigo fuente completo para este libro es publicado como un repositorio Mercurial, en http://hg.serpentine .
com/mercurial/book .
2
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 13/204
Capıtulo 1
Introduccion
1.1. Acerca del control de revisiones
El control de revisiones es el proceso de administrar diferentes versiones de una pieza de informaci on. En su forma
mas simple es algo que la mayorıa de gente hace a mano: cada vez que usted modifica un fichero, lo graba con un
nuevo nombre que contiene un numero, cada uno mayor que el anterior.Administrar manualmente muchas versiones de incluso solo un fichero es una tarea propensa a errores, a pesar de
que hace bastante tiempo hay herramientas que ayudan en este proceso. Las primeras herramientas para automatizar
el control de revisiones fueron pensadas para que un usuario administrara un solo fichero. En las decadas pasadas, el
alcance de las herramientas de control de revisiones ha ido aumentando considerablemente; ahora manejan muchos
ficheros y facilitan el trabajo en conjunto de varias personas. Las mejores herramientas de control de revisiones de la
actualidad no tienen problema con miles de personas trabajando en proyectos que consisten de cientos de miles de
ficheros.
1.1.1. ¿Por que usar control de revisiones?
Hay muchas razones por las cuales usted o su equipo desearıa usar una herramienta automatica de control de
revisiones para un proyecto.
Llevar registro del historial y la evolucion de su proyecto, para evitar hacer la tarea manualmente. Por cada
cambio, tendra una bitacora de qui´ en lo hizo; por qu´ e se hizo; cu´ ando se hizo; y de qu´ e se trataba el cambio.
Cuando trabaja con mas personas, los programas de control de revisiones facilitan la colaboraci on. Por ejemplo,
cuando varias personas hacen cambios potencialmente incompatibles de forma casi simult anea, el programa le
ayudara a identificar y resolver tales conflictos.
Puede ayudarle a recuperarse de equivocaciones. Si aplica un cambio que posteriormente se evidencia como
un error, puede revertirlo a una version previa a uno o muchos ficheros. De hecho, una herramienta realmente
buena, incluso puede ayudarle efectivamente a darse cuenta exactamente cuando se introdujo el error (para mas
detalles ver la seccion 9.5).
Le ayudara a trabajar simultaneamente, y a manejar las diferencias entre multiples versiones de su proyecto.
La mayorıa de estas razones son igualmente validas —por lo menos en teorıa— ası este trabajando en un proyecto
solo usted, o con mucha gente.
Algo fundamental acerca de lo practico de un sistema de control de revisiones en estas dos escalas (“un hacker
solitario” y “un equipo gigantesco”) es como se comparan los beneficios con los costos. Una herramienta de control
de revisiones que sea dif ıcil de entender o usar impondra un costo alto.
3
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 14/204
Un proyecto de quinientas personas es muy propenso a colapsar solamente con su peso inmediatamente sin una
herramienta y un proceso de control de versiones. En este caso, el costo de usar control de revisiones ni siquiera se
tiene en cuenta, puesto que sin el, el fracaso esta casi garantizado.
Por otra parte, un “arreglo rapido” de una sola persona, excluirıa la necesidad de usar una herramienta de control
de revisiones, porque casi seguramente, el costo de usar una estarıa cerca del costo del proyecto. ¿No es ası?
Mercurial soporta ambas escalas de de desarrollo de manera unica. Puede aprender lo basico en pocos minutos, y
dado su bajo sobrecosto, puede aplicar el control de revisiones al proyecto mas pequeno con facilidad. Su simplicidadsignifica que no tendra que preocuparse por conceptos obtusos o secuencias de ordenes compitiendo por espacio
mental con lo que sea que realmente este tratando de hacer. Al mismo tiempo, Mercurial tiene alto desempeno y su
naturaleza peer-to-peer le permite escalar indoloramente para manejar grandes proyectos.
Ninguna herramienta de control de revisiones puede salvar un proyecto mal administrado, pero la elecci on de
herramientas puede hacer una gran diferencia en la fluidez con la cual usted puede trabajar en un proyecto.
1.1.2. La cantidad de nombres del control de revisiones
El control de revisiones es un campo amplio, tan amplio que no hay un acronimo o nombre unico. A continuacion
presentamos un listado de nombres comunes y acronimos que se podrıan encontrar:
Control de revisiones (RCS)
Manejo de Configuraciones de Programas (SCM), o administracon de configuraciones
Administracion de codigo fuente
Control de Codigo Fuente, o Control de Fuentes
Control de Versiones (VCS)
Algunas personas aducen que estos terminos tienen significados diversos, pero en la practica se sobreponen tanto que
no hay una forma acordada o incluso adecuada de separarlos.
1.2. Historia resumida del control de revisiones
La herramienta de control de revisiones mas antigua conocida es SCCS (Sistema de Control de Codigo), escrito
por Marc Rochkind en Bell Labs, a comienzos de los setentas (1970s). SCCS operaba sobre ficheros individuales, y
requerıa que cada persona que trabajara en el proyecto tuviera acceso a un espacio compartido en un solo sistema.
Solamente una persona podıa modificar un fichero en un momento dado; el arbitramiento del acceso a los ficheros
se hacıa con candados. Era comun que la gente pusiera los candados a los ficheros, y que posteriormente olvidara
quitarlos, impidiendo que otro pudiera modificar los ficheros en cuesti on sin la intervencion del administrador.
Walter Tichy desarrollo una alternativa gratuita a SCCS a comienzos de los ochentas (1980s); llamo a su programa
RCS (Sistema de Control de Revisiones). Al igual que SCCS, RCS requerıa que los desarrolladores trabajaran en
un unico espacio compartido y colocaran candados a los ficheros para evitar que varias personas los modificaran
simultaneamente.
Despues en los ochenta, Dick Grune uso RCS como un bloque de construccion para un conjunto de guiones de
lınea de comando, que inicialmente llamo cmt, pero que renombro a CVS (Sistema Concurrente de Versiones). La
gran innovacion de CVS era que permitıa a los desarrolladores trabajar simultaneamente de una forma mas o menos
independiente en sus propios espacios de trabajo. Los espacios de trabajo personales impedıan que los desarrolladoresse pisaran las mangueras todo el tiempo, situacion comun con SCCS y RCS. Cada desarrollador tenıa una copia de
todos los ficheros del proyecto y podıa modificar sus copias independientemente, Tenıan que fusionar sus ediciones
antes de consignar los cambios al repositorio central.
Brian Berliner tomo los scripts originales de Grune y los reescribio en C, publicando en 1989 el codigo sobre el
cual se ha desarrollado la version moderna de CVS. CVS adquirio posteriormente la habilidad de operar sobre una
conexion de red, dotandolo de una arquitectura, cliente/servidor. La arquitectura de CVS es centralizada; el historial
del proyecto esta unicamente en el repositorio central. Los espacios de trabajo de los clientes contienen unicamente
4
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 15/204
copias recientes de las versiones de los ficheros, y pocos metadatos para indicar donde esta el servidor. CVS ha tenido
un exito enorme; Es probablemente el sistema de control de revisiones mas extendido del planeta.
A comienzos de los noventa (1990s), Sun MicroSystems desarrollo un temprano sistema distribuido de control
de revisiones llamado TeamWare. Un espacio de trabajo TeamWare contiene una copia completa del historial del
proyecto. TeamWare no tiene la nocion de repositorio central. (CVS se basaba en RCS para el almacenamiento de su
historial; TeamWare usaba SCCS.)
A medida que avanzaba la decada de los noventa, se empezo a evidenciar los problemas de CVS. Almacenacambios simultaneos a muchos ficheros de forma individual, en lugar de agruparlos como una operacion unica y
atomica logicamente. No maneja bien su jerarquıa de ficheros; es f acil desordenar un repositorio al renombrar ficheros
y directorios. Peor aun, su codigo fuente es difıcil de leer y mantener, lo que hizo que su “umbral de dolor” para
arreglar sus problemas arquitecturales fuera algo prohibitivo.
En 2001, Jim Blandy y Karl Fogel, dos desarrolladores que hab ıan trabajado en CVS, comenzaron un proyecto
para reemplazarlo con una herramienta con mejor arquitectura y codigo mas limpio. El resultado, Subversion, no
se separo del modelo centralizado cliente/servidor de CVS, pero anadio consignaciones atomicas de varios ficheros,
mejor manejo de espacios de nombres , y otras caracterısticas que lo hacen mejor que CVS. Desde su version inicial,
ha ido creciendo en popularidad rapidamente.
Mas o menos en forma simultanea Graydon Hoare comenzo a trabajar en un ambicioso sistema distribuido de
control de versiones que llamo Monotone. Mientras que Monotone se enfocaba a evitar algunas fallas de dise no de
CVS con una arquitectura peer-to-peer, fue mucho mas alla de las herramientas anteriores (y posteriores) de control de
revisiones en varios aspectos innovadores. Usa hashes criptograficos como identificadores, y tiene una nocion integralde “confianza” para codigo de diversas fuentes.
Mercurial nacio en el 2005. Algunos de sus aspectos de de diseno fueron influenciados por Monotone, pero Mer-
curial se enfoca en la facilidad de uso, gran rendimiento y escalabilidad para proyectos muy grandes.
1.3. Tendencias en el control de revisiones
Ha habido una tendencia inconfundible en el desarrollo y uso de las herramientas de control de revisiones en las
cuatro decadas pasadas, mientras la gente se ha hecho familiar con las capacidades de sus herramientas y se ha visto
restringida por sus limitaciones.
La primera generacion comenzo administrando ficheros individuales en computadores por persona. A pesar de que
tales herramientas representaron un avance importante frente al control de revisiones manual, su modelo de candados
y la dependencia a un solo computador los limito a equipos de trabajo pequenos y acoplados.La segunda generacion dejo atras esas limitaciones moviendose a arquitecturas centradas en redes, y administrando
proyectos completos a la vez. A medida que los proyectos crecıan, nacieron nuevos problemas. Con la necesidad de
comunicacion frecuente con los servidores, escalar estas maquinas se convirtio en un problema en proyectos realmente
grandes. Las redes con poca estabilidad podrıan impedir que usuarios remotos se conectaran al servidor. A medida que
los proyectos de codigo abierto comenzaron a ofrecer acceso de solo lectura de forma anonima a cualquiera, la gente
sin permiso para consignar vio que no podıan usar tales herramientas para interactuar en un proyecto de forma natural,
puesto que no podıan guardar sus cambios.
La generacion actual de herramientas de control de revisiones es peer-to-peer por naturaleza. Todos estos sistemas
han eliminado la dependencia de un unico servidor central, y han permitido que la gente distribuya sus datos de control
de revisiones donde realmente se necesita. La colaboracion a traves de Internet ha cambiado las limitantes tecnologicas
por la cuestion de eleccion y consenso. Las herramientas modernas pueden operar sin conexi on indefinidamente y
autonomamente, necesitando una conexion de red solamente para sincronizar los cambios con otro repositorio.
1.4. Algunas ventajas del control distribuido de revisiones
A pesar de que las herramientas para el control distribuido de revisiones lleva varios anos siendo tan robustas y
usables como la generacion previa de sus contrapartes, algunas personas que usan las herramientas mas antiguas no
se han percatado de sus ventajas. Hay gran cantidad de situaciones en las cuales las herramientas distribuidas brillan
frente a las centralizadas.
5
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 16/204
Para un desarrollador individual, las herramientas distribuidas casi siempre son mas rapidas que las centralizadas.
Por una razon sencilla: Una herramienta centralizada necesita comunicarse por red para las operaciones m as usuales,
debido a que los metadatos se almacenan en una sola copia en el servidor central. Una herramienta distribuida almacena
todos sus metadatos localmente. Con todo lo demas de la misma forma, comunicarse por red tiene un sobrecosto en
una herramienta centralizada. No subestime el valor de una herramienta de respuesta rapida: Usted empleara mucho
tiempo interactuando con su programa de control de revisiones.
Las herramientas distribuidas son indiferentes a los caprichos de su infraestructura de servidores, de nuevo, debidoa la replicacion de metadatos en tantos lugares. Si usa un sistema centralizado y su servidor explota, ojala los medios
f ısicos de su copia de seguridad sean confiables, y que su ultima copia sea reciente y ademas funcione. Con una
herramienta distribuida tiene tantas copias de seguridad disponibles como computadores de contribuidores.
La confiabilidad de su red afectara las herramientas distribuidas de una forma mucho menor que a las herramientas
centralizadas. Usted no puede siquiera usar una herramienta centralizada sin conexion de red, excepto por algunas
ordenes muy limitadas. Con herramientas distribuidas, si sus conexion cae mientras usted esta trabajando, podrıa
nisiquiera darse cuenta. Lo unico que que no podra hacer es comunicarse con repositorios en otros computadores, algo
que es relativamente raro comparado con las operaciones locales. Si tiene colaboradores remotos en su equipo, puede
ser importante.
1.4.1. Ventajas para proyectos de codigo abierto
Si descubre un proyecto de codigo abierto y decide que desea comenzar a trabajar en el, y ese proyecto usa unaherramienta de control distribuido de revisiones, usted es de inmediato un par con la gente que se considera el “alma”
del proyecto. Si ellos publican sus repositorios, usted puede copiar inmediatamente el historial del proyecto, hacer
cambios y guardar su trabajo, usando las mismas herramientas de la misma forma que ellos. En contraste, con una
herramienta centralizada, usted debe usar el programa en un modo “s olo lectura” a menos que alguien le otorgue
permisos para consignar cambios en el repositorio central. Hasta entonces, no podra almacenar sus cambios y sus
modificaciones locales correran el riesgo de danarse cuando trate de actualizar su vista del repositorio.
Las bifurcaciones (forks) no son un problema
Se ha mencionado que las herramientas de control distribuido de versiones albergan un riesgo a los proyectos
de codigo abierto, puesto que se vuelve muy sencillo hacer una “bifurcacion”1 del desarrollo del proyecto. Una bi-
furcacion sucede cuando hay diferencias de opinion o actitud entre grupos de desarrolladores que desemboca en la
decision de la imposibilidad de continuar trabajando juntos. Cada parte toma una copia m as o menos completa delcodigo fuente del proyecto y toma su propio rumbo.
En algunas ocasiones los lıderes de las bifurcaciones reconcilian sus diferencias. Con un sistema centralizado de
control de revisiones, el proceso t´ ecnico de reconciliarse es doloroso, y se hace de forma muy manual. Usted tiene que
decidir que historial de revisiones va a “ganar”, e injertar los cambios del otro equipo en el arbol de alguna manera.
Con esto usualmente se pierde algo o todo del historial de la revision de alguna de las partes.
Lo que las herramientas distribuidas hacen con respecto a las bifurcaciones, es que las bifurcaciones son la ´ unica
forma de desarrollar un proyecto. Cada cambio que usted hace es potencialmente un punto de bifurcaci on. La gran
fortaleza de esta aproximacion es que las herramientas distribuidas de control de revisiones tiene que ser bueno al
fusionar las bifurcaciones, porque las bifurcaciones son absolutamente fundamentales: pasan todo el tiempo.
Si todas las porciones de trabajo que todos hacen, todo el tiempo, se enmarcan en terminos de bifurcaciones
y fusiones, entonces a aquello a lo que se refiere en el mundo del codigo abierto a una “bifurcacion” se convierte
puramente en una cuestion social. Lo que hacen las herramientas distribuidas es disminuir la posibilidad de una
bifurcacion porque:
Eliminan la distincion social que imponen las herramientas centralizadas: aquella entre miembros (personas con
permiso de consignar) y forasteros (los que no tienen el permiso).
Facilitan la reconciliacion despues de una bifurcacion social, porque todo lo que concierne al programa de
control de revisiones es una fusion.
1N. del T. fork.
6
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 17/204
Algunas personas se resisten a las herramientas distribuidas porque desean mantener control completo sobre sus
proyectos, y creen que las herramientas centralizadas les dan tal control. En todo caso, si este es su parecer, y usted
publica sus repositorios de CVS o Subversion, hay muchas herramientas disponibles que pueden obtener el historial
completo (aunque sea lentamente) y recrearlo en otro sitio que usted no controla. Siendo ası un control ilusorio, puesto
que esta impidiendo la fluidez de colaboracion en lugar de prevenir que alguien se sienta impulsado a obtener una
copia y hacer una bifurcacion con su historial.
1.4.2. Ventajas para proyectos comerciales
Muchos proyectos comerciales tienen grupos de trabajo distribuidos alrededor del globo. Quienes contribuyen y
estan lejos de un repositorio central veran una ejecucion mas lenta de los comandos y tal vez menos confiabilidad.
Los sistemas de control de revision comerciales intentan amortiguar estos problemas con adiciones de replicacion
remota que usualmente son muy costosos y complicados de administrar. Un sistema distribuido no padece estos prob-
lemas. Mejor aun, puede colocar varios servidores autorizados, por ejemplo, uno por sitio, de tal forma que no haya
comunicacion redundante entre repositorios sobre enlaces de conexion costosos.
Los sistemas de control de revisiones distribuidos tienden a ser poco escalables. No es inusual que costosos sis-
temas centralizados caigan ante la carga combinada de unas cuantas docenas de usuarios concurrentes. De nuevo, las
respuestas tıpicas de replicacion tienden a ser costosas y complejas de instalar y administrar. Dado que la carga en
un servidor central—si es que tiene uno—es muchas veces menor con una herramienta distribuida (debido a que los
datos estan replicados en todas partes), un solo servidor economico puede tratar las necesidades de equipos muchomas grandes, y la replicacion para balancear la carga se vuelve cosa de guiones.
Si tiene un empleado en el campo, se beneficiara grandemente de un sistema distribuido de control de versiones
al resolver problemas en el sitio del cliente. La herramienta le permitir a generar construcciones a la medida, probar
diferentes arreglos de forma independiente y buscar de forma eficiente las fuentes de fallos en el historial y regresiones
en los ambientes de los clientes, todo sin necesidad de conectarse al servidor de su companıa.
1.5. ¿Por que elegir Mercurial?
Mercurial cuenta con un conjunto unico de propiedades que lo hacen una eleccion particularmente buena como
sistema de control de revisiones, puesto que:
Es f acil de aprender y usar.
Es liviano.
Escala de forma excelente.
Es f acil de acondicionar.
Si los sistemas de control de revisiones le son familiares, deberıa estar listo para usar Mercurial en menos de cinco
minutos. Si no, solo va a tomar unos pocos minutos mas. Las ordenes de Mercurial y su conjunto de caracterısticas
son uniformes y consistentes generalmente, y basta con que siga unas pocas reglas generales en lugar de un monton
de excepciones.
En un proyecto pequeno, usted puede comenzar a trabajar con Mercurial en pocos momentos. Crear nuevos cam-
bios y ramas, transferir cambios (localmente o por la red); y las operaciones relacionadas con el estado y el historial
son rapidas. Mercurial buscar ser ligero y no incomodar en su camino combinando poca sobrecarga cognitiva con
operaciones asombrosamente rapidas.
La utilidad de Mercurial no se limita a proyectos pequenos: esta siendo usado por proyectos con centenas de miles
de contribuyentes, cada uno conteniendo decenas de miles de ficheros y centenas de megabytes de codigo fuente
Si la funcionalidad basica de Mercurial no es suficiente para usted, es muy facil extenderlo. Mercurial se comporta
muy bien con tareas de scripting y su limpieza interna junto con su implementacion en Python permiten anadir carac-
terısticas f acilmente en forma de extensiones. Hay un buen numero de extensiones utiles y populares en este momento,
desde ayudar a identificar fallos hasta mejorar su desempeno.
7
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 18/204
1.6. Comparacion de Mercurial con otras herramientas
Antes de leer, por favor tenga en cuenta que esta seccion necesariamente refleja mis propias experiencias, intereses
y (tengo que decirlo) mis preferencias. He usado cada una de las herramientas de control de versiones listadas a
continuacion, y en muchos casos por varios anos.
1.6.1. Subversion
Subversion es una herramienta de control de revisiones muy popular, desarrollada para reemplazar a CVS. Tiene
una arquitectura centralizada tipo cliente/servidor.
Subversion y Mercurial tienen comandos con nombres similares para hacer las mismas operaciones, por lo que si
le son familiares en una, sera sencillo aprender a usar la otra. Ambas herramientas son portables en todos los sistemas
operativos populares.
Antes de la version 1.5, Subversion no tenıa soporte para fusiones. En el momento de la escritura, sus capcidades
para llevar cuenta de las funciones son nuevas, complicadas y poco estables2.
Mercurial tiene una ventaja considerable en desempeno sobre Subversion en cualquier operacion de control de
revisiones que yo haya medido. He medido sus ventajas con factores desde dos hasta seis veces comparando con al-
macenamiento de ficheros ra local Subversion 1.4.3, el cual es el metodo de acceso mas rapido. En los escenarios
mas realistas incluyendo almacenamiento con la red de por medio, Subversion se encuentra en desventaja aun mayor.
Dado que casi todas las ordenes de Subversion deben tratar con el servidor y Subversion no tiene utilidades de repli-cacion adecuadas, la capacidad del servidor y el ancho de banda se convierten en cuellos de botella para proyectos
modestamente grandes.
Adicionalmente, Subversion tiene un sobrecosto considerable en almacenamiento para evitar transacciones por
red en algunas operaciones, tales como encontrar ficheros modificados (status) y desplegar informacion frente a la
revision actual (diff). Como resultado, la copia de trabajo de Subversion termina siendo del mismo tamano o mas
grande que un repositorio de Mercurial y el directorio de trabajo, a pesar de que el repositorio de Mercurial contiene
el historial completo del proyecto.
Subversion tiene soporte amplio de otras herramientas. Mercurial por ahora est a bastante atras en este aspecto.
Esta diferencia esta disminuyendo, y algunas de las herramientas GUI3, eclipsan sus equivalentes de Subversion. Al
igual que Mercurial, Subversion tiene un excelente manual de usuario.
Dado que Subversion no almacena el historial de revisiones en el cliente, es muy bueno para administrar proyectos
que tienen muchos ficheros binarios grandes y opacos. Si consigna cincuenta revisiones de un fichero de 10MB que
no es comprimible, el esapacio en el cliente de Subversion se mantendr a constante mientras que el espacio usadopor cualquier Sistema Distribuido de Control de Revisiones crecera rapidamente en proporcion con el numero de
revisiones, debido a que las diferencias entre cada revision es grande.
Adicionalmente, generalmente es dif ıcil o mas bien, imposible mezclar diferentes versiones de un fichero binario.
La habilidad de Subversion para permitirle al usuario poner una cerradura a un fichero, de modo que tenga un permiso
exclusivo para consignar cambios, puede ser una ventaja significativa en un proyecto donde los ficheros binarios sean
usados ampliamente.
Mercurial puede importar el historial de revisiones de un repositorio de Subversion. Tambien puede exportar el
historial de revisiones a un repositorio de Subversion. De esta forma es sencillo “dar un vistazo” y usar Mercurial
y Subversion en paralelo antes de decidirse a dar el paso. La conversion del historial es incremental, de modo que
puede aplicar una conversion inicial, y despues conversiones pequenas y adicionales posteriormente para traer nuevos
cambios.
1.6.2. Git
Git es una herramienta distribuida de control de revisiones desarrollada para administrar el arbol del kernel de
Linux. Al igual que Mercurial los principios de su diseno fueron influenciados por Monotone.
2N. del T. buggy3N. del T. Interfaz de Usuario Grafica
8
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 19/204
Git tiene un conjunto de ordenes muy grande; en la version 1.5.0 ofrece 139 ordenes individuales. Tiene cierta
reputacion de ser dif ıcil de aprender. Comparado con Git, Mercurial tiene un fuerte enfoque hacia la facilidad.
En terminos de rendimiento, Git es extremadamente rapido. En muchos casos, es mas rapido que Mercurial, por lo
menos en Linux, mientras que Mercurial se comporta mejor en otras operaciones. De todas maneras en Windows, el
desempeno y el nivel general de soporte que ofrece Git, al momento de la escritura, est a bastante atras de Mercurial.
Mientras que el repositorio de Mercurial no requiere mantenimiento, el repositorio de Git requiere frecuentes
“reempaquetados” de sus metadatos. Sin estos, el desempeno se degrada y el uso de espacio crece rapidamente. Unservidor que contenga repositorios de Git que no sean reempacados rigurosa y frecuentemente requerir a trabajo in-
tenso de disco durante las copias de seguridad, y ha habido situaciones en copias de seguridad diaria que toman m as
de 24 horas como resultado. Un repositorio recien reempacado de Git es un poco mas pequeno que un repositorio de
Mercurial, pero un repositorio sin reempacar es varios ordenes de magnitud mas grande.
El corazon de Git esta escrito en C. Muchas ordenes de Git estan implementadas como guiones de lınea de co-
mandos o de Perl y la calidad de esos guiones varıa ampliamente. He encontrado muchas situaciones en las cuales los
guiones no tuvieron en cuenta la presencia de errores que podrıan haber sido fatales.
Mercurial puede importar el historial de revisiones de un repositorio de Git.
1.6.3. CVS
CVS es probablemente la herramienta de control de revisiones mas ampliamente usada en el planeta. Debido a su
edad y su poca pulcritud interna, ha sido ligeramente mantenida en muchos anos.Tiene una arquitectura centralizada cliente/servidor. No agrupa cambios relacionados en consignaciones atomicas,
pemitiendo que con facilidad la gente “rompa la construccion”: una persona puede consignar exitosamente parte del
cambio y estar bloqueada por la necesidad de una mezcla, forzando a otras personas a ver solamente una porci on del
trabajo que estaban buscando hacer. Esto afecta tambien la forma como usted trabaja con el historial del proyecto. Si
quiere ver todas las modificaciones que alguien hizo como parte de una tarea, necesitara inspeccionar manualmente
las descripciones y las marcas de tiempo de cambio de cada fichero involucrado (esto, si usted saber cuales eran tales
ficheros).
CVS tiene una nocion confusa de etiquetas y ramas que yo no tratar ıa incluso de describir. No soporta renom-
bramiento de ficheros o directorios adecuadamente, facilitando el corromper un repositorio. Casi no tiene chequeo
de consistencia interna, por lo tanto es casi imposible identificar por que o c omo se corrompio un repositorio. Yo no
recomendarıa un repositorio de CVS para proyecto alguno, ni existente ni nuevo.
Mercurial puede importar el historial de revisiones de CVS. De todas maneras hay ciertas precauciones que apli-
can; las cuales tambien son necesarias para cualquier herramienta importadora de historial de CVS. Debido a la faltade atomicidad de cambios y el no versionamiento de la jerarqu ıa del sistema de ficheros, es imposible reconstruir
completamente el historial de CVS con precision; hay cierto trabajo de conjetura involucrado y los renombramientos
tampoco se mostraran. Debido a que gran parte de la administracion avanzada de CVS tiene que hacerse manualmente
y por lo tanto es proclive al error, es comun que los importadores de CVS encuentren muchos problemas con reposi-
torios corruptos (marcas de tiempo totalmente desubicadas y ficheros que han permanecido con candados por m as de
una decada son dos de los problemas menos interesantes de los que puedo retomar de mi experiencia personal).
Mercurial puede importar el historial de revisiones de un repositorio CVS.
1.6.4. Herramientas comerciales
Perforce tiene una arquitectura centralizada cliente/servidor sin almacenamiento de dato alguno de cache en el
lado del cliente. A diferencia de las herramientas modernas de control de revisiones, Perforce requiere que un usuario
ejecute un comando para informar al servidor acerca de todo fichero que se vaya a editar.
El rendimiento de Perforce es muy bueno para equipos pequenos, pero se degrada rapidamente cuando el numero
de usuarios va mas alla de pocas docenas. Instalaciones modestamente grandes de Perforce requiere la organizaci on
de proxies para soportar la carga que sus usuarios generan.
9
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 20/204
1.6.5. Elegir una herramienta de control de revisiones
Con la excepcion de CVS, toda las herramientas que se han listado anteriormente tienen fortalezas unicas que las
hacen valiosas de acuerdo al tipo de trabajo. No hay una unica herramienta de control de revisiones que sea la mejor
en todas las situaciones.
Por ejemplo, Subversion es una buena eleccion para trabajar con edicion frecuente de ficheros binarios, debido a
su naturaleza centralizada y soporte para poner candados a ficheros.
Personalmente encuentro las propiedades de simplicidad, desempeno, y buen soporte de fusiones de Mercurial una
combinacion llamativa que ha dado buenos frutos por varios anos.
1.7. Migrar de otra herramienta hacia Mercurial
Mercurial viene con una extension llamada convert, que puede importar historiales de revisiones de forma incre-
mental desde varias herramientas de control de revisiones. Por “incremental”, quiero decir que puede migrar toda el
historial de un proyecto en una primera instancia y despues volver a ejecutar la migracion posteriormente para obtener
los nuevos cambios que han sucedido despues de la migracion inicial.
A continuacion presentamos las herramientas de revisiones que soporta el comando convert:
Subversion
CVS
Git
Darcs
Adicionalmente, convert puede exportar cambios de Mercurial hacia Subversion. Lo que hace posible probar
Subversion y Mercurial en paralelo antes de lanzarse a un migraci on total, sin arriesgarse a perder trabajo alguno.
El comando “hg convert” es sencillo de usar. Basta con apuntarlo hacia la ruta o el URL del repositorio fuente,
opcionalmente darle el nombre del nombre del repositorio destino y comenzara a hacer su trabajo. Despues de la
conversion inicial, basta con invocar de nuevo el comando para importar cambios nuevos.
10
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 21/204
Capıtulo 2
Una gira de Mercurial: lo basico
2.1. Instalar Mercurial en su sistema
Hay paquetes binarios precompilados de Mercurial disponibles para cada sistema operativo popular. Esto hace
f acil empezar a usar Mercurial en su computador inmediatamente.
2.1.1. Linux
Dado que cada distribucion de Linux tiene sus propias herramientas de manejo de paquetes, polıticas, y ritmos
de desarrollo, es dif ıcil dar un conjunto exhaustivo de instrucciones sobre como instalar el paquete de Mercurial. La
version de Mercurial que usted tenga a disposicion puede variar dependiendo de que tan activa sea la persona que
mantiene el paquete para su distribucion.
Para mantener las cosas simples, me enfocare en instalar Mercurial desde la lınea de comandos en las distribuciones
de Linux mas populares. La mayorıa de estas distribuciones proveen administradores de paquetes graficos que le
permitiran instalar Mercurial con un solo clic; el nombre de paquete a buscar es mercurial.
Debian1 apt-get install mercurial
Fedora Core1 yum install mercurial
Gentoo1 emerge mercurial
OpenSUSE1 yum install mercurial
Ubuntu El paquete de Mercurial de Ubuntu esta basado en el de Debian. Para instalarlo, ejecute el siguiente comando.
1 apt-get install mercurial
El paquete de Mercurial para Ubuntu tiende a atrasarse con respecto a la version de Debian por un margen de
tiempo considerable (al momento de escribir esto, 7 meses), lo que en algunos casos significar a que usted puedeencontrarse con problemas que ya habran sido resueltos en el paquete de Debian.
2.1.2. Solaris
SunFreeWare, en http://www.sunfreeware.com , es una buena fuente para un gran numero de paquetes compi-
lados para Solaris para las arquitecturas Intel y Sparc de 32 y 64 bits, incluyendo versiones actuales de Mercurial.
11
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 22/204
2.1.3. Mac OS X
Lee Cantey publica un instalador de Mercurial para Mac OS X en http://mercurial.berkwood.com . Este
paquete funciona en tanto en Macs basados en Intel como basados en PowerPC. Antes de que pueda usarlo, usted
debe instalar una version compatible de Universal MacPython [BI]. Esto es f acil de hacer; simplemente siga las
instrucciones del sitio de Lee.
Tambien es posible instalar Mercurial usando Fink o MacPorts, dos administradores de paquetes gratuitos y pop-
ulares para Mac OS X. Si usted tiene Fink, use sudo apt-get install mercurial-py25. Si usa MacPorts, sudo
port install mercurial.
2.1.4. Windows
Lee Cantey publica un instalador de Mercurial para Windows en http://mercurial.berkwood.com . Este pa-
quete no tiene dependencias externas; “simplemente funciona”.
Nota: La version de Windows de Mercurial no convierte automaticamente los fines
de lınea entre estilos Windows y Unix. Si usted desea compartir trabajo con usuar-
ios de Unix, debera hacer un trabajo adicional de configuracion. XXX Terminar
esto.
2.2. Arrancando
Para empezar, usaremos el comando “hg version” para revisar si Mercurial esta instalado adecuadamente. La
informacion de la version que es impresa no es tan importante; lo que nos importa es si imprime algo en absoluto.
1 $ hg version
2 Mercurial Distributed SCM (version 1.0.1)
3
4 Copyright (C) 2005-2008 Matt Mackall <[email protected]> and others
5 This is free software; see the source for copying conditions. There is NO
6 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2.2.1. Ayuda integrada
Mercurial provee un sistema de ayuda integrada. Esto es invaluable para esas ocasiones en la que usted esta atorado
tratando de recordar como ejecutar un comando. Si esta completamente atorado, simplemente ejecute “hg help”; esto
imprimira una breve lista de comandos, junto con una descripci on de que hace cada uno. Si usted solicita ayuda sobre
un comando especıfico (como abajo), se imprime informacion mas detallada.
1 $ hg help init
2 hg init [-e CMD] [--remotecmd CMD] [DEST]
3
4 create a new repository in the given directory
5
6 Initialize a new repository in the given directory. If the given
7 directory does not exist, it is created.8
9 If no directory is given, the current directory is used.
10
11 It is possible to specify an ssh:// URL as the destination.
12 Look at the help text for the pull command for important details
13 about ssh:// URLs.
14
12
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 23/204
15 options:
16
17 -e --ssh specify ssh command to use
18 --remotecmd specify hg command to run on the remote side
19
20 use "hg -v help init" to show global options
Para un nivel mas impresionante de detalle (que usted no va a necesitar usualmente) ejecute “hg help -v”. La opcion
-v es la abreviacion para --verbose, y le indica a Mercurial que imprima mas informacion de lo que harıa usualmente.
2.3. Trabajar con un repositorio
En Mercurial, todo sucede dentro de un repositorio. El repositorio para un proyecto contiene todos los ficheros que
“pertenecen a” ese proyecto, junto con un registro historico de los ficheros de ese proyecto.
No hay nada particularmente magico acerca de un repositorio; es simplemente un arbol de directorios en su sistema
de ficheros que Mercurial trata como especial. Usted puede renombrar o borrar un repositorio en el momento que lo
desee, usando bien sea la lınea de comandos o su explorador de ficheros.
2.3.1. Hacer una copia local de un repositorio
Copiar un repositorio es solo ligeramente especial. Aunque usted podrıa usar un programa normal de copia de
ficheros para hacer una copia del repositorio, es mejor usar el comando integrado que Mercurial ofrece. Este comando
se llama “hg clone”1, porque crea una copia identica de un repositorio existente.
1 $ hg clone http://hg.serpentine.com/tutorial/hello
2 destination directory: hello
3 requesting all changes
4 adding changesets
5 adding manifests
6 adding file changes
7 added 5 changesets with 5 changes to 2 files
8 updating working directory9 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
Si nuestro clonado tiene exito, deberıamos tener un directorio local llamado hello. Este directorio contendra algunos
ficheros.
1 $ ls -l
2 total 0
3 drwxr-xr-x 3 jerojasro jerojasro 120 Feb 10 18:23 hello
4 $ ls hello
5 Makefile hello.c
Estos ficheros tienen el mismo contenido e historial en nuestro repositorio y en el repositorio que clonamos.
Cada repositorio Mercurial esta completo, es autocontenido e independiente. Contiene su propia copia de los
ficheros y el historial de un proyecto. Un repositorio clonado recuerda la ubicaci on de la que fue clonado, pero no se
comunica con ese repositorio, ni con ningun otro, a menos que usted le indique que lo haga.
Lo que esto significa por ahora es que somos libres de experimentar con nuestro repositorio, con la tranquilidad de
saber que es una “caja de arena” privada que no afectara a nadie mas.
1N. del T. Del termino “clonar” en ingles.
13
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 24/204
2.3.2. Que hay en un repositorio?
Cuando miramos en detalle dentro de un repositorio, podemos ver que contiene un directorio llamado .hg. Aquı es
donde Mercurial mantiene todos los metadatos del repositorio.
1 $ cd hello
2 $ ls -a
3 . .. .hg Makefile hello.c
Los contenidos del directorio .hg y sus subdirectorios son exclusivos de Mercurial. Usted es libre de hacer lo que
desee con cualquier otro fichero o directorio en el repositorio.
Para introducir algo de terminologıa, el directorio .hg es el repositorio “real”, y todos los ficheros y directorios que
coexisten con el estan en el directorio de trabajo. Una forma sencilla de recordar esta distincion es que el repositorio
contiene el historial de su proyecto, mientras que el directorio de trabajo contiene una instant anea de su proyecto en
un punto particular del historial.
2.4. Vistazo rapido al historial
Una de las primeras cosas que se desea hacer con un repositorio nuevo, poco conocido, es conocer su historial. El
comando “hg log” nos permite ver el mismo.
1 $ hg log
2 changeset: 4:2278160e78d4
3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Sat Aug 16 22:16:53 2008 +0200
6 summary: Trim comments.
7
8 changeset: 3:0272e0d5a517
9 user: Bryan O’Sullivan <[email protected]>
10 date: Sat Aug 16 22:08:02 2008 +0200
11 summary: Get make to generate the final binary from a .o file.
12
13 changeset: 2:fef857204a0c
14 user: Bryan O’Sullivan <[email protected]>
15 date: Sat Aug 16 22:05:04 2008 +0200
16 summary: Introduce a typo into hello.c.
17
18 changeset: 1:82e55d328c8c
19 user: [email protected]
20 date: Fri Aug 26 01:21:28 2005 -0700
21 summary: Create a makefile
22
23 changeset: 0:0a04b987be5a
24 user: [email protected]
25 date: Fri Aug 26 01:20:50 2005 -0700
26 summary: Create a standard "hello, world" program
27
Por defecto este programa imprime un parrafo breve por cada cambio al proyecto que haya sido grabado. Dentro de
la terminologıa de Mercurial, cada uno de estos eventos es llamado conjunto de cambios, porque pueden contener un
registro de cambios a varios ficheros.
14
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 25/204
Los campos de la salida de “hg log” son los siguientes.
changeset2 Este campo tiene un numero, seguido por un :, seguido por una cadena hexadecimal. Ambos son identificadores
para el conjunto de cambios. Hay dos identificadores porque el numero es mas corto y mas facil de recordar que
la cadena hexadecimal.
user3 La identidad de la persona que creo el conjunto de cambios. Este es un campo en el que se puede almacenar
cualquier valor, pero en la mayorıa de los casos contiene el nombre de una persona y su direccion de correoelectronico.
date4 La fecha y hora en la que el conjunto de cambios fue creado, y la zona horaria en la que fue creado. (La fecha
y hora son locales a dicha zona horaria; ambos muestran la fecha y hora para la persona que creo el conjunto de
cambios).
summary5 La primera lınea del texto que uso la persona que creo el conjunto de cambios para describir el mismo.
El texto impreso por “hg log” es solo un sumario; omite una gran cantidad de detalles.
La figura 2.1 es una representacion grafica del historial del repositorio hello, para hacer mas facil ver en que di-
reccion esta “fluyendo” el historial. Volveremos a esto varias veces en este capıtulo y en los siguientes.
0: 0a04
1: 82e5
2: fef8
3: 0272
4: 2278 (la más nueva)
(la más antigua)
4: 2278
número de
revisión
identificador del
conjunto de cambios
Figura 2.1: Historial grafico del repositorio hello
2.4.1. Conjuntos de cambios, revisiones, y comunicandose con otras personas
Ya que el ingles es un lenguaje notablemente desordenado, y el area de ciencias de la computacion tiene una
notable historia de confusion de terminos (porque usar solo un termino cuando cuatro pueden servir?), el control de
revisiones tiene una variedad de frases y palabras que tienen el mismo significado. Si usted habla acerca del historial
de Mercurial con alguien, encontrara que la expresion “conjunto de cambios” es abreviada a menudo como “cambio”
o (por escrito) “cset”6, y algunas veces un se hace referencia a un conjunto de cambios como una “revision” o “rev”7.
Si bien no es relevante que palabra use usted para referirse al concepto “conjunto de cambios”, el identificador que
usted use para referise a “un conjunto de cambios particular” es muy importante. Recuerde que el campo changeseten la salida de “hg log” identifica un conjunto de cambios usando tanto un numero como una cadena hexadecimal.
2N. del T. Conjunto de cambios.3N. del T. Usuario.4N. del T. Fecha.5N. del T. Sumario.6N. del T. Abreviatura para la expresion “changeset” en ingles.7N. del T. De nuevo, como abreviacion para el termino en ingles para “revision” (“revision”).
15
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 26/204
El numero de revision s´ olo es v´ alido dentro del repositorio.
Por otro lado, la cadena hexadecimal es el identificador permanente e inmutable que siempre identificara ese
conjunto de cambios en todas las copias del repositorio.
La diferencia es importante. Si usted le envıa a alguien un correo electronico hablando acerca de la “revision 33”, hay
una probabilidad alta de que la revision 33 de esa persona no sea la misma suya. Esto sucede porque el numero de
revision depende del orden en que llegan los cambios al repositorio, y no hay ninguna garant ıa de que los mismoscambios llegaran en el mismo orden en diferentes repositorios. Tres cambios dados a,b, c pueden aparecer en un
repositorio como 0,1,2, mientras que en otro aparecen como 1, 0, 2.
Mercurial usa los numeros de revision simplemente como una abreviacion conveniente. Si usted necesita hablar
con alguien acerca de un conjunto de cambios, o llevar el registro de un conjunto de cambios por alguna otra raz on
(por ejemplo, en un reporte de fallo), use el identificador hexadecimal.
2.4.2. Ver revisiones especıficas
Para reducir la salida de “hg log” a una sola revision, use la opcion -r (o --rev). Puede usar un numero de
revision o un identificador hexadecimal de conjunto de cambios, y puede pasar tantas revisiones como desee.
1 $ hg log -r 3
2 changeset: 3:0272e0d5a517
3 user: Bryan O’Sullivan <[email protected]>
4 date: Sat Aug 16 22:08:02 2008 +0200
5 summary: Get make to generate the final binary from a .o file.
6
7 $ hg log -r 0272e0d5a517
8 changeset: 3:0272e0d5a517
9 user: Bryan O’Sullivan <[email protected]>
10 date: Sat Aug 16 22:08:02 2008 +0200
11 summary: Get make to generate the final binary from a .o file.
12
13 $ h g l o g - r 1 - r 4
14 changeset: 1:82e55d328c8c
15 user: [email protected]
16 date: Fri Aug 26 01:21:28 2005 -0700
17 summary: Create a makefile
18
19 changeset: 4:2278160e78d4
20 tag: tip
21 user: Bryan O’Sullivan <[email protected]>
22 date: Sat Aug 16 22:16:53 2008 +0200
23 summary: Trim comments.
24
Si desea ver el historial de varias revisiones sin tener que mencionar cada una de ellas, puede usar la notaci´ on de
rango; esto le permite expresar el concepto “quiero ver todas las revisiones entre a y b, inclusive”.
1 $ hg log -r 2:4
2 changeset: 2:fef857204a0c
3 user: Bryan O’Sullivan <[email protected]>
4 date: Sat Aug 16 22:05:04 2008 +0200
5 summary: Introduce a typo into hello.c.
6
16
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 27/204
7 changeset: 3:0272e0d5a517
8 user: Bryan O’Sullivan <[email protected]>
9 date: Sat Aug 16 22:08:02 2008 +0200
10 summary: Get make to generate the final binary from a .o file.
11
12 changeset: 4:2278160e78d4
13 tag: tip14 user: Bryan O’Sullivan <[email protected]>
15 date: Sat Aug 16 22:16:53 2008 +0200
16 summary: Trim comments.
17
Mercurial tambien respeta el orden en que usted especifica las revisiones, ası que “hg log -r 2:4” muestra 2,3,4
mientras que “hg log -r 4:2” muestra 4, 3,2.
2.4.3. Informacion mas detallada
Aunque la informacion presentada por “hg log” es util si usted sabe de antemano que esta buscando, puede
que necesite ver una descripcion completa del cambio, o una lista de los ficheros que cambiaron, si est a tratando de
averiguar si un conjunto de cambios dado es el que usted est a buscando. La opcion -v (or --verbose) del comando“hg log” le da este nivel extra de detalle.
1 $ hg log -v -r 3
2 changeset: 3:0272e0d5a517
3 user: Bryan O’Sullivan <[email protected]>
4 date: Sat Aug 16 22:08:02 2008 +0200
5 files: Makefile
6 description:
7 Get make to generate the final binary from a .o file.
8
9
Si desea ver tanto la descripcion como el contenido de un cambio, anada la opcion -p (o --patch). Esto muestra
el contenido de un cambio como un diff unificado (si usted nunca ha visto un diff unificado antes, vea la seccion 12.4
para un vistazo global).
1 $ h g l o g - v - p - r 2
2 changeset: 2:fef857204a0c
3 user: Bryan O’Sullivan <[email protected]>
4 date: Sat Aug 16 22:05:04 2008 +0200
5 files: hello.c
6 description:
7 Introduce a typo into hello.c.
8
9
10 diff -r 82e55d328c8c -r fef857204a0c hello.c
11 --- a/hello.c Fri Aug 26 01:21:28 2005 -0700
12 +++ b/hello.c Sat Aug 16 22:05:04 2008 +0200
13 @@ -11,6 +11,6 @@
14
15 int main(int argc, char **argv)
16 {
17
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 28/204
17 - printf("hello, world!\n");
18 + printf("hello, world!\");
19 return 0;
20 }21
2.5. Todo acerca de las opciones para comandos
Tomemos un breve descanso de la tarea de explorar los comandos de Mercurial para hablar de un patr on en la
manera en que trabajan; sera util tener esto en mente a medida que avanza nuestra gira.
Mercurial tiene un enfoque directo y consistente en el manejo de las opciones que usted le puede pasar a los
comandos. Se siguen las convenciones para opciones que son comunes en sistemas Linux y Unix modernos.
Cada opcion tiene un nombre largo. Por ejemplo, el comando “ hg log” acepta la opcion --rev, como ya hemos
visto.
Muchas opciones tienen tambien un nombre corto. En vez de --rev, podemos usar -r. (El motivo para que
algunas opciones no tengan nombres cortos es que dichas opciones se usan rara vez.)
Las opciones largas empiezan con dos guiones (p.ej. --rev), mientras que las opciones cortas empiezan conuno (e.g. -r).
El nombre y uso de las opciones es consistente en todos los comandos. Por ejemplo, cada comando que le
permite pasar un ID de conjunto de cambios o un n umero de revision acepta tanto la opcion -r como la --rev.
En los ejemplos en este libro, uso las opciones cortas en vez de las largas. Esto s olo muestra mis preferencias, ası que
no le de significado especial a eso.
Muchos de los comandos que generan salida de algun tipo mostraran mas salida cuando se les pase la opcion -v
(o --verbose8), y menos cuando se les pase la opcion -q (o --quiet9).
2.6. Hacer y repasar cambios
Ahora que tenemos una comprension adecuada sobre como revisar el historial en Mercurial, hagamos algunoscambios y veamos como examinarlos.
Lo primero que haremos sera aislar nuestro experimento en un repositorio propio. Usaremos el comando “hg
clone”, pero no hace falta clonar una copia del repositorio remoto. Como ya contamos con una copia local del mismo,
podemos clonar esa. Esto es mucho mas rapido que clonar a traves de la red, y en la mayorıa de los casos clonar un
repositorio local usa menos espacio en disco tambien.
1 $ cd ..
2 $ hg clone hello my-hello
3 updating working directory
4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ cd my-hello
A manera de recomendacion, es considerado buena practica mantener una copia “prıstina” de un repositorio remoto a
mano, del cual usted puede hacer clones temporales para crear cajas de arena para cada tarea en la que desee trabajar.
Esto le permite trabajar en multiples tareas en paralelo, teniendo cada una de ellas aislada de las otras hasta que est en
completas y usted este listo para integrar los cambios de vuelta. Como los clones locales son tan baratos, clonar y
destruir repositorios no consume demasiados recursos, lo que facilita hacerlo en cualquier momento.
8N. del T. Prolijo.9N. del T. Silencioso.
18
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 29/204
En nuestro repositorio my-hello, hay un fichero hello.c que contiene el clasico programa “hello, world”10.
Usaremos el clasico y venerado comando sed para editar este fichero y hacer que imprima una segunda l ınea de
salida. (Estoy usando el comando sed para hacer esto solo porque es f acil escribir un ejemplo automatizado con el.
Dado que usted no tiene esta restriccion, probablemente no querra usar sed; use su editor de texto preferido para hacer
lo mismo).
1 $ sed -i ’/printf/a\\tprintf("hello again!\\n");’ hello.c
El comando “hg status” de Mercurial nos dice lo que Mercurial sabe acerca de los ficheros en el repositorio.
1 $ ls
2 Makefile hello.c
3 $ hg status
4 M hello.c
El comando “hg status” no imprime nada para algunos ficheros, solo una lınea empezando con “M” para el fichero
hello.c. A menos que usted lo indique explıcitamente, “hg status” no imprimira nada respecto a los ficheros que
no han sido modificados.
La “M” indica que Mercurial se dio cuenta de que nosotros modificamos hello.c. No tuvimos que decirle a
Mercurial que ıbamos a modificar ese fichero antes de hacerlo, o que lo modificamos una vez terminamos de hacerlo;
el fue capaz de darse cuenta de esto por s ı mismo.
Es algo util saber que hemos modificado el fichero hello.c, pero preferirıamos saber exactamente qu´ e cambios
hicimos. Para averiguar esto, usamos el comando “hg diff”.
1 $ hg diff
2 diff -r 2278160e78d4 hello.c
3 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200
4 +++ b/hello.c Tue Feb 10 18:23:34 2009 +0000
5 @@ -8,5 +8,6 @@
6 int main(int argc, char **argv)
7 {8 printf("hello, world!\");
9 + printf("hello again!\n");
10 return 0;11 }
2.7. Grabar cambios en un nuevo conjunto de cambios
Podemos modificar, compilar y probar nuestros cambios, y usar “hg status” y “hg diff” para revisar los mis-
mos, hasta que estemos satisfechos con los resultados y lleguemos a un momento en el que sea natural que querramos
guardar nuestro trabajo en un nuevo conjunto de cambios.
El comando “hg commit” nos permite crear un nuevo conjunto de cambios. Nos referiremos usualmente a esto
como “hacer una consigna” o consignar.
2.7.1. Definir un nombre de usuarioCuando usted trata de ejecutar “hg commit”11 por primera vez, no esta garantizado que lo logre. Mercurial registra
su nombre y direccion en cada cambio que usted consigna, para que mas adelante otros puedan saber quien es el
responsable de cada cambio. Mercurial trata de encontrar un nombre de usuario adecuado con el cual registrar la
consignacion. Se intenta con cada uno de los siguientes m etodos, en el orden presentado.
10N. del T. Hola, mundo.11N. del T. Hacer una consignacion
19
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 30/204
1. Si usted pasa la opcion -u al comando “hg commit” en la lınea de comandos, seguido de un nombre de usuario,
se le da a esto la maxima precedencia.
2. A continuacion se revisa si usted ha definido la variable de entorno HGUSER.
3. Si usted crea un fichero en su directorio personal llamado .hgrc, con una entrada username, se usa luego. Para
revisar como debe verse este fichero, refierase a la seccion 2.7.1 mas abajo.
4. Si usted ha definido la variable de entorno EMAIL, sera usada a continuacion.
5. Mercurial le pedira a su sistema buscar su nombre de usuario local, y el nombre de m aquina, y construira un
nombre de usuario a partir de estos componentes. Ya que esto generalmente termina generando un nombre de
usuario no muy util, se imprimira una advertencia si es necesario hacerlo.
Si todos estos procedimientos fallan, Mercurial fallara, e imprimira un mensaje de error. En este caso, no le permi-
tira hacer la consignacion hasta que usted defina un nombre de usuario.
Trate de ver la variable de entorno HGUSER y la opcion -u del comando “hg commit” como formas de hacer caso
omiso de la seleccion de nombre de usuario que Mercurial hace normalmente. Para uso normal, la manera mas simple y
sencilla de definir un nombre de usuario para usted es crear un fichero .hgrc; los detalles se encuentran mas adelante.
Crear el fichero de configuracion de Mercurial
Para definir un nombre de usuario, use su editor de texto favorito para crear un fichero llamado .hgrc en su
directorio personal. Mercurial usara este fichero para obtener las configuraciones personalizadas que usted haya hecho.
El contenido inicial de su fichero .hgrc deberıa verse ası.
1 # Este es un fichero de configuracion de Mercurial.
2 [ui]
3 username = Primernombre Apellido <[email protected]>
La l ınea “[ui]” define una section del fichero de configuracion, ası que usted puede leer la lınea “username = ...”
como “defina el valor del elemento username en la seccion ui”. Una seccion continua hasta que empieza otra nueva,
o se llega al final del fichero. Mercurial ignora las lıneas vacıas y considera cualquier texto desde el caracter “#” hasta
el final de la l ınea como un comentario.
Escoger un nombre de usuario
Usted puede usar el texto que desee como el valor del campo de configuracion username, ya que esta informacion
sera leıda por otras personas, e interpretada por Mercurial. La convencion que sigue la mayorıa de la gente es usar su
nombre y direccion de correo, como en el ejemplo anterior.
Nota: El servidor web integrado de Mercurial ofusca las direcciones de correo,
para dificultar la tarea de las herramientas de recoleccion de direcciones de correo
que usan los spammersa. Esto reduce la probabilidad de que usted empiece a recibir
mas correo basura si publica un repositorio en la red.
aN. del T. Personas que envıan correo no solicitado, t ambien conocido como correo basura
2.7.2. Escribir un mensaje de consignacionCuando consignamos un cambio, Mercurial nos ubica dentro de un editor de texto, para ingresar un mensaje que
describa las modificaciones que hemos introducido en este conjunto de cambios. Esto es conocido como un mensaje de
consignaci´ on. Sera un registro de lo que hicimos y porque lo hicimos, y sera impreso por “hg log” una vez hayamos
hecho la consignacion.
1 $ hg commit
20
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 31/204
El editor en que “hg commit” nos ubica contendra una lınea vacıa, seguida de varias lıneas que empiezan con la
cadena “HG:”.
1 lınea vacıa
2 HG: changed hello.c
Mercurial ignora las lıneas que empiezan con “HG:”; solo las usa para indicarnos para cuales ficheros esta registrandolos cambios. Modificar o borrar estas lıneas no tiene ningun efecto.
2.7.3. Escribir un buen mensaje de consignacion
Ya que por defecto “hg log” solo muestra la primera lınea de un mensaje de consignacion, lo mejor es escribir un
mensaje cuya primera lınea tenga significado por sı misma. A continuacion se encuentra un ejemplo de un mensaje de
consignacion que no sigue esta pauta, y debido a ello tiene un sumario que no es legible.
1 changeset: 73:584af0e231be
2 user: Persona Censurada <[email protected]>
3 date: Tue Sep 26 21:37:07 2006 -0700
4 summary: se incluye buildmeister/commondefs. Anade un modulo
Con respecto al resto del contenido del mensaje de consignaci on, no hay reglas estrictas-y-rapidas. Mercurial no
interpreta ni le da importancia a los contenidos del mensaje de consignacion, aunque es posible que su proyecto tenga
polıticas que definan una manera particular de escribirlo.
Mi preferencia personal es usar mensajes de consignacion cortos pero informativos, que me digan algo que no
puedo inferir con una mirada rapida a la salida de “hg log --patch”.
2.7.4. Cancelar una consignacion
Si usted decide que no desea hacer la consignacion mientras esta editando el mensaje de la misma, simplemente
cierre su editor sin guardar los cambios al fichero que esta editando. Esto hara que no pase nada ni en el repositorio ni
en el directorio de trabajo.
Si ejecutamos el comando “hg commit” sin ningun argumento, se registran todos los cambios que hemos hecho,
como lo indican “hg status” y “hg diff”.
2.7.5. Admirar nuestro trabajo
Una vez hemos terminado la consignacion, podemos usar el comando “hg tip”12 para mostrar el conjunto de
cambios que acabamos de crear. La salida de este comando es identica a la de “hg log”, pero solo muestra la revision
mas reciente en el repositorio.
1 $ hg tip -vp
2 changeset: 5:fccff93807a3
3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:34 2009 +0000
6 files: hello.c7 description:
8 Added an extra line of output
9
10
11 diff -r 2278160e78d4 -r fccff93807a3 hello.c
12N. del T. Punta.
21
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 32/204
12 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200
13 +++ b/hello.c Tue Feb 10 18:23:34 2009 +0000
14 @@ -8,5 +8,6 @@
15 int main(int argc, char **argv)
16 {17 printf("hello, world!\");
18 + printf("hello again!\n");19 return 0;
20 }21
Nos referimos a la revision mas reciente en el repositorio como la revision de punta, o simplemente la punta.
2.8. Compartir cambios
Anteriormente mencionamos que los repositorios en Mercurial estan auto contenidos. Esto quiere decir que el
conjunto de cambios que acabamos de crear solo existe en nuestro repositorio my-hello. Veamos unas cuantas formas
de propagar este cambio a otros repositorios.
2.8.1. Jalar cambios desde otro repositorio
Para empezar, clonemos nuestro repositorio hello original, el cual no contiene el cambio que acabamos de
consignar. Llamaremos a este repositorio temporal hello-pull.
1 $ cd ..
2 $ hg clone hello hello-pull
3 updating working directory
4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
Usaremos el comando “hg pull” para traer los cambios de my-hello y ponerlos en hello-pull. Sin embargo,
traer cambios desconocidos y aplicarlos en un repositorio es una perspectiva que asusta al menos un poco. Mercurial
cuenta con el comando “hg incoming”13 para decirnos que cambios jalarıa el comando “hg pull” al repositorio,sin jalarlos.
1 $ cd hello-pull
2 $ hg incoming ../my-hello
3 comparing with ../my-hello
4 searching for changes
5 changeset: 5:fccff93807a3
6 tag: tip
7 user: Bryan O’Sullivan <[email protected]>
8 date: Tue Feb 10 18:23:34 2009 +0000
9 summary: Added an extra line of output
10
(Por supuesto, alguien podrıa enviar mas conjuntos de cambios al repositorio en el tiempo que pasa entre la ejecucion
de “hg incoming” y la ejecucion de “hg pull” para jalar los cambios, ası que es posible que terminemos jalando
cambios que no esperabamos.)
Traer cambios al repositorio simplemente es cuestion de ejecutar el comando “hg pull”, indicandole de que repos-
itorio debe jalarlos.
13N. del T. Entrante, o cambios entrantes.
22
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 33/204
1 $ hg tip
2 changeset: 4:2278160e78d4
3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Sat Aug 16 22:16:53 2008 +0200
6 summary: Trim comments.7
8 $ hg pull ../my-hello
9 pulling from ../my-hello
10 searching for changes
11 adding changesets
12 adding manifests
13 adding file changes
14 added 1 changesets with 1 changes to 1 files
15 (run ’hg update’ to get a working copy)
16 $ hg tip
17 changeset: 5:fccff93807a3
18 tag: tip
19 user: Bryan O’Sullivan <[email protected]>20 date: Tue Feb 10 18:23:34 2009 +0000
21 summary: Added an extra line of output
22
Como puede verse por las salidas antes-y-despues de “hg tip”, hemos jalado exitosamente los cambios en nuestro
repositorio. Aun falta un paso para que podamos ver estos cambios en nuestro directorio de trabajo.
2.8.2. Actualizar el directorio de trabajo
Hasta ahora hemos pasado por alto la relacion entre un repositorio y su directorio de trabajo. El comando “ hg
pull” que ejecutamos en la seccion 2.8.1 trajo los cambios al repositorio, pero si revisamos, no hay rastro de esos
cambios en el directorio de trabajo. Esto pasa porque “hg pull” (por defecto) no modifica el directorio de trabajo. En
vez de eso, usamos el comando “hg update”14 para hacerlo.
1 $ grep printf hello.c
2 printf("hello, world!\");
3 $ hg update tip
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ grep printf hello.c
6 printf("hello, world!\");
7 printf("hello again!\n");
Puede parecer algo raro que “hg pull” no actualice el directorio de trabajo automaticamente. De hecho, hay
una buena razon para esto: usted puede usar “hg update” para actualizar el directorio de trabajo al estado en que se
encontraba en cualquier revisi´ on del historial del repositorio. Si usted hubiera actualizado el directorio de trabajo a una
revision anterior—digamos, para buscar el origen de un fallo—y hubiera corrido un “hg pull” que hubiera actualizadoel directorio de trabajo automaticamente a la nueva revision, puede que no estuviera particularmente contento.
Sin embargo, como jalar-y-actualizar es una secuencia de operaciones muy comun, Mercurial le permite combina-
rlas al pasar la opcion -u a “hg pull”.
1 hg pull -u
14N. del T. Actualizar.
23
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 34/204
Si mira de vuelta la salida de “hg pull” en la seccion 2.8.1 cuando lo ejecutamos sin la opcion -u, vera que el
comando imprimio un amable recordatorio de que tenemos que encargarnos explıcitamente de actualizar el directorio
de trabajo:
1 (run ’hg update’ to get a working copy)
Para averiguar en que revision se encuentra el directorio de trabajo, use el comando “hg parents”.
1 $ hg parents
2 changeset: 5:fccff93807a3
3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:34 2009 +0000
6 summary: Added an extra line of output
7
Si mira de nuevo la figura 2.1, vera flechas conectando cada conjunto de cambios. En cada caso, el nodo del que la
flecha sale es un padre, y el nodo al que la flecha llega es su hijo. El directorio de trabajo tiene un padre exactamente
de la misma manera; ese es el conjunto de cambios que contiene actualmente el directorio de trabajo.
Para actualizar el conjunto de trabajo a una revision particular, pase un numero de revision o un ID de conjunto decambios al comando “hg update”.
1 $ hg update 2
2 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 $ hg parents
4 changeset: 2:fef857204a0c
5 user: Bryan O’Sullivan <[email protected]>
6 date: Sat Aug 16 22:05:04 2008 +0200
7 summary: Introduce a typo into hello.c.
8
9 $ hg update
10 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
Si no indica explıcitamente una revision, “hg update” actualizara hasta la revision depunta, comose vio enla segunda
llamada a “hg update” en el ejemplo anterior.
2.8.3. Empujar cambios a otro repositorio
Mercurial nos permite empujar cambios a otro repositorio, desde el repositorio que estemos usando actualmente.
De la misma forma que en el ejemplo de “hg pull” arriba, crearemos un repositorio temporal para empujar allı nue-
stros cambios.
1 $ cd ..
2 $ hg clone hello hello-push
3 updating working directory
4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
El comando “hg outgoing”15 nos dice que cambios serıan empujados en el otro repositorio.
1 $ cd my-hello
2 $ hg outgoing ../hello-push
15N. del T. Saliente. Cambios salientes.
24
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 35/204
3 comparing with ../hello-push
4 searching for changes
5 changeset: 5:fccff93807a3
6 tag: tip
7 user: Bryan O’Sullivan <[email protected]>
8 date: Tue Feb 10 18:23:34 2009 +0000
9 summary: Added an extra line of output10
Y el comando “hg push” se encarga de empujar dichos cambios.
1 $ hg push ../hello-push
2 pushing to ../hello-push
3 searching for changes
4 adding changesets
5 adding manifests
6 adding file changes
7 added 1 changesets with 1 changes to 1 files
Al igual que “hg pull”, el comando “hg push” no actualiza el directorio de trabajo del repositorio en el que estamos
empujando los cambios. (A diferencia de “hg pull”, “hg push” no ofrece la opcion -u para actualizar el directorio
de trabajo del otro repositorio.)
Que pasa si tratamos de jalar o empujar cambios y el repositorio receptor ya tiene esos cambios? Nada emocio-
nante.
1 $ hg push ../hello-push
2 pushing to ../hello-push
3 searching for changes
4 no changes found
2.8.4. Compartir cambios a traves de una red
Los comandos que hemos presentando en las pocas secciones anteriores no estan limitados a trabajar con reposito-
rios locales. Cada uno de ellos funciona exactamente de la misma manera a traves de una conexion de red. Simplemente
pase una URL en vez de una ruta local.
1 $ hg outgoing http://hg.serpentine.com/tutorial/hello
2 comparing with http://hg.serpentine.com/tutorial/hello
3 searching for changes
4 changeset: 5:fccff93807a3
5 tag: tip
6 user: Bryan O’Sullivan <[email protected]>
7 date: Tue Feb 10 18:23:34 2009 +0000
8 summary: Added an extra line of output
9
En este ejemplo, podemos ver que cambios empujarıamos al repositorio remoto, aunque, de manera entendible, elrepositorio remoto esta configurado para no permitir a usuarios anonimos empujar cambios a el.
1 $ hg push http://hg.serpentine.com/tutorial/hello
2 pushing to http://hg.serpentine.com/tutorial/hello
3 searching for changes
4 ssl required
25
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 36/204
Capıtulo 3
Una gira de Mercurial: fusionar trabajo
Hasta ahora hemos cubierto como clonar un repositorio, hacer cambios, y jalar o empujar dichos cambios de un
repositorio a otro. Nuestro siguiente paso es fusionar cambios de repositorios separados.
3.1. Fusionar lıneas de trabajoFusionar es una parte fundamental de trabajar con una herramienta de control distribuido de versiones.
Alicia y Roberto tienen cada uno una copia personal del repositorio de un proyecto en el que estan trabajando.
Alicia arregla un fallo en su repositorio; Roberto anade una nueva caracterıstica en el suyo. Ambos desean que
el repositorio compartido contenga el arreglo del fallo y la nueva caracterıstica.
Frecuentemente trabajo en varias tareas diferentes en un mismo proyecto al mismo tiempo, cada una aislada
convenientemente de las otras en su propio repositorio. Trabajar de esta manera significa que a menudo debo
fusionar una parte de mi propio trabajo con otra.
Como fusionar es una operacion tan necesaria y comun, Mercurial la facilita. Revisemos el proceso. Empezaremos
clonando (otro) repositorio (ve lo seguido que aparecen?) y haciendo un cambio en el.
1 $ cd ..
2 $ hg clone hello my-new-hello
3 updating working directory
4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ cd my-new-hello
6 $ sed -i ’/printf/i\\tprintf("once more, hello.\\n");’ hello.c
7 $ hg commit -m ’A new hello for a new day.’
Ahora deberıamos tener dos copias de hello.c con contenidos diferentes. El historial de los dos repositorios diverge
ahora, como se ilustra en la figura 3.1.
1 $ cat hello.c
2 /*3 * Placed in the public domain by Bryan O’Sullivan. This program is
4 * not covered by patents in the United States or other countries.
5 */
6
7 #include <stdio.h>
8
9 int main(int argc, char **argv)
26
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 37/204
10 {11 printf("once more, hello.\n");
12 printf("hello, world!\");
13 return 0;
14 }15 $ cat ../my-hello/hello.c
16 /*17 * Placed in the public domain by Bryan O’Sullivan. This program is
18 * not covered by patents in the United States or other countries.
19 */
20
21 #include <stdio.h>
22
23 int main(int argc, char **argv)
24 {25 printf("hello, world!\");
26 printf("hello again!\n");
27 return 0;
28 }
0: 0a04
1: 82e5
2: fef8
3: 0272
4: 2278
5: fccf
my−hello
0: 0a04
1: 82e5
2: fef8
3: 0272
4: 2278
5: 05b9
my−new−hello
Los cambios
más recientes
difieren
historia común
revisión principal
(sin hijos)
Figura 3.1: Historial reciente divergente de los repositorios my-hello y my-new-hello
Ya sabemos que jalar los cambios desde nuestro repositorio my-hello no tendra efecto en el directorio de trabajo.
1 $ hg pull ../my-hello2 pulling from ../my-hello
3 searching for changes
4 adding changesets
5 adding manifests
6 adding file changes
7 added 1 changesets with 1 changes to 1 files (+1 heads)
27
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 38/204
8 (run ’hg heads’ to see heads, ’hg merge’ to merge)
Sin embargo, el comando “hg pull” dice algo acerca de “frentes”1.
3.1.1. Conjuntos de cambios de frentes
Un frente es un cambio que no tiene descendientes, o hijos, como tambien se les conoce. La revision de punta es,por tanto, un frente, porque la revision mas reciente en un repositorio no tiene ningun hijo. Sin embargo, un repositorio
puede contener mas de un frente.
0: 0a04
1: 82e5
2: fef8
3: 0272
4: 2278
5: 05b9
6: fccf
tip (y principal)
principal
Figura 3.2: Contenidos del repositorio despues de jalar my-hello a my-new-hello
En la figura 3.2 usted puede ver el efecto que tiene jalar los cambios de my-hello a my-new-hello. El historial que
ya existıa en my-new-hello se mantiene intacto, pero fue anadida una nueva revision. Refiriendonos a la figura 3.1,
podemos ver que el ID del conjunto de cambios se mantiene igual en el nuevo repositorio, pero el n´ umero de revisi´ on
ha cambiado. (Incidentalmente, este es un buen ejemplo de porque no es seguro usar numeros de revision cuando se
habla de conjuntos de cambios). Podemos ver los frentes en un repositorio usando el comando “hg heads”2.
1 $ hg heads
2 changeset: 6:fccff93807a3
3 tag: tip
4 parent: 4:2278160e78d4
5 user: Bryan O’Sullivan <[email protected]>
6 date: Tue Feb 10 18:23:34 2009 +00007 summary: Added an extra line of output
8
9 changeset: 5:05b9c1e50b3c
10 user: Bryan O’Sullivan <[email protected]>
1N. del T. El autor se refiere a heads aquı.2N. del T. Frentes.
28
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 39/204
11 date: Tue Feb 10 18:23:36 2009 +0000
12 summary: A new hello for a new day.
13
3.1.2. Hacer la fusion
Que pasa si tratamos de usar el comando usual, “hg update”, para actualizar el nuevo frente?
1 $ hg update
2 abort: crosses branches (use ’hg merge’ or ’hg update -C’)
Mercurial nos indica que el comando “hg update” no hara la fusion; no actualizara el directorio de trabajo cuando
considera que lo que deseamos hacer es una fusion, a menos que lo obliguemos a hacerlo. En vez de “ hg update”,
usamos el comando “hg merge” para hacer la fusion entre los dos frentes.
1 $ hg merge
2 merging hello.c
3 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
4 (branch merge, don’t forget to commit)
4: 2278
5: 05b9
6: fccf punta (y frente)
frente
fusióndirectorio de trabajo
durante la fusión
4: 2278
5: 05b9
6: fccf
punta 7: 22a5
Directorio de trabajo durante la fusión Repositorio después de consignar la fusión
Figura 3.3: Directorio de trabajo y repositorio durante la fusi on, y consignacion consecuente
Esto actualiza el directorio de trabajo, de tal forma que contenga los cambios de ambos frentes, lo que se ve
reflejado tanto en la salida de “hg parents” como en los contenidos de hello.c.
1 $ hg parents
2
changeset: 5:05b9c1e50b3c3 user: Bryan O’Sullivan <[email protected]>
4 date: Tue Feb 10 18:23:36 2009 +0000
5 summary: A new hello for a new day.
6
7 changeset: 6:fccff93807a3
8 tag: tip
9 parent: 4:2278160e78d4
29
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 40/204
10 user: Bryan O’Sullivan <[email protected]>
11 date: Tue Feb 10 18:23:34 2009 +0000
12 summary: Added an extra line of output
13
14 $ cat hello.c
15 /*
16 * Placed in the public domain by Bryan O’Sullivan. This program is17 * not covered by patents in the United States or other countries.
18 */
19
20 #include <stdio.h>
21
22 int main(int argc, char **argv)
23 {24 printf("once more, hello.\n");
25 printf("hello, world!\");
26 printf("hello again!\n");
27 return 0;
28 }
3.1.3. Consignar los resultados de la fusion
Siempre que hacemos una fusion, “hg parents” mostrara dos padres hasta que consignemos (“hg commit”) los
resultados de la fusion.
1 $ hg commit -m ’Merged changes’
Ahora tenemos una nueva revision de punta; note que tiene los dos frentes anteriores como sus padres. Estos son las
mismas revisiones que mostro previamente el comando “hg parents”.
1 $ hg tip
2 changeset: 7:22a572779faf
3 tag: tip
4 parent: 5:05b9c1e50b3c
5 parent: 6:fccff93807a3
6 user: Bryan O’Sullivan <[email protected]>
7 date: Tue Feb 10 18:23:36 2009 +0000
8 summary: Merged changes
9
En la figura 3.3 usted puede apreciar una representacion de lo que pasa en el directorio de trabajo durante la fusion
cuando se hace la consignacion. Durante la fusion, el directorio de trabajo tiene dos conjuntos de cambios como sus
padres, y estos se vuelven los padres del nuevo conjunto de cambios.
3.2. Fusionar cambios con conflictos
La mayorıa de las fusiones son algo simple, pero a veces usted se encontrara fusionando cambios donde mas de
uno de ellos afecta las mismas secciones de los mismos ficheros. A menos que ambas modificaciones sean id enticas,
el resultado es un conflicto, en donde usted debe decidir como reconciliar ambos cambios y producir un resultado
coherente.
30
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 41/204
Saludos!
Soy Mariam Abacha, la
esposa del anterior
dictador de Nigeria
Sani Abacha. Le
contacto en secreto,
buscando los medios
para desarrollar
Saludos!
Soy Shehu Musa
Abacha, sobrina del
anterior dictador de
Nigeria Sani Abacha.
Le contacto en secreto,
buscando los medios
para desarrollar
Saludos!
Soy Alhaji Abba
Abacha, hijo del
anterior dictador de
Nigeria Sani Abacha.
Le contacto en secreto,
buscando los medios
para desarrollar
Versión inicial
Nuestros cambios Sus cambios
Figura 3.4: Cambios con conflictos a un documento
La figura 3.4 ilustra un ejemplo con dos cambios generando conflictos en un documento. Empezamos con una sola
version del fichero; luego hicimos algunos cambios; mientras tanto, alguien mas hizo cambios diferentes en el mismo
texto. Lo que debemos hacer para resolver el conflicto causado por ambos cambios es decidir como debe quedar
finalmente el fichero.
Mercurial no tiene ninguna utilidad integrada para manejar conflictos. En vez de eso, ejecuta un programa externo
llamado hgmerge. Es un guion de lınea de comandos que es instalado junto con Mercurial; usted puede modificarlo
para que se comporte como usted lo desee. Por defecto, lo que hace es tratar de encontrar una de varias herramientas
para fusionar que es probable que esten instaladas en su sistema. Primero se intenta con unas herramientas para fusionar
cambios automaticamente; si esto no tiene exito (porque la fusion demanda una guıa humana) o dichas herramientas
no estan presentes, el guion intenta con herramientas graficas para fusionar.
Tambien es posible hacer que Mercurial ejecute otro programa o guion en vez de hgmerge, definiendo la variable
de entorno HGMERGE con el nombre del programa de su preferencia.
3.2.1. Usar una herramienta grafica para fusion
Mi herramienta favorita para hacer fusiones es kdiff3, y la usare para describir las caracterısticas comunes de las
herramientas graficas para hacer fusiones. Puede ver una captura de pantalla de kdiff3 ejecutandose, en la figura 3.5.
El tipo de fusion que la herramienta hace se conoce como fusi´ on de tres vıas, porque hay tres versiones diferentes del
fichero en que estamos interesados. Debido a esto la herramienta divide la parte superior de la ventana en tres paneles.
A la izquierda esta la revision base del fichero, p.ej. la version mas reciente de la que descienden las dos
versiones que estamos tratando de fusionar.
En la mitad esta “nuestra” version del fichero, con las modificaciones que hemos hecho.
A la derecha esta la version del fichero de “ellos”, la que forma parte del conjunto de cambios que estamostratando de fusionar.
En el panel inferior se encuentra el resultado actual de la fusion. Nuestra tarea es reemplazar todo el texto rojo, que
muestra los conflictos sin resolver, con una fusion adecuada de “nuestra” version del fichero y la de “ellos”.
Los cuatro paneles estan enlazados; si avanzamos vertical o horizontalmente en cualquiera de ellos, los otros son
actualizados para mostrar las secciones correspondientes del fichero que tengan asociado.
31
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 42/204
Figura 3.5: Usando kdiff3 para fusionar versiones de un fichero
En cada conflicto del fichero podemos escoger resolverlo usando cualquier combinacion del texto de la revision
base, la nuestra, o la de ellos. Tambien podemos editar manualmente el fichero en que queda la fusion, si es necesario
hacer cambios adicionales.
Hay muchas herramientas para fusionar ficheros disponibles. Se diferencian en las plataformas para las que estan
disponibles, y en sus fortalezas y debilidades particulares. La mayorıa estan afinadas para fusionar texto plano, mien-
tras que otras estan pensadas para formatos de ficheros especializados (generalmente XML).
3.2.2. Un ejemplo real
En este ejemplo, reproduciremos el historial de modificaciones al fichero de la figura 3.4 mostrada anteriormente.
Empecemos creando un repositorio con la version base de nuestro documento.
1 $ cat > letter.txt <<EOF
2 > Greetings!
3 > I am Mariam Abacha, the wife of former
4 > Nigerian dictator Sani Abacha.
5 > EOF
6 $ hg add letter.txt
7 $ hg commit -m ’419 scam, first draft’
Clonaremos el repositorio y haremos un cambio al fichero.
1 $ cd ..
2 $ hg clone scam scam-cousin
3 updating working directory
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
32
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 43/204
5 $ cd scam-cousin
6 $ cat > letter.txt <<EOF
7 > Greetings!
8 > I am Shehu Musa Abacha, cousin to the former
9 > Nigerian dictator Sani Abacha.
10 > EOF
11 $ hg commit -m ’419 scam, with cousin’
Y haremos otro clon, para simular a alguien mas haciendo un cambio al mismo fichero. (Esto introduce la idea de
que no es tan inusual hacer fusiones consigo mismo, cuando usted aısla tareas en repositorios separados, y de hecho
encuentra conflictos al hacerlo.)
1 $ cd ..
2 $ hg clone scam scam-son
3 updating working directory
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ cd scam-son
6 $ cat > letter.txt <<EOF
7 > Greetings!
8 > I am Alhaji Abba Abacha, son of the former9 > Nigerian dictator Sani Abacha.
10 > EOF
11 $ hg commit -m ’419 scam, with son’
Ahora que tenemos dos versiones diferentes de nuestro fichero, crearemos un entorno adecuado para hacer la fusion.
1 $ cd ..
2 $ hg clone scam-cousin scam-merge
3 updating working directory
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ cd scam-merge
6 $ hg pull -u ../scam-son
7 pulling from ../scam-son
8 searching for changes
9 adding changesets
10 adding manifests
11 adding file changes
12 added 1 changesets with 1 changes to 1 files (+1 heads)
13 not updating, since new heads added
14 (run ’hg heads’ to see heads, ’hg merge’ to merge)
En este ejemplo, no usare el comando normal de Mercurial para hacer la fusion (hgmerge), porque lanzarıa mi linda
herramienta automatizada para correr ejemplos dentro de una interfaz grafica de usuario. En vez de eso, definire la
variable de entorno HGMERGE para indicarle a Mercurial que use el comando merge. Este comando forma parte de la
instalacion base de muchos sistemas Unix y similares. Si usted est a ejecutando este ejemplo en su computador, no semoleste en definir HGMERGE.
1 $ export HGMERGE=merge
2 $ hg merge
3 merging letter.txt
4 merge: warning: conflicts during merge
5 merging letter.txt failed!
33
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 44/204
6 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
7 There are unresolved merges, you can redo the full merge using:
8 hg update -C 1
9 hg merge 2
10 $ cat letter.txt
11 Greetings!
12 <<<<<<< /tmp/tour-merge-conflictsNZwSt/scam-merge/letter.txt13 I am Shehu Musa Abacha, cousin to the former
14 =======
15 I am Alhaji Abba Abacha, son of the former
16 >>>>>>> /tmp/letter.txt˜other.749P-k
17 Nigerian dictator Sani Abacha.
Debido a que merge no puede resolver los conflictos que aparecen, el deja marcadores de fusi´ on en el fichero con
conflictos, indicando si provienen de nuestra version o de la de ellos.
Mercurial puede saber —por el codigo de salida del comando merge— que no fue posible hacer la fusion exitosa-
mente, ası que nos indica que comandos debemos ejecutar si queremos rehacer la fusion. Esto puede ser util si, por
ejemplo, estamos ejecutando una herramienta grafica de fusion y salimos de ella porque nos confundimos o cometimos
un error.
Si la fusion —automatica o manual— falla, no hay nada que nos impida “arreglar” los ficheros afectados por
nosotros mismos, y consignar los resultados de nuestra fusion:
1 $ cat > letter.txt <<EOF
2 > Greetings!
3 > I am Bryan O’Sullivan, no relation of the former
4 > Nigerian dictator Sani Abacha.
5 > EOF
6 $ hg resolve -m letter.txt
7 hg: unknown command ’resolve’
8 Mercurial Distributed SCM
9
10 basic commands:
11
12 add add the specified files on the next commit
13 annotate show changeset information per file line
14 clone make a copy of an existing repository
15 commit commit the specified files or all outstanding changes
16 diff diff repository (or selected files)
17 export dump the header and diffs for one or more changesets
18 init create a new repository in the given directory
19 log show revision history of entire repository or files
20 merge merge working directory with another revision
21 parents show the parents of the working dir or revision
22 pull pull changes from the specified source
23 push push changes to the specified destination
24 remove remove the specified files on the next commit
25 serve export the repository via HTTP
26 status show changed files in the working directory
27 update update working directory
28
29 use "hg help" for the full list of commands or "hg -v" for details
30 $ hg commit -m ’Send me your money’
34
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 45/204
31 $ hg tip
32 changeset: 3:e29827f5cf51
33 tag: tip
34 parent: 1:eac603d73208
35 parent: 2:78b0a9e9cf1b
36 user: Bryan O’Sullivan <[email protected]>
37 date: Tue Feb 10 18:23:37 2009 +000038 summary: Send me your money
39
3.3. Simplificar el ciclo jalar-fusionar-consignar
El proceso de fusionar cambios delineado anteriomente es directo, pero requiere la ejecucion de tres comandos en
sucesion.
1 hg pull
2 hg merge
3 hg commit -m ’Fusionados cambios remotos’
En la consignacion final usted debe proveer un mensaje adecuado, que casi siempre es un fragmento de texto “de
relleno” carente de valor particular.
Serıa agradable reducir la cantidad de pasos necesarios, si fuera posible. De hecho, Mercurial es distribuido junto
con una extension llamada fetch3 que hace precisamente esto.
Mercurial cuenta con un mecanismo de extension flexible que le permite a sus usuarios extender su funcionalidad,
manteniendo el nucleo de Mercurial pequeno y f acil de manejar. Algunas extensiones anaden nuevos comandos que
usted puede usar desde la l ınea de comandos, mientras que otros funcionan “tras bambalinas”, por ejemplo, anadiendo
funcionalidad al servidor.
La extension fetch anade un comando llamado, no sorpresivamente, “hg fetch”. Esta extension actua como una
combinacion de “hg pull”, “hg update” y “hg merge”. Empieza jalando cambios de otro repositorio al repositorio
actual. Si encuentra que los cambios anaden un nuevo frente en el repositorio actual, inicia una fusion, y luego consigna
el resultado de la misma con un mensaje generado automaticamente. Si no se anadieron nuevos frentes, actualiza el
directorio de trabajo con el nuevo conjunto de cambios de punta.
Activar la extension fetch es f acil. Edite su .hgrc, y vaya a (o cree) la seccion [extensions]. Luego anada una
lınea que diga simplemente “fetch ”.
1 [extensions]
2 fetch =
(Normalmente, a la derecha del “=” deberıa aparecer la ubicacion de la extension, pero como el comando fetch es
parte de la distribucion estandar, Mercurial sabe donde buscarla.)
3N. del T. Descargar, traer.
35
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 46/204
Capıtulo 4
Tras bambalinas
A diferencia de varios sistemas de control de revisiones, los conceptos en los que se fundamenta Mercurial son lo
suficientemente simples como para entender f acilmente como funciona el software. Saber esto no es necesario, pero
considero util tener un “modelo mental” de que es lo que sucede.
Comprender esto me da la confianza de que Mercurial ha sido cuidadosamente disenado para ser tanto seguro como
eficiente. Y tal vez con la misma importancia, si es facil para mı hacerme a una idea adecuada de que esta haciendo elsoftware cuando llevo a cabo una tarea relacionada con control de revisiones, es menos probable que me sosprenda su
comportamiento.
En este capıtulo, cubriremos inicialmente los conceptos centrales del diseno de Mercurial, y luego discutiremos
algunos detalles interesantes de su implementacion.
4.1. Registro del historial de Mercurial
4.1.1. Seguir el historial de un unico fichero
Cuando Mercurial sigue las modificaciones a un fichero, guarda el historial de dicho fichero en un objeto de
metadatos llamado filelog1. Cada entrada en el fichero de registro contiene suficiente informacion para reconstruir una
revision del fichero que se esta siguiendo. Los ficheros de registro son almacenados como ficheros el el directorio
.hg/store/data. Un fichero de registro contiene dos tipos de informacion: datos de revisiones, y un ındice para
ayudar a Mercurial a buscar revisiones eficientemente.
El fichero de registro de un fichero grande, o con un historial muy largo, es guardado como ficheros separados
para datos (sufijo “.d”) y para el ındice (sufijo “.i”). Para ficheros pequenos con un historial pequeno, los datos de
revisiones y el ındice son combinados en un unico fichero “.i”. La correspondencia entre un fichero en el directorio
de trabajo y el fichero de registro que hace seguimiento a su historial en el repositorio se ilustra en la figura 4.1.
4.1.2. Administracion de ficheros monitoreados
Mercurial usa una estructura llamada manifiesto para centralizar la informacion que maneja acerca de los ficheros
que monitorea. Cada entrada en el manifiesto contiene informacion acerca de los ficheros involucrados en un unico
conjunto de cambios. Una entrada registra que ficheros estan presentes en el conjunto de cambios, la revision de cada
fichero, y otros cuantos metadatos del mismo.
4.1.3. Registro de informacion del conjunto de cambios
La bit acora de cambios contiene informacion acerca de cada conjunto de cambios. Cada revision indica quien
consigno un cambio, el comentario para el conjunto de cambios, otros datos relacionados con el conjunto de cambios,
y la revision del manifiesto a usar.
1N. del T. Fichero de registro
36
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 47/204
.hg/store/data/README.iREADME
.hg/store/data/src/hello.c.d
.hg/store/data/src/hello.c.isrc/hello.c
Directorio de trabajo Repositorio
Figura 4.1: Relacion entre ficheros en el directorio de trabajo y ficheros de registro en el repositorio
4.1.4. Relaciones entre revisiones
Dentro de una bitacora de cambios, un manifiesto, o un fichero de registro, cada revisi on conserva un apuntadora su padre inmediato (o sus dos padres, si es la revision de una fusion). Como mencione anteriormente, tambien hay
relaciones entre revisiones a trav´ es de estas estructuras, y tienen naturaleza jerarquica.
Por cada conjunto de cambios en un repositorio, hay exactamente una revisi on almacenada en la bitacora de
cambios. Cada revision de la bitacora de cambios contiene un apuntador a una unica revision del manifiesto. Una
revision del manifiesto almacena un apuntador a una unica revision de cada fichero de registro al que se le hacıa
seguimiento cuando fue creado el conjunto de cambios. Estas relaciones se ilustran en la figura 4.2.
Bitácora de cambios
Manifiesto
Bitácora de archivos
Figura 4.2: Relaciones entre metadatos
Como lo muestra la figura, no hay una relacion “uno a uno” entre las revisiones en el conjunto de cambios, el
manifiesto, o el fichero de registro. Si el manifiesto no ha sido modificado de un conjunto de cambios a otro, las
entradas en la bitacora de cambios para esos conjuntos de cambios apuntaran a la misma revision del manifiesto. Si
un fichero monitoreado por Mercurial no sufre ningun cambio de un conjunto de cambios a otro, la entrada para dicho
fichero en las dos revisiones del manifiesto apuntara a la misma revision de su fichero de registro.
37
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 48/204
4.2. Almacenamiento seguro y eficiente
La base comun de las bitacoras de cambios, los manifiestos, y los ficheros de registros es provista por una unica
estructura llamada el revlog2.
4.2.1. Almacenamiento eficiente
El revlog provee almacenamiento eficiente de revisiones por medio del mecanismo de deltas3. En vez de almacenar
una copia completa del fichero por cada revision, almacena los cambios necesarios para transformar una revision
anterior en la nueva revision. Para muchos tipos de fichero, estos deltas son tıpicamente de una fraccion porcentual del
tamano de una copia completa del fichero.
Algunos sistemas de control de revisiones obsoletos solo pueden manipular deltas de ficheros de texto plano. Ellos
o bien almacenan los ficheros binarios como instantaneas completas, o codificados en alguna representacion de texto
plano adecuada, y ambas alternativas son enfoques que desperdician bastantes recursos. Mercurial puede manejar
deltas de ficheros con contenido binario arbitrario; no necesita tratar el texto plano como un caso especial.
4.2.2. Operacion segura
Mercurial solo a˜ nade datos al final de los ficheros de revlog. Nunca modifica ninguna seccion de un fichero una
vez ha sido escrita. Esto es mas robusto y eficiente que otros esquemas que requieren modificar o reescribir datos.Adicionalmente, Mercurial trata cada escritura como parte de una transacci´ on, que puede cubrir varios ficheros.
Una transaccion es at omica: o bien la transaccion tiene exito y entonces todos sus efectos son visibles para todos
los lectores, o la operacion completa es cancelada. Esta garantıa de atomicidad implica que, si usted esta ejecutando
dos copias de Mercurial, donde una de ellas esta leyendo datos y la otra los esta escribiendo, el lector nunca vera un
resultado escrito parcialmente que podrıa confundirlo.
El hecho de que Mercurial solo hace adiciones a los ficheros hace mas f acil proveer esta garantıa transaccional. A
medida que sea mas f acil hacer operaciones como esta, mas confianza tendra usted en que sean hechas correctamente.
4.2.3. Recuperacion rapida de datos
Mercurial evita ingeniosamente un problema comun a todos los sistemas de control de revisiones anteriores¿
el problema de la recuperaci´ on4 ineficiente de datos. Muchos sistemas de control de revisiones almacenan los con-
tenidos de una revision como una serie incremental de modificaciones a una “instantanea”. Para reconstruir una versioncualquiera, primero usted debe leer la instantanea, y luego cada una de las revisiones entre la instantanea y su version
objetivo. Entre mas largo sea el historial de un fichero, mas revisiones deben ser leıdas, y por tanto toma mas tiempo
reconstruir una version particular.
La innovacion que aplica Mercurial a este problema es simple pero efectiva. Una vez la cantidad de informaci on de
deltas acumulada desde la ultima instantanea excede un umbral fijado de antemano, se almacena una nueva instantanea
(comprimida, por supuesto), en lugar de otro delta. Esto hace posible reconstruir cualquier version de un fichero
rapidamente. Este enfoque funciona tan bien que desde entonces ha sido copiado por otros sistemas de control de
revisiones.
La figura 4.3 ilustra la idea. En una entrada en el fichero ındice de un revlog, Mercurial almacena el rango de
entradas (deltas) del fichero de datos que se deben leer para reconstruir una revision en particular.
Nota al margen: la influencia de la compresion de vıdeo
Si le es familiar la compresion de vıdeo, o ha mirado alguna vez una emision de TV a traves de cable digital
o un servicio de satelite, puede que sepa que la mayor parte de los esquemas de compresion de vıdeo almacenan
2N. del T. Contraccion de revision log, registro de revision.3N. del T. Diferencias.4N. del T. Retrieval. Recuperacion en el sentido de traer los datos, o reconstruirlos a partir de otros datos, pero no debido a una falla o calamidad,
sino a la operacion normal del sistema.
38
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 49/204
Índice, rev 7
Índice de bitácora de revisiones (archivo .i) Datos de Bitacora de revisiones (archivo .d)
Snapshot, rev 4
Delta, rev 4 a 5
Delta, rev 5 a 6
Delta, rev 6 a 7
Delta, rev 2 a 3
Figura 4.3: Instantanea de un revlog, con deltas incrementales
cada cuadro del mismo como un delta contra el cuadro predecesor. Adicionalmente, estos esquemas usan tecnicas de
compresion “con perdida” para aumentar la tasa de compresion, por lo que los errores visuales se acumulan a lo largo
de una cantidad de deltas inter-cuadros.
Ya que existe la posibilidad de que un flujo de vıdeo se “pierda” ocasionalmente debido a fallas en la se nal, y
para limitar la acumulacion de errores introducida por la compresion con perdidas, los codificadores de vıdeo insertan
periodicamente un cuadro completo (tambien llamado “cuadro clave”) en el flujo de vıdeo; el siguiente delta es gen-
erado con respecto a dicho cuadro. Esto quiere decir que si la senal de vıdeo se interrumpe, se reanudara una vez se
reciba el siguiente cuadro clave. Ademas, la acumulacion de errores de codificacion se reinicia con cada cuadro clave.
4.2.4. Identificacion e integridad fuerte
Ademas de la informacion de deltas e instantaneas, una entrada en un revlog contiene un hash criptografico de
los datos que representa. Esto hace dif ıcil falsificar el contenido de una revision, y hace f acil detectar una corrupcion
accidental.
Los hashes proveen mas que una simple revision de corrupcion: son usados como los identificadores para las
revisiones. Los hashes de identificacion de conjuntos de cambios que usted ve como usuario final son de las revisiones
de la bitacora de cambios. Aunque los ficheros de registro y el manifiesto tambien usan hashes, Mercurial solo los usa
tras bambalinas.
Mercurial verifica que los hashes sean correctos cuando recupera revisiones de ficheros y cuando jala cambios
desde otro repositorio. Si se encuentra un problema de integridad, Mercurial se quejara y detendra cualquier operacion
que este haciendo.
Ademas del efecto que tiene en la eficiencia en la recuperacion, el uso periodico de instantaneas de Mercurial lo
hace mas robusto frente a la corrupcion parcial de datos. Si un fichero de registro se corrompe parcialmente debido a
un error de hardware o del sistema, a menudo es posible reconstruir algunas o la mayorıa de las revisiones a partir delas secciones no corrompidas del fichero de registro, tanto antes como despues de la seccion corrompida. Esto no serıa
posible con un sistema de almacenamiento basado unicamente en deltas.
39
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 50/204
4.3. Historial de revisiones, ramas y fusiones
Cada entrada en el revlog de Mercurial conoce la identidad de la revision de su ancestro inmediato, al que se conoce
usualmente como su padre. De hecho, una revision contiene sitio no solo para un padre, sino para dos. Mercurial usa
un hash especial, llamado el “ID nulo”, para representar la idea de “no hay padre aqu ı”. Este hash es simplemente una
cadena de ceros.
En la figura 4.4 usted puede ver un ejemplo de la estructura conceptual de un revlog. Los ficheros de registro,manifiestos, y bitacoras de cambios comparten la misma estructura; solo difieren en el tipo de datos almacenados en
cada delta o instantanea.
La primera revision en un revlog (al final de la imagen) tiene como padre al ID nulo, en las dos ranuras disponibles
para padres. En una revision normal, la primera ranura para padres contiene el ID de la revision padre, y la segunda
contiene el ID nulo, senalando ası que la revision solo tiene un padre real. Un par de revisiones que tenga el mismo ID
padre son ramas. Una revision que representa una fusion entre ramas tiene dos IDs de revision normales en sus ranuras
para padres.
4.4. El directorio de trabajo
En el directorio de trabajo, Mercurial almacena una instantanea de los ficheros del repositorio como si fueran los
de un conjunto de cambios particular.El directorio de trabajo “sabe” que conjunto de cambios contiene. Cuando usted actualiza el directorio de traba-
jo para que contenga un conjunto de cambios particular, Mercurial busca la revision adecuada del manifiesto para
averiguar que ficheros estaba monitoreando cuando se hizo la consignacion del conjunto de cambios, y que revision
de cada fichero era la actual en ese momento. Luego de eso, recrea una copia de cada uno de esos ficheros, con los
mismos contenidos que tenıan cuando fue consignado el conjunto de cambios.
El estado de directorio5 contiene el conocimiento de Mercurial acerca del directorio de trabajo. Allı se detalla a
que conjunto de cambios es actualizado el directorio de trabajo, y todos los ficheros que Mercurial esta monitoreando
en este directorio.
Tal como la revision de un revlog tiene espacio para dos padres, para que pueda representar tanto una revisi on
normal (con un solo padre) o una fusion de dos revisiones anteriores, el estado de directorio tiene espacio para dos
padres. Cuando usted usa el comando “hg update”, el conjunto de cambios al que usted se actualiza es almacenado
en la casilla destinada al “primer padre”, y un ID nulo es almacenado en la segunda. Cuando usted hace una fusion
(“hg merge”) con otro conjunto de cambios, la casilla para el primer padre permanece sin cambios, y la casilla parael segundo es actualizada con el conjunto de cambios con el que usted acaba de hacer la fusi on. El comando “hg
parents” le indica cuales son los padres del estado de directorio.
4.4.1. Que pasa en una consignacion
El estado de directorio almacena informacion sobre los padres para algo mas que mero registro. Mercurial usa los
padres del estado de directorio como los padres de un nuevo conjunto de cambios cuando usted hace una consignacion.
La figura 4.5 muestra el estado normal del directorio de trabajo, que tiene un unico conjunto de cambios como
padre. Dicho conjunto de cambios es la punta, el conjunto de cambios mas reciente en el repositorio que no tiene
hijos.
Es util pensar en el directorio de trabajo como en “el conjunto de cambios que estoy a punto de enviar”. Cualquier
fichero que usted le diga a Mercurial que fue anadido, borrado, renombrado o copiado, se vera reflejado en ese conjunto
de cambios, como tambien se veran las modificaciones a cualquiera de los ficheros que Mercurial ya est e monitorean-do; el nuevo conjunto de cambios dentra los padres del directorio de trabajo como propios.
Luego de una consignacion, Mercurial actualizara los padres del directorio de trabajo, de tal manera que el primer
padre sea el ID del nuevo conjunto de cambios, y el segundo sea el ID nulo. Esto puede verse en la figura 4.6. Mercurial
no toca ninguno de los ficheros del directorio de trabajo cuando usted hace la consignacion; solo modifica el estado de
directorio para anotar sus nuevos padres.
5N. del T. dirstate, en ingles en el original.
40
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 51/204
4.4.2. Creacion de un nuevo frente
Es perfectamente normal actualizar el directorio de trabajo a un conjunto de cambios diferente a la punta actual. Por
ejemplo, usted podrıa desear saber en que estado se encontraba su proyecto el martes pasado, o podrıa estar buscando
en todos los conjuntos de cambios para saber cuando se introdujo un fallo. En casos como estos, la accion natural
es actualizar el directorio de trabajo al conjunto de cambios de su interes, y examinar directamente los ficheros en el
directorio de trabajo para ver sus contenidos tal como estaban en el momento de hacer la consignaci on. El efecto que
tiene esto se muestra en la figura 4.7.
Una vez se ha actualizado el directorio de trabajo a un conjunto de cambios anterior, qu e pasa si se hacen cambios,
y luego se hace una consignacion? Mercurial se comporta en la misma forma que describı anteriormente. Los padres
del directorio de trabajo se convierten en los padres del nuevo conjunto de cambios. Este nuevo conjunto de cambios
no tiene hijos, ası que se convierte en la nueva punta. Y el repositorio tiene ahora dos conjuntos de cambios que no
tienen hijos; a estos los llamamos frentes. Usted puede apreciar la estructura que esto crea en la figura 4.8.
Nota: Si usted es nuevo en Mercurial, deberıa tener en mente un “error” comun,
que es usar el comando “hg pull” sin ninguna opcion. Por defecto, el comando
“hg pull” no actualiza el directorio de trabajo, ası que usted termina trayendo
nuevos conjuntos de cambios a su repositorio, pero el directorio de trabajo sigue
usando el mismo conjunto de cambios que tenıa antes de jalar. Si usted hace al-
gunos cambios, y luego hace una consignacion, estara creando un nuevo frente,
porque su directorio de trabajo no es sincronizado a cualquiera que sea la nuevapunta.
Pongo la palabra “error” en comillas porque todo lo que usted debe hacer para
rectificar la situacion es hacer una fusion (“hg merge”), y luego una consignacion
(“hg commit”). En otras palabras, esto casi nunca tiene consecuencias negativas;
solo sorprende a la gente. Discutire otras formas de evitar este comportamiento,
y porque Mercurial se comporta de esta forma, inicialmente sorprendente, m as
adelante.
4.4.3. Fusion de frentes
Cuando usted ejecuta el comando “hg merge”, Mercurial deja el primer padre del directorio de trabajo intacto, y
escribe como segundo padre el conjunto de cambios contra el cual usted esta haciendo la fusion, como se muestra en
la figura 4.9.Mercurial tambien debe modificar el directorio de trabajo, para fusionar los ficheros que el monitorea en los dos
conjuntos de cambios. Con algunas simplificaciones, el proceso es el siguiente, por cada fichero en los manifiestos de
ambos conjuntos de cambios.
Si ningun conjunto de cambios ha modificado un fichero, no se hace nada con el mismo.
Si un conjunto de cambios ha modificado un fichero, y el otro no lo ha hecho, se crea una copia del fichero con
las modificaciones pertinentes en el directorio de trabajo.
Si un conjunto de cambios borra un fichero, y el otro no lo ha hecho (o tambien lo borro), se borra dicho fichero
del directorio de trabajo.
Si un conjunto de cambios ha borrado un fichero, pero el otro lo ha modificado, se le pregunta al usuario
que hacer: conservar el fichero modificado, o borrarlo?
Si ambos conjuntos de cambios han modificado un fichero, se invoca el programa externo de fusi on para definir
el nuevo contenido del fichero fusionado. Esto puede requerir interaccion directa de parte del usuario.
Si un conjunto de cambios ha modificado un fichero, y el otro ha renombrado o copiado el mismo, asegurarse
de que los cambios sigan al nuevo nombre de fichero.
41
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 52/204
Hay mas detalles—hacer una fusion tiene una gran cantidad de casos especiales—pero estas son las elecciones mas
comunes que se ven involucradas en una fusion. Como usted puede ver, muchos de los casos son completamente
automaticos, y de hecho la mayorıa de las fusiones terminan automaticamente, sin requerir la interaccion del usuario
para resolver ningun conflicto.
Cuando considere que pasa cuando usted hace una consignacion despues de una fusion, de nuevo el directorio
de trabajo es “el conjunto de cambios que estoy a punto de consignar”. Una vez termina su trabajo el comando “ hg
merge”, el directorio de trabajo tiene dos padre; estos se convertiran en los padres del nuevo conjunto de cambios.Mercurial le permite hacer multiples fusiones, pero usted debe consignar los resultados de cada fusion sucesi-
vamente. Esto es necesario porque Mercurial solo monitorea dos padres, tanto para las revisiones como para los
directorios de trabajo. Aunque tecnicamente es posible fusionar varios conjuntos de trabajo en una sola operacion, la
posibilidad de confundir al usuario y crear un desorden terrible en la fusion se hace incontenible de inmediato.
4.5. Otras caracterısticas de dise ˜ no interesantes
En las secciones anteriores, he tratado de resaltar algunos de los aspectos mas importantes del diseno de Mercurial,
para mostrar que se presta gran cuidado y atencion a la confiabilidad y el desempeno. Sin embargo, la atencion a
los detalles no para ahı. Hay una cantidad de aspectos de la construccion de Mercurial que encuentro interesantes
personalmente. Detallare unos cuantos de ellos aquı, aparte de los elementos “importantes” de arriba, para que, si
usted esta interesado, pueda obetener una idea mejor de la cantidad de esfuerzo mental invertido en el diseno de unsistema bien disenado.
4.5.1. Compresion ingeniosa
Cuando es adecuado, Mercurial almacenara tanto las instantaneas como los deltas en formato comprimido. Lo hace
tratando siempre de comprimir una instantanea o delta, y conservando la version comprimida solo si es mas pequena
que la version sin compresion.
Esto implica que Mercurial hace “lo correcto” cuando almacena un fichero cuyo formato original esta comprimido,
como un fichero zip o una imagen JPEG. Cuando estos tipos de ficheros son comprimidos por segunda vez, el fichero
resultante usualmente es mas grande que la version comprimida una sola vez, por lo que Mercurial almacenara el
fichero zip o JPEG original.
Los deltas entre revisiones de un fichero comprimido usualmente son mas grandes que las instantaneas del mismo
fichero, y Mercurial de nuevo hace “lo correcto” en estos casos. El encuentra que dicho delta excede el umbral respectoal cual se deberıa almacenar una instantanea completa del fichero, ası que almacena la instantanea, ahorrando espacio
de nuevo respecto al enfoque simplista de usar unicamente deltas.
Recompresion de red
Cuando almacena las revisiones en disco, Mercurial usa el algoritmo de compresi on “deflacion” (el mismo usado
en el popular formato de fichero zip), que provee una buena velocidad con una tasa de compresion respetable. Sin
embargo, cuando se transmiten datos de revisiones a traves de una conexion de red, Mercurial descomprime los datos
comprimidos de las revisiones.
Si la conexion es hecha a traves de HTTP, Mercurial recomprime el flujo completo de datos usando un algoritmo de
compresion que brinda una mejor tasa de compresion (el algoritmo Burrows-Wheeler del ampliamente usado paquete
de compresion bzip2). Esta combinacion de algoritmo y compresion del flujo completo de datos (en vez de una
revision a la vez) reduce sustancialmente la cantidad de bytes a transferir, brindando as ı un mejor desempeno de redsobre casi todo tipo de redes.
(Si la conexion se hace sobre ssh, Mercurial no recomprmime el flujo, porque ssh puede hacer esto por sı mismo.)
4.5.2. Reordenado de lectura/escritura y atomicidad
Anadir datos al final de un fichero no es todo lo que hace falta para garantizar que un lector no vera una escritura
parcial. Si recuerda la figura 4.2, las revisiones en la bitacora de cambios apuntan a revisiones en el manifiesto, y las
42
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 53/204
revisiones en el manifiesto apuntan a revisiones en ficheros de registro. Esta jerarquıa es deliberada.
Un escritor inicia una transaccion al escribir los datos del ficheros del fichero de registro y el manifiesto, y no
escribe nada en la bitacora de cambios hasta que dichas escrituras hayan terminado. Un lector empieza leyendo datos
de la bitacora de cambios, luego del manifiesto, y finalmente del fichero de registro.
Como el escritor siempre termina de escribir los datos en el fichero de registro y en el manifiesto antes de escribir
a la bitacora de cambios, un lector nunca vera un apuntador a una version parcialmente escrita de revisiones del
manifiesto desde la bitacora de cambios, y nunca leera un apuntador a una revision parcialmente escrita del fichero deregistro desde el manifiesto.
4.5.3. Acceso concurrente
El reordenado de lectura/escritura y la atomicidad garantizan que Mercurial nunca necesita bloquear un repositorio
cuando esta leyendo datos, aun si se esta escribiendo al repositorio mientras se hace la lectura. Esto tiene un gran
efecto en la escalabilidad; usted puede tener cualquier cantidad de procesos Mercurial leyendo datos de un repositorio
de manera segura al mismo tiempo, sin importar si se esta escribiendo al mismo o no.
La naturaleza carente de bloqueos de la lectura significa que si usted esta compartiendo un repositorio en un
sistema multiusuario, no necesita dar a los usuarios locales permisos de escritura a su repositorio para que ellos
puedan clonarlo o jalar cambios; solo necesitan permisos de lectura. (Esta no es una caracterıstica comun entre los
sistemas de control de revisiones, ası que no la de por hecha! Muchos de ellos requieren que los lectores sean capaces
de bloquear el repositorio antes de poder leerlo, y esto requiere acceso de escritura en al menos un directorio, lo quepor supuesto se convierte en una fuente de todo tipo de problemas administrativos y de seguridad bastante molestos.)
Mercurial usar bloqueos para asegurarse de que solo un proceso pueda escribir a un repositorio al mismo tiempo
(el mecanismo de bloqueo es seguro incluso sobre sistemas de ficheros notoriamente hostiles al bloqueo, como NFS).
Si un repositorio esta bloqueado, los escritores esperaran un buen rato para revisar si el repositorio ya ha sido desblo-
queado, pero si el repositorio sique bloqueado por mucho tiempo, el proceso que intenta escribir fallar a por tiempo de
espera maximo. Esto significa que sus guiones automaticos diarios no se quedaran esperando para siempre, apilandose
si el sistema se cayo sin que nadie se diera cuenta, por ejemplo. (S ı, el tiempo de espera maximo es configurable, de
cero a infinito).
Acceso seguro al estado de directorio
Al igual que con los datos de revision, Mercurial no requiere un bloqueo para leer el fichero de estado de directorio;
sı se usa un bloqueo para escribir a el. Para evitar la posibilidad de leer una copia parcialmente escrita del fichero deestado de directorio, Mercurial escribe a un fichero con un nombre unico en el mismo directorio del fichero de estado
de directorio, y luego renombra atomicamente este fichero temporal a dirstate6. Ası se garantiza que el fichero
llamado dirstate este completo, y no parcialmente escrito.
4.5.4. Evitar movimientos de brazo
Un aspecto crıtico para el desempeno de Mercurial es evitar los movimientos del brazo de lectura del disco duro, ya
que cualquier movimiento de brazo es mucho mas costoso que incluso una operacion de lectura relativamente grande.
Es por esto que, por ejemplo, el estado de directorio es almacenado como un solo fichero. Si hubiera un estado de
directorio por cada directorio que Mercurial monitorea, el disco harıa un movimiento de brazo por cada directorio. En
cambio, Mercurial lee el estado de directorio completo en un solo paso.
Mercurial tambien usa un esquema de “copiar al escribir” cuando clona un repositorio en un mismo medio de
almacenamiento local. En vez de copiar cada fichero de revlog del repositorio viejo al nuevo, se crea un “enlace duro”,que es una manera sucinta de decir “estos dos nombres apuntan al mismo fichero”. Cuando Mercurial est a a punto de
escribir a uno de los ficheros de revlog, revisa si la cantidad de nombres apuntando al fichero es de m as de uno. Si lo
es, mas de un repositorio esta usando el fichero, ası que Mercurial hace una nueva copia del fichero, privada para este
repositorio.
6N. del T. Estado de directorio.
43
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 54/204
Algunos desarrolladores de control de revisiones han indicado que la idea de hacer una copia privada completa
de un fichero no es eficiente desde el punto de vista de almacenamiento. Aunque esto es cierto, el almacenamiento
es barato, y este metodo brinda el maximo rendimiento al tiempo que delega la mayor parte del trabajo de manejo de
ficheros al sistema operativo. Un esquema alternativo seguramente reducirıa el desempeno y aumentarıa la complejidad
del software, cada uno de los cuales es mucho mas importante para la “sensacion” que se tiene del software en el trabajo
dıa a dıa.
4.5.5. Otros contenidos del estado de directorio
Debido a que Mercurial no lo fuerza a indicar si usted est a modificando un fichero, se usa el estado de directorio
para almacenar informacion extra para poder determinar efecientemente si usted ha modificado un fichero. Por cada
fichero en el directorio de trabajo, se almacena el momento en que Mercurial modific o por ultima vez el fichero, y el
tamano del fichero en ese momento.
Cuando usted anade (“hg add”), remueve (“hg remove”), renombra (“hg rename”)o copia (“hg copy”) ficheros,
Mercurial actualiza el estado de directorio para saber que hacer con dichos ficheros cuando usted haga la consignacion.
Cuando Mercurial esta revisando el estado de los ficheros en el directorio de trabajo, revisa primero la fecha de
modificacion del fichero. Si no ha cambiado, el fichero no ha sido modificado. Si el tamano del fichero ha cambiado,
el fichero ha sido modificado. Solo en el caso en que el tiempo de modificacion ha cambiado, pero el tamano no, es
necesario leer el contenido del fichero para revisar si ha cambiado. Almacenar estos pocos datos reduce dramatica-
mente la cantidad de datos que Mercurial debe leer, lo que brinda una mejora en el rendimiento grande, comparadocon otros sistemas de control de revisiones.
44
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 55/204
Segundo padre
32bf9a5f22c0
Hash de revisión
34b8b7a15ea1
...
Datos de Revisión (delta o snapshot)
Primer padre
000000000000
Segundo padre
000000000000
Hash de revisión
ff9dc8bc2a8b
...
Datos de revisión (delta o snapshot)
Primer padre
34b8b7a15ea1
Segundo padre
000000000000
Hash de revisión
1b67dc96f27a
...
Datos de revisión (delta o snapshot)
Primer padre
ff9dc8bc2a8b
Segundo padre
000000000000
Hash de revisión
5b80c922ebdd
...
Datos de revisión (delta o snapshot)
Primer padre
ecacb6b4c9fd
Segundo padre
000000000000
Hash de revisión
32bf9a5f22c0
...
Datos de revisión (delta o snapshot)
Primer padre
ff9dc8bc2a8b
Segundo padre
000000000000
Hash de revisión
ecacb6b4c9fd
...
Datos de revisión (delta o snapshot)
Revisión principal
(sin hijos)
Revisión de fusión
(dos padres)
Ramas
(dos revisiones,
mismo padre)
Primera revisión
(ambos padres nulos)
Primer padre
5b80c922ebdd
Figura 4.4:
45
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 56/204
e7639888bb2f
7b064d8bac5e
000000000000
Historia en el repositorio
e7639888bb2f
000000000000
Primer padre
Segundo padre
Padres del directorio de trabajo
Figura 4.5: El directorio de trabajo puede tener dos padres
dfbbb33f3fa3
e7639888bb2f
7b064d8bac5e
000000000000
Historia en el repositorio
dfbbb33f3fa3
000000000000
Primer padre
Segundo padre
Padres del directorio de trabajo
Nuevo
conjuntode
cambios
Figura 4.6: El directorio de trabajo obtiene nuevos padres luego de una consignaci on
46
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 57/204
e7639888bb2f
7b064d8bac5e
000000000000
Historia en el repositorio
7b064d8bac5e
000000000000
Primer padre
Segundo padre
Padres del directorio de trabajo
Figura 4.7: El directorio de trabajo, actualizado a un conjunto de cambios anterior
e7639888bb2f
7b064d8bac5e
000000000000
ffb20e1701ea
000000000000
Primer padre
Segundo padre
Padres del directorio de trabajo
ffb20e1701ea
Cabeza Pre−existente Cabeza recién creada (y tip)
Figura 4.8: Despues de una consignacion hecha mientras se usaba un conjunto de cambios anterior
47
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 58/204
7b064d8bac5e
000000000000
ffb20e1701ea
e7639888bb2f
Primer padre (sin cambio)
Segundo padre
Padres del directorio de trabajo
ffb20e1701ea
Cabeza pre−existente Cabeza recién creada(y tip)
e7639888bb2f
Figura 4.9: Fusion de dos frentes
48
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 59/204
Capıtulo 5
Mercurial dıa a dıa
5.1. Como indicarle a Mercurial que ficheros seguir
Mercurial no trabaja con ficheros en su repositorio a menos que usted se lo indique expl ıcitamente. La orden “hg
status” le mostrara cuales ficheros son desconocidos para Mercurial; se emplea un “?” para mostrar tales ficheros.
Para indicarle a Mercurial que tenga en cuenta un fichero, emplee la orden “hg add”. Una vez que haya adicionadoel fichero, la lınea referente al fichero al aplicar la orden “hg status” para tal fichero cambia de “?” a “A”.
1 $ hg init add-example
2 $ cd add-example
3 $ e c h o a > a
4 $ hg status
5 ? a
6 $ hg add a
7 $ hg status
8 A a
9 $ hg commit -m ’Added one file’
10 $ hg status
Despues de invocar “hg commit”, los ficheros que haya adicionado antes de consignar no se listar an en la salida
de “hg status”. La razon para esto es que “hg status” solamente le muestra aquellos ficheros “interesantes” —
los que usted haya modificado o a aquellos sobre los que usted haya indicado a Mercurial hacer algo— de forma
predeterminada. Si tiene un repositorio que contiene miles de ficheros, rara vez desear a saber cuales de ellos estan
siendo seguidos por Mercurial, pero que no han cambiado. (De todas maneras, puede obtener tal informaci on; mas
adelante hablaremos de ello.)
Cuando usted anade un fichero, Mercurial no hace nada con el inmediatamente. En cambio, tomara una instantanea
del estado del fichero la proxima vez que usted consigne. Continuara haciendo seguimiento a los cambios que haga
sobre el fichero cada vez que consigne, hasta que usted lo elimine.
5.1.1. Nombramiento explıcito e implıcito de ficheros
Mercurial tiene un comportamiento util en el cual si a una orden, le pasa el nombre de un directorio, todas las
ordenes lo interpretaran como “Deseo operar en cada fichero de este directorio y sus subdirectorios”.
1 $ mkdir b
2 $ echo b > b/b
3 $ echo c > b/c
4 $ mkdir b/d
49
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 60/204
5 $ echo d > b/d/d
6 $ hg add b
7 adding b/b
8 adding b/c
9 adding b/d/d
10 $ hg commit -m ’Added all files in subdirectory’
Tenga en cuenta que en este ejemplo Mercurial imprimio los nombres de los ficheros que se adicionaron, mientras que
no lo hizo en el ejemplo anterior cuando adicionamos el fichero con nombre a.
En el ultimo caso hicimos explıcito el nombre del fichero que deseabamos adicionar en la lınea de ordenes, y
Mercurial asume en tales casos que usted sabe lo que esta haciendo y no imprime informacion alguna.
Cuando hacemos impl ıcitos los nombres de los ficheros dando el nombre de un directorio, Mercurial efectua el
paso extra de imprimir el nombre de cada fichero con el que va a hacer algo. Esto para aclarar lo que est a sucediendo,
y reducir en lo posible una sorpresa silenciosa pero fatal. Este comportamiento es com un a la mayorıa de ordenes en
Mercurial.
5.1.2. Nota al margen: Mercurial trata ficheros, no directorios
Mercurial no da seguimiento a la informacion de los directorios. En lugar de eso tiene en cuenta las rutas de
los ficheros. Antes de crear un fichero, primero crea todos los directorios que hagan falta para completar la ruta delmismo. Despues de borrar un fichero, borra todos los directorios vacıos que estuvieran en la ruta del fichero borrado.
Suena como una diferencia trivial, pero tiene una consecuencia practica menor: no es posible representar un directorio
completamente vacıo en Mercurial.
Los directorios vacıos rara vez son utiles, y hay soluciones alternativas no intrusivas que usted puede emplear para
obtener el efecto apropiado. Los desarrolladores de Mercurial pensaron que la complejidad necesaria para administrar
directorios vacıos no valıa la pena frente al beneficio limitado que esta caracterıstica podrıa traer.
Si necesita un directorio vacıo en su repositorio, hay algunas formas de lograrlo. Una es crear un directorio,
despues hacer “hg add” a un fichero “oculto” dentro de ese directorio. En sistemas tipo Unix, cualquier fichero cuyo
nombre comience con un punto (“.”) es tratado como oculto por la mayorıa de comandos y herramientas GUI. Esta
aproximacion se ilustra en la figura 5.1.
1
$ hg init hidden-example2 $ cd hidden-example
3 $ mkdir empty
4 $ touch empty/.hidden
5 $ hg add empty/.hidden
6 $ hg commit -m ’Manage an empty-looking directory’
7 $ ls empty
8 $ cd ..
9 $ hg clone hidden-example tmp
10 updating working directory
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 $ ls tmp
13 empty
14 $ ls tmp/empty
Figura 5.1: Simular un directorio vacıo con un fichero oculto
Otra forma de abordar la necesidad de un directorio vacıo es simplemente crear uno en sus guiones de construccion
antes de que lo necesiten.
50
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 61/204
5.2. Como dejar de hacer seguimiento a un fichero
Si decide que un fichero no pertenece a su repositorio, use la orden “hg remove”; se borrara el fichero y le
indicara a Mercurial que deje de hacerle seguimiento. Los ficheros eliminados se representan con “ R” al usar “hg
status”.
1 $ hg init remove-example
2 $ cd remove-example
3 $ e c h o a > a
4 $ mkdir b
5 $ echo b > b/b
6 $ h g a d d a b
7 adding b/b
8 $ hg commit -m ’Small example for file removal’
9 $ hg remove a
10 $ hg status
11 R a
12 $ hg remove b
13 removing b/b
Despues de hacer “hg remove” a un fichero, Mercurial dejara de hacer seguimiento al mismo, incluso si recrea el
fichero con el mismo nombre en su directorio de trabajo. Si decide recrear un fichero con el mismo nombre y desea que
Mercurial le haga seguimiento, basta con hacerle “hg add”. Mercurial sabra que el fichero recientemente adicionado
no esta relacionado con el fichero anterior que tenıa el mismo nombre.
5.2.1. Al eliminar un fichero no se afecta su historial
Es preciso tener en cuenta que eliminar un fichero tiene solo dos efectos.
Se elimina la version actual del fichero del directorio de trabajo.
Mercurial deja de hacer seguimiento a los cambios del fichero desde la proxima consignacion.
Al eliminar un fichero no se altera de ninguna manera el historial del mismo.Si actualiza su directorio de trabajo a un conjunto de cambios en el cual el fichero que elimino aun era tenido en
cuenta, este reaparecera en el directorio de trabajo, con los contenidos que este tenıa cuando se consigno tal conjunto
de cambios. Si usted actualiza el directorio de trabajo a un conjunto de cambios posterior en el cual el fichero hab ıa
sido eliminado, Mercurial lo eliminara de nuevo del directorio de trabajo.
5.2.2. Ficheros perdidos
Mercurial considera como perdido un fichero que usted borro, pero para el que no se uso “hg remove”. Los
ficheros perdidos se representan con “!” al visualizar “hg status”. Las ordenes de Mercurial generalmente no haran
nada con los ficheros perdidos.
1 $ hg init missing-example
2 $ cd missing-example3 $ e c h o a > a
4 $ hg add a
5 $ hg commit -m ’File about to be missing’
6 $ rm a
7 $ hg status
8 ! a
51
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 62/204
Si su repositorio contiene un fichero que “hg status” reporta como perdido, y desea que el mismo se vaya, se
puede usar “hg remove --after” posteriormente para indicarle a Mercurial que usted deseaba borrar tal fichero.
1 $ hg remove --after a
2 $ hg status
3 R a
Por otro lado, si borro un fichero perdido por accidente, puede usar “hg revert nombre de fichero” para
recuperar el fichero. Reaparecera, sin modificaciones.
1 $ hg revert a
2 $ cat a
3 a
4 $ hg status
5.2.3. Nota al margen: ¿Por que decirle explıcitamente a Mercurial que elimine un fichero?
Es posible que se haya preguntado por que Mercurial exige que usted le indique explıcitamente que esta borrando
un fichero. Al principio del desarrollo de Mercurial, este permitıa que usted borrara el fichero sin mas; Mercurial se
darıa cuenta de la ausencia del fichero automaticamente despues de la ejecucion de “hg commit”, y dejarıa de hacer
seguimiento al fichero. En la practica, resultaba muy sencillo borrar un fichero accidentalmente sin darse cuenta.
5.2.4. Atajo util—agregar y eliminar ficheros en un solo paso
Mercurial ofrece una orden combinada, “hg addremove”, que agrega los ficheros que no tienen seguimiento y
marca los ficheros faltantes como eliminados.
1 $ hg init addremove-example
2 $ cd addremove-example
3 $ e c h o a > a
4 $ e c h o b > b
5 $ hg addremove
6 adding a
7 adding b
La orden “hg commit” se puede usar con la opcion -A que aplica el mismo agregar-eliminar, seguido inmediatamente
de una consignacion.
1 $ e c h o c > c
2 $ hg commit -A -m ’Commit with addremove’
3 adding c
5.3. Copiar ficheros
Mercurial ofrece la orden “hg copy” para hacer una copia nueva de un fichero. Cuando se copia un fichero con
esta orden, Mercurial lleva un registro indicando que el nuevo fichero es una copia del fichero original. Los ficheros
copiados se tratan de forma especial cuando usted hace una fusion con el trabajo de alguien mas.
52
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 63/204
5.3.1. Resultados de copiar un fichero durante una fusion
Durante una fusion los cambios “siguen” una copia. Para ilustrar lo que esto significa, haremos un ejemplo. Comen-
zaremos con el mini repositorio usual que contiene un solo fichero
1 $ hg init my-copy
2 $ cd my-copy
3 $ echo line > file4 $ hg add file
5 $ hg commit -m ’Added a file’
Debemos hacer algo de trabajo en paralelo, de forma que tengamos algo para fusionar. Aquı clonamos el repositorio.
1 $ cd ..
2 $ hg clone my-copy your-copy
3 updating working directory
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
De vuelta en el repositorio inicial, usemos la orden “hg copy” para hacer una copia del primer fichero que creamos.
1 $ cd my-copy
2 $ hg copy file new-file
Si vemos la salida de la orden “hg status”, el fichero copiado luce tal como un fichero que se ha anadido
normalmente.
1 $ hg status
2 A new-file
Pero si usamos la opcion -C de la orden “hg status”, se imprimira otra lınea: el fichero desde el cual fue copiado
nuestro fichero recien anadido.
1 $ hg status -C
2 A new-file
3 file
4 $ hg commit -m ’Copied file’
Ahora, en el repositorio que clonamos, hagamos un cambio en paralelo. Adicionaremos una lınea de contenido al
fichero original que creamos.
1 $ cd ../your-copy
2 $ echo ’new contents’ >> file
3 $ hg commit -m ’Changed file’
Hemos modificado el fichero file en este repositorio. Cuando jalemos los cambios del primer repositorio y fu-
sionemos las dos cabezas, Mercurial propagara los cambios que hemos hecho localmente en file a su copia, new-file.
1 $ hg pull ../my-copy
2 pulling from ../my-copy
3 searching for changes
4 adding changesets
5 adding manifests
6 adding file changes
53
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 64/204
7 added 1 changesets with 1 changes to 1 files (+1 heads)
8 (run ’hg heads’ to see heads, ’hg merge’ to merge)
9 $ hg merge
10 merging file and new-file
11 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
12 (branch merge, don’t forget to commit)
13 $ cat new-file14 line
15 new contents
5.3.2. ¿Por que los cambios se reflejan en las copias?
Este comportamiento de cambios en ficheros que se propagan a las copias de los ficheros parecer ıa esoterico, pero
en la mayorıa de casos es absolutamente deseable. Es indispensable recordar que esta propagaci on solamente sucede
cuando fusionamos. Por lo tanto si sobre un fichero se usa “ hg copy”, y se modifica el fichero original durante el
curso normal de su trabajo, nada pasara.
Lo segundo a tener en cuenta es que las modificaciones solamente se propagaran en las copias unicamente si los
repositorios de los cuales esta jalando los cambios no saben de la copia.
Explicaremos a continuaci´on la raz
´on de este comportamiento de Mercurial. Digamos que yo he aplicado unarreglo de un fallo importante a un fichero fuente y consigne los cambios. Por otro lado, usted decidio hacer “hg
copy” sobre el fichero en su repositorio, sin saber acerca del fallo o sin ver el arreglo, y ha comenzado a trabajar sobre
su copia del fichero.
Si jala y fusiona mis cambios y Mercurial no hubiera propagado los cambios en las copias, su fichero fuente tendrıa
el fallo, a menos que usted haya recordado propagar el arreglo del fallo a mano, el mismo permanecer ıa en su copia
del fichero.
Mercurial previene esta clase de problemas, gracias a la propagacion automatica del cambio que arreglo el fallo
del fichero original. Hasta donde se, Mercurial es el ´ unico sistema de control de revisiones que propaga los cambios
en las copias de esta forma.
Cuando su historial de cambios tiene un registro de la copia y la subsecuente fusi on, usualmente no es necesario
propagar los cambios el fichero original a las copias del mismo, y por esta raz on Mercurial propaga unicamente los
cambios en las copias hasta este punto y no mas alla.
5.3.3. Como hacer que los cambios no sigan a la copia?
Si por algun motivo usted decide que esta caracterıstica de propagacion automatica de cambios en las copias
no es para usted, simplemente use la orden usual de su sistema para copiar ficheros (en sistemas tipo Unix, es cp),
y posteriormente use “hg add” sobre la nueva copia hecha a mano. Antes de hacerlo, de todas maneras, relea la
seccion 5.3.2, y tome una decision asegurandose que este comportamiento no es el apropiado para su caso especıfico.
5.3.4. Comportamiento de la orden “hg copy”
Cuando usa la orden “hg copy”, Mercurial hace una copia de cada fichero fuente tal como se encuentra en el direc-
torio actual. Esto significa que si usted hace modificaciones a un fichero, y le aplica “hg copy” sin haber consignado
primero los cambios, la nueva copia contendra tambien las modificaciones que haya hecho hasta ese punto. (Este
comportamiento me parece poco intuitivo, y por tal motivo lo menciono.)La orden “hg copy” actua de forma parecida a la orden cp de Unix (puede usar el alias “hg cp” si le es mas
comodo). El ultimo argumento es el destino, y todos los argumentos previos son las fuentes. Si solamente indica un
fichero como la fuente, y el destino no existe, se crea un fichero nuevo con ese nombre.
1 $ mkdir k
2 $ hg copy a k
54
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 65/204
3 $ ls k
4 a
Si el destino es un directorio, Mercurial copia las fuentes en este.
1 $ mkdir d
2 $ h g c o p y a b d3 $ ls d
4 a b
La copia de un directorio es recursiva, y preserva la estructura del directorio fuente.
1 $ hg copy c e
2 copying c/a/c to e/a/c
Si tanto la fuente como el destino son directorios, la estructura de la fuente se recrea en el directorio destino.
1 $ hg copy c d
2 copying c/a/c to d/c/a/c
De la misma forma que la orden “hg rename”, si copia un fichero manualmente y desea que Mercurial sepa que
ha copiado un fichero, basta con aplicar la opcion --after a la orden “hg copy”.
1 $ c p a z
2 $ hg copy --after a z
5.4. Renombrar ficheros
La necesidad de renombrar un fichero es mas comun que hacer una copia del mismo. La razon por la cual discutı la
orden “hg copy” antes de hablar acerca de cambiar el nombre de los ficheros, es que Mercurial trata el renombrar un
fichero de la misma forma que una copia. Por lo tanto, saber lo que hace Mercurial cuando usted copia un fichero le
indica que esperar cuando renombra un fichero.Cuando usa la orden “hg rename”, Mercurial hace una copia de cada fichero fuente, lo borra y lo marca como
fichero eliminado.
1 $ hg rename a b
La orden “hg status” muestra la nueva copia del fichero como anadida y el fichero inicial de la copia, como elimi-
nado.
1 $ hg status
2 A b
3 R a
De la misma forma en que se usa la orden “hg copy
”, debemos usar la opcion-C
de la orden “hg status
” paraverificar que el fichero anadido realmente comienza a ser seguido por Mercurial como una copia del fichero original,
ahora eliminado.
1 $ hg status -C
2 A b
3 a
4 R a
55
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 66/204
Igual que con “hg remove” y “hg copy”, puede indicarsele a Mercurial acerca de un renombramiento inmediato
con la opcion --after. El comportamiento de la orden “hg rename” y las opciones que acepta, son similares a la
orden “hg copy” en casi todo.
5.4.1. Renombrar ficheros y fusionar cambios
Dado que el renombrado de Mercurial se implementa como un copiar-y-eliminar, la misma propagacion de cambiosocurre cuando usted fusiona despues de renombrar como despues de hacer una copia.
Si yo modifico un fichero y usted lo renombra a un nuevo fichero, y posteriormente fusionamos nuestros respectivos
cambios, mi modificacion al fichero bajo su nombre original se propagara en el fichero con el nuevo nombre. (Es lo
que se esperarıa que “simplemente funcione,” pero, no todos los sistemas de control de revisiones hacen esto.)
Aunque el hecho de que los cambios sigan la copia es una caracter ıstica respecto a la cual usted puede estar
de acuerdo y decir “si, puede ser util,” deberıa ser claro que el seguimiento de cambios de un renombramiento es
definitivamente importante. Sin esto, serıa muy sencillo que los cambios se quedaran atras cuando los ficheros se
renombran.
5.4.2. Cambios de nombre divergentes y fusion
El caso de renombramiento con nombres divergentes ocurre cuando dos desarrolladores comienzan con un fichero—
llamemoslo foo—en sus repositorios respectivos.
1 $ hg clone orig anne
2 updating working directory
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 $ hg clone orig bob
5 updating working directory
6 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Anne renombra el fichero a bar.
1 $ cd anne
2 $ hg mv foo bar
3 $ hg ci -m ’Rename foo to bar’
Mientras que Bob lo renombra como quux.
1 $ cd ../bob
2 $ hg mv foo quux
3 $ hg ci -m ’Rename foo to quux’
Veo esto como un conflicto porque cada desarrollador ha expresado intenciones diferentes acerca de como consid-
era deberıa haberse nombrado el fichero.
¿Que cree que deberıa pasar cuando fusionen su trabajo? El comportamiento de Mercurial es que siempre preserva
ambos nombres cuando fusiona los conjuntos de cambios que contienen nombres divergentes.
1 # See http://www.selenic.com/mercurial/bts/issue455
2 $ cd ../orig
3 $ hg pull -u ../anne
4 pulling from ../anne
5 searching for changes
6 adding changesets
7 adding manifests
56
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 67/204
8 adding file changes
9 added 1 changesets with 1 changes to 1 files
10 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
11 $ hg pull ../bob
12 pulling from ../bob
13 searching for changes
14 adding changesets15 adding manifests
16 adding file changes
17 added 1 changesets with 1 changes to 1 files (+1 heads)
18 (run ’hg heads’ to see heads, ’hg merge’ to merge)
19 $ hg merge
20 warning: detected divergent renames of foo to:
21 bar
22 quux
23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 (branch merge, don’t forget to commit)
25 $ ls
26 bar quux
Tenga en cuenta que Mercurial le advierte acerca de nombres divergentes, pero deja que usted decida qu e hacer
con la divergencia despues de la fusion.
5.4.3. Cambios de nombre convergentes y fusion
Otra clase de conflicto al cambiar el nombre de ficheros ocurre cuando dos personas eligen renombrar diferentes
ficheros fuente al mismo destino. En este caso Mercurial aplica su maquinaria de fusion usual, y le permite a usted
guiar la situacion a una resolucion adecuada.
5.4.4. Otros casos lımite relacionados con renombramientos
Mercurial tiene un fallo de mucho tiempo en el cual no es capaz de fusionar cuando por un lado hay un fichero con
un nombre dado, mientras que en otro hay un directorio con el mismo nombre. Esto esta documentado como Fallo de
Mercurial No. 29.
1 $ hg init issue29
2 $ cd issue29
3 $ e c h o a > a
4 $ hg ci -Ama
5 adding a
6 $ e c h o b > b
7 $ hg ci -Amb
8 adding b
9 $ h g u p 0
10 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
11 $ mkdir b12 $ echo b > b/b
13 $ hg ci -Amc
14 adding b/b
15 created new head
16 $ hg merge
17 abort: Is a directory: /tmp/issue29HYiaCx/issue29/b
57
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 68/204
5.5. Recuperarse de equivocaciones
Mercurial tiene unas ordenes poderosas que le ayudaran a recuperarse de equivocaciones comunes.
La orden “hg revert” le permite deshacer cambios que haya hecho a su directorio de trabajo. Por ejemplo, si
aplico “hg add” a un fichero por accidente, ejecute “hg revert” con el nombre del fichero que anadio, y en tanto
que el fichero no haya sido tocado de forma alguna, no sera adicionado, ni seguido por Mercurial. Tambien puede usar
“hg revert” para deshacerse de cambios erroneos a un fichero.Tenga en cuenta que la orden “hg revert” se usa para cambios que no han sido consignados. Cuando haya
consignado un cambio, si decide que era un error, puede hacer algo todavıa, pero sus opciones pueden estar mas
limitadas.
Para obtener informacion acerca de la orden “hg revert” y detalles de como tratar con cambios consignados, vea
el capıtulo 9.
58
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 69/204
Capıtulo 6
Colaborar con otros
Debido a su naturaleza descentralizada, Mercurial no impone polıtica alguna de como deben trabajar los grupos
de personas. Sin embargo, si el control distribuido de versiones es nuevo para usted, es bueno tener herramientas y
ejemplos a la mano al pensar en posibles modelos de flujo de trabajo.
6.1. La interfaz web de Mercurial
Mercurial tiene una poderosa interfaz web que provee bastantes capacidades utiles.
Para uso interactivo, la interfaz le permite visualizar uno o varios repositorios. Puede ver el historial de un reposi-
torio, examinar cada cambio (comentarios y diferencias), y ver los contenidos de cada directorio y fichero.
Adicionalmente la interfaz provee notificaciones RSS de los cambios del repositorio. Esto le permite “subscribirse”a
un repositorio usando su herramienta de lectura de notificaciones favorita, y ser notificado automaticamente de la ac-
tividad en el repositorio tan pronto como sucede. Me gusta mucho mas este modelo que el estar suscrito a una lista de
correo a la cual se envıan las notificaciones, dado que no requiere configuracion adicional de parte de quien sea que
esta administrando el repositorio.
La interfaz web tambien permite a los usuarios remotos clonar repositorios, jalar cambios, y (cuando el servidor
esta configurado para permitirlo) empujar cambios al mismo. El protocolo de entunelamiento HTTP de Mercurial
comprime datos agresivamente, de forma que trabaja eficientemente incluso en conexiones de red con poco ancho debanda.
La forma mas sencilla de empezar a trabajar con la interfaz web es usar su navegador para visitar un repositorio
existente, como por ejemplo el repositorio principal de Mercurial en http://www.selenic.com/repo/hg?style=
gitweb.
Si esta interesado en proveer una interfaz web a sus propios repositorios, Mercurial ofrece dos formas de hacerlo.
La primera es usando la orden “hg serve”, que esta enfocada a servir “de forma liviana” y por intervalos cortos. Para
mas detalles de como usar esta orden vea la seccion 6.4 mas adelante. Si tiene un repositorio que desea hacer disponible
de forma permanente, Mercurial tiene soporte embebido para el estandar CGI (Common Gategay Interface), que es
manejado por todos los servidores web comunes. Vea la seccion 6.6 para los detalles de la configuracion a traves de
CGI.
6.2. Modelos de colaboracionCon una herramienta adecuadamente flexible, tomar decisiones acerca del flujo de trabajo es mucho mas un reto
de ingenierıa social que un problema tecnico. Mercurial impone pocas limitaciones sobre como puede estructurar el
flujo de trabajo en un proyecto, ası que depende de usted y de su grupo definir y trabajar con un modelo que se ajuste
a sus necesidades particulares.
59
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 70/204
6.2.1. Factores a tener en cuenta
El aspecto mas importante que usted debe considerar de cualquier modelo es que tan bien se ajusta a las necesidades
y capacidades de la gente que lo usara. Esto puede parecer auto-evidente; aun ası, usted no puede permitirse olvidarlo
ni por un momento.
Una vez definı un modelo de flujo de trabajo que parecıa ser perfectamente adecuado para mı, pero que causo una
cantidad considerable de consternacion y friccion dentro de mi equipo de desarrollo. A pesar de mis intentos de ex-
plicar porque necesitabamos un conjunto complejo de ramas, y de como debıan fluir los cambios entre ellas, algunos
miembros del equipo se molestaron. Aunque ellos eran personas inteligentes, no quer ıan prestar atencion a las lim-
itaciones bajo las cuales estabamos operando, o comparar las consecuencias de esas limitaciones con los detalles del
modelo que yo estaba proponiendo.
No esconda bajo la alfombra los problemas sociales o t ecnicos que usted pueda preveer. Sin importar el esquema
que usted use, debe hacer planes para enfrentar posibles errores o problemas. Considere anadir procedimientos autom-
atizados para prevenir, o recuperarse rapidamente de, los problemas que usted pueda anticipar. A manera de ejemplo,
si usted planea tener una rama en la vayan los cambios que no est en listos para produccion, harıa bien en pensar en la
posibilidad de que alguien fusione accidentalmente dichos cambios en una rama para publicacion. Usted podrıa evitar
este problema en particular escribiendo un gancho que evite que se fusionen cambios desde ramas inapropiadas.
6.2.2. Anarquıa informal
No sugerirıa un enfoque de “todo vale” como algo sostenible, pero es un modelo que es facil de entender, y que
funciona perfectamente bien en unas cuantas situaciones inusuales.
Como un ejemplo, muchos proyectos tienen un grupo informal de colaboradores que rara vez se reunen f ısica-
mente. A algunos grupos les gusta evitar el aislamiento de trabajar a distancia organizando “sprints” ocasionales. En
un sprint, una cantidad de gente se reune en un mismo sitio (el cuarto de conferencias de una empresa, el cuarto de
reuniones de un hotel, ese tipo de lugares) y pasar varios dıas mas o menos encerrados allı, trabajando intensamente
en un punado de proyectos.
Un sprint es el lugar perfecto para usar el comando “hg serve”, ya que “hg serve” no requiere una infraestruc-
tura especial de servidores. Usted puede empezar a trabajar con “hg serve” en momentos, leyendo la seccion 6.4 mas
abajo. Luego simplemente dıgale a las personas cerca suyo que usted est a ejecutando un servidor, envıeles la URL a
traves de un mensaje instantaneo, y tendra de inmediato una forma rapida de trabajar juntos. Ellos pueden escribir su
URL en un navegador web y revisar sus cambios r apidamente; o ellos pueden jalar un arreglo de fallo que usted haya
hecho y verificarlo; o pueden clonar una rama que contiene una nueva caracter ıstica y probarla.Lo bueno, y lo malo, de hacer cosas de manera ad hoc como aquı, es que solo las personas que saben de sus
cambios, y donde estan, pueden verlos. Un enfoque tan informal sencillamente no puede escalarse mas alla de un
punado de personas, porque cada individuo tiene que saber de n repositorios diferentes de los cuales jalar.
6.2.3. Un repositorio central unico
Para proyectos pequenos migrando desde una herramienta centralizada de control de revisiones, tal vez la forma
mas f acil de empezar es hacer que los cambios vayan a traves de un repositorio central compartido. Este es tambien el
“bloque base” para esquemas mas ambiciosos de flujo de trabajo.
Los colaboradores empiezan clonando una copia de este repositorio. Ellos pueden jalar cambios de el siempre que
lo necesiten, y algunos (o tal vez todos los) desarrolladores tienen permiso para empujar cambios de vuelta cuando
esten listos para que los demas los vean.
Bajo este modelo, para los usuarios tiene sentido jalar cambios directamente entre ellos, sin ir a trav es del reposi-torio central. Considere un caso en el que yo tengo un arreglo tentativo de fallo, pero me preocupa que al publicarlo en
el repositorio central rompa los arboles de todos los demas cuando lo jalen. Para reducir el potencial de dano, puedo
pedirle a usted que clone mi repositorio en un repositorio personal suyo y lo pruebe. Esto nos permite aplazar este
cambio potencialmente inseguro hasta que haya tenido algo de pruebas.
En este tipo de escenario, la gente usualmente utiliza el protocolo ssh para empujar cambios de manera segura
al repositorio central, como se documenta en la seccion 6.5. Tambien es usual publicar una copia de solo lectura del
60
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 71/204
repositorio sobre HTTP usando CGI, como en la seccion 6.6. Publicar a traves de HTTP satisface las necesidades de
aquellos que no tienen permiso para empujar, y de aquellos que desean usar navegadores web para explorar el historial
del repositorio.
6.2.4. Trabajo con muchas ramas
Los proyectos de cierta talla tienden de manera natural a progresar de forma simultanea en varios frentes. En elcaso del software, es comun que un proyecto tenga versiones periodicas oficiales. Una version puede entrar a “modo
mantenimiento” por un tiempo despues de su primera publicacion; las versiones de mantenimiento tienden a contener
solamente arreglos de fallos, no nuevas caracterısticas. En paralelo con las versiones de mantenimiento, puede haber
una o varias versiones futuras en desarrollo. La gente usa normalmente la palabra “rama” para referirse a una de las
direcciones ligeramente distintas en las cuales avanza el desarrollo.
Mercurial esta especialmente preparado para administrar un buen numero de ramas simultaneas pero no identicas.
Cada “direccion de desarrollo” puede vivir en su propio repositorio central, y usted puede mezclar los cambios de una
a otra cuando sea necesario. Dado que los repositorios son independientes entre sı, los cambios inestables de una rama
de desarrollo nunca afectaran una rama estable a menos que alguien mezcle explıcitamente los cambios.
A continuacion hay un ejemplo de como podrıa hacerse esto en la practica. Digamos que tiene una “rama principal”
en un servidor central.
1 $ hg init main
2 $ cd main
3 $ echo ’This is a boring feature.’ > myfile
4 $ hg commit -A -m ’We have reached an important milestone!’
5 adding myfile
Alguien lo clona, hace cambios locales, los prueba, y los empuja de vuelta.
Una vez que la rama principal alcanza un hito de proyecto se puede usar la orden “ hg tag” para dar un nombre
permanente a la revision del hito.
1 $ hg tag v1.0
2 $ hg tip
3 changeset: 1:471e84684405
4 tag: tip
5 user: Bryan O’Sullivan <[email protected]>
6 date: Tue Feb 10 18:23:16 2009 +0000
7 summary: Added tag v1.0 for changeset a1e37e7a184f
8
9 $ hg tags
10 tip 1:471e84684405
11 v1.0 0:a1e37e7a184f
Digamos que en la rama principal ocurre mas desarrollo.
1 $ cd ../main
2 $ echo ’This is exciting and new!’ >> myfile
3
$ hg commit -m ’Add a new feature’4 $ cat myfile
5 This is a boring feature.
6 This is exciting and new!
Cuando se usa la etiqueta con que se identifico la version, la gente que clone el repositorio en el futuro puede usar
“hg update” para obtener una copia del directorio de trabajo igual a cuando se creo la etiqueta de la revision que se
consigno.
61
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 72/204
1 $ cd ..
2 $ hg clone -U main main-old
3 $ cd main-old
4 $ hg update v1.0
5 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
6 $ cat myfile7 This is a boring feature.
Adicionalmente, justo despues de que la rama principal se etiquete, alguien puede clonarla en el servidor a una
nueva rama “estable”, tambien en el servidor.
1 $ cd ..
2 $ hg clone -rv1.0 main stable
3 requesting all changes
4 adding changesets
5 adding manifests
6 adding file changes
7 added 1 changesets with 1 changes to 1 files
8 updating working directory9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Alguien que requiera hacer un cambio en la rama estable puede clonar ese repositorio, hacer sus cambios, consignar-
los, y empujarlos de vuelta.
1 $ hg clone stable stable-fix
2 updating working directory
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 $ cd stable-fix
5 $ echo ’This is a fix to a boring feature.’ > myfile
6 $ hg commit -m ’Fix a bug’
7 $ hg push
8 pushing to /tmp/branchingOpMbpu/stable
9 searching for changes
10 adding changesets
11 adding manifests
12 adding file changes
13 added 1 changesets with 1 changes to 1 files
Puesto que los repositorios de Mercurial son independientes, y que Mercurial no mueve los cambios de un lado a
otro automaticamente, las ramas estable y principal estan aisladas la una de la otra. Los cambios que haga en la rama
principal no se “filtran” a la rama estable y viceversa.
Es usual que los arreglos de fallos de la rama estable deban hacerse en la rama principal tambien. En lugar de
reescribir el arreglo del fallo en la rama principal, usted puede jalar y mezclar los cambios de la rama estable a la
principal, y Mercurial traera tales arreglos por usted.
1 $ cd ../main
2 $ hg pull ../stable
3 pulling from ../stable
4 searching for changes
5 adding changesets
6 adding manifests
62
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 73/204
7 adding file changes
8 added 1 changesets with 1 changes to 1 files (+1 heads)
9 (run ’hg heads’ to see heads, ’hg merge’ to merge)
10 $ hg merge
11 merging myfile
12 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
13 (branch merge, don’t forget to commit)14 $ hg commit -m ’Bring in bugfix from stable branch’
15 $ cat myfile
16 This is a fix to a boring feature.
17 This is exciting and new!
La rama principal aun contendra los cambios que no estan en la estable y contendra ademas todos los arreglos de fallos
de la rama estable. La rama estable permanece incolume a tales cambios.
6.2.5. Ramas de caracterısticas
En proyectos grandes, una forma efectiva de administrar los cambios es dividir el equipo en grupos m as pequenos.
Cada grupo tiene una rama compartida, clonada de una rama “principal” que conforma el proyecto completo. Aquellos
que trabajan en ramas individuales usualmente estan aislados de los desarrollos de otras ramas.
maestro
cripto sistemadearchivos ipc memoria red seguridad
Figura 6.1: Ramas de Caracterısticas
Cuando se considera que una caracterıstica particular esta en buena forma, alguien de ese equipo de caracterısticas jala y fusiona de la rama principal a la rama de caracterısticas y empuja de vuelta a la rama principal.
6.2.6. El tren de publicacion
Algunos proyectos se organizan al estilo“tren”: una version se planifica para ser liberada cada cierto tiempo, y las
caracterısticas que esten listas cuando ha llegado el “tren”, se incorporan.
Este modelo tiene cierta similitud a las ramas de caracterısticas. La diferencia es que cuando una caracterıstica
pierde el tren, alguien en el equipo de caracterısticas jala y fusiona los cambios que se fueron en la versi on liberada
hacia la rama de caracterıstica, y el trabajo continua sobre lo fusionado para que la caracterıstica logre estar en la
proxima version.
6.2.7. El modelo del kernel Linux
El desarrollo del kernel Linux tiene una estructura jerarquica bastante horizontal, rodeada de una nube de caos
aparente. Dado que la mayorıa de los desarrolladores de Linux usan git, una herramienta de control de versiones
distribuida con capacidades similares a Mercurial, resulta de utilidad describir la forma en que el trabajo fluye en tal
ambiente; si le gustan estas ideas, la aproximacion se traduce bien de Git a Mercurial.
En el centro de la comunidad esta Linus Torvalds, el creador de Linux. El publica un unico repositorio que es
considerado el arbol “oficial” actual por la comunidad completa de desarrolladores. Cualquiera puede clonar el arbol
de Linus, pero el es muy selectivo respecto a los arboles de los cuales jala.
63
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 74/204
Linus tiene varios “lugartenientes de confianza”. Como regla, el jala todos los cambios que ellos publican, en la
mayorıa de los casos sin siquiera revisarlos. Algunos de sus lugartenientes generalmente aceptan ser los “mantene-
dores”, responsables de subsistemas especıficos dentro del kernel. Si un hacker cualquiera desea hacer un cambio a un
subsistema y busca que termine en el arbol de Linus, debe encontrar quien es el mantenedor del subsistema y solici-
tarle que tome su cambio. Si el mantenedor revisa los cambios y esta de acuerdo en tomarlos, estos pasaran al arbol de
Linus a su debido tiempo.
Cada lugarteniente tiene su forma particular de revisar, aceptar y publicar los cambios; y para decidir cuandopresentarlos a Linus. Adicionalmente existen varias ramas conocidas que mucha gente usa para prop ositos distintos.
Por ejemplo, algunas personas mantienen repositorios “estables” de versiones anteriores del kernel, a los cuales aplican
arreglos de fallos crıticos cuando es necesario. Algunos mantenedores publican varios arboles: uno para cambios
experimentales; uno para cambios que van a ofrecer al mantenedor principal; y ası sucesivamente. Otros publican solo
un arbol.
Este modelo tiene dos caracterısticas notables. La primera es que es de “jalar exclusivamente”. Usted debe solicitar,
convencer o incluso rogar a otro desarrollador para que tome sus cambios, porque casi no hay arboles en los cuales
mas de una persona pueda publicar, y no hay forma de publicar cambios en un arbol que alguien mas controla.
La segunda es que esta basado en reputacion y meritocracia. Si usted es un desconocido, Linus probablemente
ignorara sus cambios, sin siquiera responderle. Pero el mantenedor de un subsistema probablemente los revisara, y
los acogera en caso de que aprueben su criterio de aplicabilidad. A medida que usted ofrezca “mejores” cambios a
un mantenedor, habra mas posibilidad de que se conf ıe en su juicio y se acepten los cambios. Si usted es reconocido
y mantiene una rama durante bastante tiempo para algo que Linus no ha aceptado, personas con intereses similarespueden jalar sus cambios regularmente para estar al d ıa con su trabajo.
La reputacion y meritocracia no necesariamente son transversales entre “personas” de diferentes subsistemas. Si
usted es un hacker respetado pero especializado en almacenamiento, y trata de arreglar un fallo de redes, tal cambio
puede recibir un nivel de escrutinio de un mantenedor de redes comparable con el que se le har ıa a un completo
extrano.
Personas que vienen de proyectos con un ordenamiento distinto, sienten que el proceso comparativamente caotico
del Kernel Linux es completamente lunatico. Es objeto de los caprichos individuales; la gente desecha cambios cuando
lo desea; y el ritmo de desarrollo es alucinante. A pesar de eso Linux es una pieza de software exitosa y bien reconocida.
6.2.8. Solamente jalar frente a colaboracion publica
Una fuente perpetua de discusiones en la comunidad de codigo abierto yace en la afirmacion de que el modelo de
desarrollo en el cual la gente solamente jala cambios de otros “es mejor que” uno en el cual muchas personas puedenpublicar cambios a un repositorio compartido.
Tıpicamente los partidarios del modelo de publicar usan las herramientas que se apegan a este modelo. Si usted
usa una herramienta centralizada de control de versiones como Subversion, no hay forma de elegir que modelo va a
usar: la herramienta le ofrece publicacion compartida, y si desea hacer cualquier otra cosa, va a tener que tomar una
aproximacion artificial (tal como aplicar parches a mano).
Una buena herramienta de control de versiones distribuida, tal como Mercurial, soportara los dos modelos. Usted
y sus colaboradores pueden estructurar como trabajaran juntos basados en sus propias necesidades y preferencias, sin
tener que llevar a cabo las peripecias que la herramienta les obligue a hacer.
6.2.9. Cuando la colaboracion encuentra la administracion ramificada
Una vez que usted y su equipo configuren algunos repositorios compartidos y comiencen a propagar cambios
entre sus repositorios locales y compartidos, usted comenzara a encarar un reto relacionado, pero un poco distinto:
administrar las direcciones en las cuales su equipo puede moverse. A pesar de que est a ıntimamente ligado acerca
de como interactua su equipo, este es un tema lo suficientemente denso para ameritar un tratamiento aparte, en el
capıtulo 8.
64
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 75/204
6.3. Aspectos tecnicos de la colaboracion
Lo que resta del capıtulo lo dedicamos a las cuestiones de servir datos a sus colaboradores.
6.4. Compartir informalmente con “hg serve”
La orden “hg serve” de Mercurial satisface de forma espectacular las necesidades de un grupo pequeno, acoplado
y agil. Tambien sirve como una demostracion de como se siente usar los comandos usando la red.
Ejecute “hg serve” dentro de un repositorio, y en pocos segundos se iniciara un servidor HTTP especializado;
aceptara conexiones desde cualquier cliente y servira datos de este repositorio mientras lo mantenga funcionando.
Todo el que conozca la URL del servidor que usted ha iniciado, y que pueda comunicarse con su computador a traves
de la red, puede usar un navegador web o Mercurial para leer datos del repositorio. Un URL para una instancia de “ hg
serve” ejecutandose en un portatil deberıa lucir similar a http://my-laptop.local:8000/ .
La orden “hg serve” no es un servidor web de proposito general. Solamente puede hacer dos cosas:
Permitir la visualizacion del historial del repositorio que esta sirviendo, desde un navegador web.
Hablar el protocolo de conexion de Mercurial, para que la gente pueda hacer “hg clone” o “hg pull” (jalar)
cambios desde tal repositorio.
En particular, “hg serve” no permitira que los usuarios remotos modifiquen su repositorio. Es de tipo solo lectura.
Si esta familiarizandose con Mercurial, no hay nada que le impida usar “hg serve” para servir un repositorio en
su propio computador, y posteriormente usar ordenes como “hg clone”, “hg incoming”, para comunicarse con el
servidor como si el repositorio estuviera alojado remotamente. Esto puede ayudarle a adecuarse rapidamente a usar
comandos en repositorios alojados en la red.
6.4.1. Cuestiones adicionales para tener en cuenta
Dado que permite lectura sin autenticacion a todos sus clientes, deberıa usar “hg serve” exclusivamente en am-
bientes en los cuales esto no sea importante, o en los cuales tenga control completo acerca de qui en puede acceder a
su red y jalar cambios de su repositorio.
La orden “hg serve” no tiene conocimiento acerca de programas cortafuegos que puedan estar instalados en su
sistema o en su red. No puede detectar o controlar sus cortafuegos. Si otras personas no pueden acceder a su instanciade “hg serve”, lo siguiente que deberıa hacer (despu´ es de asegurarse que tienen el URL correcto) es verificar su
configuracion de cortafuegos.
De forma predeterminada, “hg serve” escucha conexiones entrantes en el puerto 8000. Si otro proceso esta es-
cuchando en tal puerto, usted puede especificar un puerto distinto para escuchar con la opcion -p.
Normalmente, cuando se inicia “hg serve”, no muestra ningun mensaje, lo cual puede ser algo desconcertante.
Si desea confirmar que en efecto esta ejecutandose correctamente, y averiguar que URL deberıa enviar a sus colabo-
radores, inıcielo con la opcion -v.
6.5. Uso del protocolo Secure Shell (ssh)
Usted puede publicar y jalar cambios en la red de forma segura usando el protocolo Secure Shell (ssh). Para usarlo
exitosamente, tendra que hacer algo de configuracion a nivel de cliente o de servidor.Si no esta familiarizado con ssh, es un protocolo de red que le permite comunicarse de manera segura con otro
computador. Para usarlo con Mercurial, debera crear una o mas cuentas de usuario en un servidor de forma tal que los
usuarios remotos puedan entrar y ejecutar ordenes.
(Si ssh le es familiar, probablemente encontrara elemental una porcion del material a continuacion.)
65
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 76/204
6.5.1. Como leer y escribir URLs de ssh
Los URLs de ssh tienden a lucir de la siguiente forma:
1 ssh://[email protected]:22/hg/hgbook
1. La parte “ssh://” le indica a Mercurial que use el protocolo ssh.
2. El componente “bos@” indica el nombre del usuario que esta entrando al servidor. Puede omitirlo si el usuario
remoto coincide con el usuario local.
3. “hg.serpentine.com ” es el nombre del servidor al cual se desea entrar.
4. El “:22” identifica el numero del puerto en el servidor al cual se conectar a. El predeterminado es el 22, ası que
solamente necesitara especificar esa porcion si no esta usando el puerto 22.
5. La ultima porcion del URL es la ruta local del repositorio en el servidor.
El componente de la ruta del URL para ssh es una fuente de confusion, puesto que no hay una forma estandar
para que las herramientas puedan interpretarlo. Algunos programas se comportan de manera distinta a otros cuando
manipulan estas rutas. No es la situacion ideal, pero es muy poco probable que vaya a cambiar. Por favor lea los
parrafos siguientes cuidadosamente.
Mercurial trata la ruta al repositorio en el servidor como relativa al directorio personal del usuario remoto. Porejemplo, si el usuario foo en el servidor tiene el directorio personal /home/foo, entonces un URL ssh que tenga como
ruta a bar realmente se refiere al directorio /home/foo/bar.
Si desea especificar una ruta relativa a otro directorio de usuario, puede usar una ruta que comience con una
virgulilla, seguida del nombre del usuario (llamemosle otrousuario), ası
1 ssh://server/˜otheruser/hg/repo
Y si realmente desea especifica una ruta absoluta en el servidor, comience con el componente de la ruta con dos
barras, como en el siguiente ejemplo:
1 ssh://server//absolute/path
6.5.2. Encontrar un cliente ssh para su sistemaCasi todos los sistemas tipo Unix vienen con OpenSSH preinstalado. Si usted esta usando un sistema de estos, eje-
cute which ssh para identificar donde esta instalada la orden ssh (usualmente estara en /usr/bin). Si por casualidad
no esta presente, vea la documentacion de sus sistema para averiguar como instalarlo.
En Windows, primero tendra que descargar un cliente adecuado. Hay dos alternativas:
El excelente paquete PuTTY [Tat] de Simon Tatham, que ofrece un conjunto completo de ordenes de cliente
ssh.
Si tiene alta tolerancia al dolor, puede usar el porte de Cygwin para OpenSSH.
En cualquier caso, tendra que editar su fichero Mercurial.ini para indicarle a Mercurial donde encontrar la orden
real del cliente. Por ejemplo, si esta usando PuTTY, tendra que usar la orden plink como un cliente de lınea de
comandos para ssh.
1 [ui]
2 ssh = C:/ruta/a/plink.exe -ssh -i "C:/ruta/a/mi/llave/privada"
Nota: La ruta a plink no deberıa contener espacios o caracteres en blanco, o
Mercurial no podra encontrarlo correctamente (por lo tanto, probablemente no serıa
buena idea colocarlo en C:\Program Filesa
aN. del T. Ubicarlo en C:\Archivos de Programa tampoco lo serıa.
66
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 77/204
6.5.3. Generar un par de llaves
Para evitar la necesidad de teclear una clave de forma repetitiva cada vez que necesita usar el cliente, recomiendo
generar un par de llaves. En un sistema tipo Unix, la orden ssh-keygen se encargara de la tarea. En Windows, si
esta usando PuTTY, necesitara la orden puttygen.
Cuando genera un par de llaves, se aconseja comedidamente protegerlas con una frase clave. (La unica oportunidad
en la cual usted no querrıa hacerlo, es cuando esta usando el protocolo ssh para tareas automatizadas en una red segura.)
No basta con generar un par de llaves. Se requiere adicionar la llave p ublica al conjunto de llaves autorizadas
del usuario que usted usa para acceder a la maquina remota. Para aquellos servidores que usen OpenSSH (la gran
mayorıa), significara anadir la llave publica a la lista en el fichero llamado authorized keys en su directorio .ssh.
En sistemas tipo Unix, su llave publica tendra la extension .pub. Si usa puttygen en Windows, puede guardar la
llave publica en un fichero de su eleccion, o pegarla desde la ventana en la cual se despliega directamente en el fichero
authorized keys.
6.5.4. Uso de un agente de autenticacion
Un agente de autenticacion es un demonio que almacena frases clave en memoria (olvidara las frases clave si sale
de su sesion y vuelve a entrar). Un cliente ssh notara si el agente esta corriendo, y le solicitara una frase clave. Si
no hay un agente de autenticacion corriendo, o el agente no almacena la frase clave necesaria, tendr a que teclear su
frase clave cada vez que Mercurial intente comunicarse con un servidor para usted (p.e. cada vez que jale o publique
cambios).
El problema de almacenar frases claves en un agente es que es posible para un atacante bien preparado recuperar
el texto plano de su frase clave, en algunos casos incluso si su sistema ya ha sido reiniciado. Es su decisi on si es un
riesgo aceptable. Lo que sı es seguro es que evita reteclear.
En sistemas tipo Unix, el agente se llama ssh-agent, y usualmente se ejecuta automaticamente cuando usted inicia
sesion. Tendra que usar la orden ssh-add para anadir frases claves al agente. En Windows, si esta usando PuTTY, la
orden pageant actua como el agente. El anade un icono a su barra del sistema que le permitira administrar las frases
clave almacenadas.
6.5.5. Configurar el lado del servidor apropiadamente
Dado que puede ser dispendioso configurar ssh si es algo nuevo para usted, hay una variedad de cosas que podrıan ir
mal. Anada a eso Mercurial y hay mucho mas en que pensar. La mayor parte de estos problemas potenciales ocurren enel lado del servidor, no en el cliente. Las buenas noticias es que una vez tiene una configuraci on funcional, usualmente
esta continuara trabajando indefinidamente.
Antes de intentar que Mercurial hable con un servidor ssh, es mejor asegurarse de que puede usar la orden normal
ssh o putty para comunicarse primero con el servidor. Si tiene problemas usando estas ordenes directamente, de
seguro Mercurial no funcionara. Pero aun, esto escondera el problema subyacente. Cuando desee revisar un problema
relacionado con ssh y Mercurial, deberıa asegurarse primero que las ordenes de ssh en el lado del cliente funcionan
primero, antes de preocuparse por si existe un problema con Mercurial.
Lo primero para asegurar en el lado del servidor es que usted pueda iniciar sesion desde otra maquina. Si no puede
entrar usando ssh o putty, el mensaje de error que obtenga le puede dar pistas de que ha ido mal. Los problemas mas
comunes son los siguientes:
Si obtiene un error de “conexion rehusada”, es posible que no haya un demonio SSH corriendo en el servidor o
que no pueda accederse a el debido a la configuracion de cortafuegos.Si obtiene un error de “no hay ruta hasta el servidor”, puede tener una direccion incorrecta para el servidor o un
cortafuegos con bloqueo agresivo que negara la existencia del servidor.
Si obtiene un mensaje de “permiso denegado”, puede que haya tecleado mal el usuario en el servidor, o que
haya tecleado incorrectamente la frase clave de su llave o la clave del usuario remoto.
67
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 78/204
En resumen, si tiene problemas al comunicarse con el demonio ssh del servidor, primero aseg urese de que se este eje-
cutando. En muchos sistemas estara instalado, pero deshabilitado de forma predeterminada. Una vez que haya hecho
esto tendra que revisar si el cortafuegos del servidor esta configurado para recibir conexiones entrantes en el puerto
en el cual esta escuchando el demonio de ssh (usualmente el 22). No trate de buscar otras posibilidades ex oticas o
configuraciones erradas hasta que haya revisado primero estas dos.
Si esta usando un agente de autenticacion en el lado del cliente para almacenar las frase claves de sus contrasenas,
deberıa poder entrar al servidor sin necesidad de que se le soliciten frases claves o contrase nas. Si se le preguntaalguna, a continuacion algunas posibilidades:
Puede haber olvidado usar ssh-add o pageant para guardar la frase clave.
Puede haber almacenado una frase clave para una llave distinta.
Si se le solicita la clave del usuario remoto, hay otras posibilidades que deben revisarse:
O bien el directorio del usuario o su directorio .ssh tiene permisos excesivamente abiertos. Como resultado el
demonio ssh no confiara ni leera su fichero authorized keys. Por ejemplo, un directorio personal o .ssh con
permisos de escritura para grupo mostrara a veces este sıntoma.
El fichero authorized keys del usuario puede tener un problema. Si alguien distinto al usuario es dueno del
mismo o puede escribir en el fichero, el demonio ssh no confiara en el y no lo leera.
En un mundo ideal, deberıa poder ejecutar la siguiente orden exitosamente, y deberıa imprimir exactamente unalınea de salida, la fecha y hora actual.
1 ssh miservidor date
Si en su servidor tiene guion que se ejecuta a la entrada e imprime letreros o cualquier otra cosa, incluso cuando se
ejecutan ordenes no interactivas como esta, deberıa arreglarlo antes de continuar, de forma que solamente imprima algo
si se ejecuta interactivamente. De otra forma estos letreros al menos llenaran la salida de Mercurial. Incluso podrıan
causar problemas potenciales cuando se ejecuten ordenes de forma remota. Mercurial intenta detectar e ignorar los
letreros en sesiones no interactivas de ssh, pero no es a prueba de tontos. (Si edita sus guiones de entrada en el
servidor, la forma usual de ver si un guion de lınea de comandos se ejecuta en un interprete interactivo es verificar el
codigo de retorno de la orden tty -s.)
Cuando verifique que el venerado ssh funciona en su servidor, el siguiente paso es asegurarse de que Mercurial
corre en el servidor. La siguiente orden deberıa ejecutarse satisfactoriamente:
1 ssh miservidor hg version
Si ve un mensaje de error en lugar de la salida usual de “hg version”, sera porque Mercurial no fue instalado en
/usr/bin. Si este es el caso, no se preocupe; no necesita hacerlo. Pero deberıa revisar los posibles problemas:
¿Esta instalado Mercurial en el servidor? ¡Se que suena trivial pero es mejor revisar!
Tal vez la ruta de busqueda de la interfaz de ordenes (normalmente vıa la variable de entorno PATH) simplemente
esta mal configurada.
Puede ser que su variable de ambiente PATH solamente apunte al lugar en el cual esta el ejecutable hg si la sesion
de entrada es interactiva. Esto puede suceder si establece la ruta en el guion de lınea de comandos de entrada
incorrecto. Consulte la documentacion de su interprete de ordenes.
La variable de ambiente PYTHONPATH puede requerir contener la ruta a los modulos de Mercurial en Python.
Puede que ni siquiera esta establecida; podrıa estar incorrecta; o puede ser que se establezca unicamente cuando
hay entradas interactivas.
Si puede ejecutar “hg version” sobre una conexion ssh, ¡felicitaciones! Ha logrado la interaccion entre el cliente
y el servidor. Ahora deberıa poder acceder a los repositorios de Mercurial que tiene el usuario en el servidor. Si tiene
problemas con Mercurial y ssh en este punto, intente usar la opcion --debug para tener informacion mas clara de lo
que esta sucediendo.
68
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 79/204
6.5.6. Compresion con ssh
Mercurial no comprime datos cuando usa el protocolo ssh, dado que el protocolo puede comprimir datos transpar-
entemente. Pero el comportamiento predeterminado del cliente ssh es no utilizar compresion.
Sobre cualquier red distinta a una LAN rapida (incluso con una red inalambrica), hacer uso de compresion puede
mejorar el rendimiento de las operaciones de Mercurial que involucren la red. Por ejemplo, sobre WAN, alguien ha
medido que la compresion reduce la cantidad de tiempo requerido para clonar un repositorio particularmente grande
de 51 minutos a 17 minutos.
Tanto ssh como plink aceptan la opcion -C para activar la compresion. Puede editar f acilmente su hgrc para
habilitar la compresion para todos los usos de Mercurial con el protocolo ssh.
1 [ui]
2 ssh = ssh -C
Si usa ssh, puede reconfigurarlo para que siempre use compresion cuando se comunique con su servidor. Para
hacerlo, edite su fichero .ssh/config (que puede no existir aun), de la siguiente forma:
1 Host hg
2 Compression yes
3 HostName hg.ejemplo.com
Que define un alias, hg. Cuando lo usa con la orden ssh o con una URL de Mercurial con protocolo ssh, hara que
ssh se conecte a hg.ejemplo.com usando compresion. Esto le brindara un nombre mas corto para teclear, junto con
compresion, los cuales por derecho propio son buenos.
6.6. Servir sobre HTTP usando CGI
Dependiendo de que tan ambicioso sea, configurar la interfaz CGI de Mercurial puede tomar desde unos minutos
hasta varias horas.
Comenzaremos con el ejemplo mas sencillo, y nos dirigiremos hacia configuraciones mas complejas. Incluso para
el caso mas basico necesitara leer y modificar la configuracion de su servidor web.
Nota: Configurar un servidor web es una actividad compleja, engorrosa y alta-mente dependiente del sistema. De ninguna manera podremos cubrir todos los ca-
sos posibles con los cuales pueda encontrarse. Use su discrecion y juicio respecto
a las siguientes secciones. Preparese para cometer muchas equivocaciones, y em-
plear bastante tiempo leyendo las bitacoras de error de su servidor.
6.6.1. Lista de chequeo de la configuracion del servidor web
Antes de continuar, tomese un tiempo para revisar ciertos aspectos de la configuracion de su sistema:
1. ¿Tiene un servidor web? Mac OS X viene con Apache, pero otros sistemas pueden no tener un servidor web
instalado.
2. Si tiene un servidor web instalado, ¿Esta ejecutandose? En la mayorıa de sistemas, aunque este presente, puede
no estar habilitado de forma predeterminada.
3. ¿Esta configurado su servidor para permitir ejecutar programas CGI en el directorio donde planea hacerlo? Casi
todos los servidores de forma predeterminada deshabilitan explıcitamente la habilidad de ejecutar programas
CGI.
69
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 80/204
Si no tiene un servidor web instalado, y no tiene experiencia configurando Apache, deber ıa considerar usar el
servidor web lighttpd en lugar de Apache. Apache tiene una reputacion bien ganada por su configuracion barroca
y confusa. A pesar de que lighttpd tiene menos caracterısticas que Apache en ciertas areas, muchas de ellas no son
relevantes para servir repositorios de Mercurial. Y definitivamente es mucho mas sencillo comenzar con lighttpd
que con Apache.
6.6.2. Configuracion basica de CGI
En sistemas tipo Unix es comun que los usuarios tengan un subdirectorio con un nombre como public html en
su directorio personal, desde el cual pueden servir paginas web. Un fichero llamado foo en este directorio sera visible
en una URL de la forma http://www.example.com/˜username/foo .
Para comenzar, encuentre el guion hgweb.cgi que deberıa estar presente en su instalacion de Mercurial. Si no
puede encontrar rapidamente una copia local en su sistema, puede descargarlo del repositorio principal de Mercurial
en http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi.
Tendra que copiar este guion en su directorio public html, y asegurarse que sea ejecutable.
1 cp .../hgweb.cgi ˜/public_html
2 chmod 755 ˜/public_html/hgweb.cgi
El argumento 755 de la orden chmod esun pocomas general que hacerlo ejecutable: asegura que el guion sea ejecutablepor cualquiera, y que el “grupo” y los “otros” no tengan permiso de escritura. Si dejara los permisos de escritura
abiertos, el subsistema suexec de Apache probablemente se negarıa a ejecutar el guion. De hecho, suexec tambien
insiste en que el directorio en el cual reside el guion no tenga permiso de escritura para otros.
1 chmod 755 ˜/public_html
¿Que podrıa resultar mal?
Cuando haya ubicado el CGI en el sitio correspondiente, abra un navegador e intente visitar el URL http://
myhostname/˜myuser/hgweb.cgi , sin dejarse abatir por un error. Hay una alta probabilidad de que esta primera
visita al URL sea fallida, y hay muchas razones posibles para este comportamiento. De hecho, podr ıa toparse con cada
uno de los errores que describimos a continuacion, ası que no deje de leerlos cuidadosamente. A continuacion presento
los problemas que yo tuve en un sistema con Fedora 7, con una instalaci on nueva de Apache, y una cuenta de usuario
que cree especıficamente para desarrollar este ejercicio.
Su servidor web puede tener directorios por usuario deshabilitados. Si usa Apache, busque el fichero de con-
figuracion que contenga la directiva UserDir. Si no esta presente en sitio alguno, los directorios por usuario estan
deshabilitados. Si la hay, pero su valor es disabled, los directorios por usuario estaran deshabilitados. En caso con-
trario, la directiva UserDir tendra el nombre del subdirectorio bajo el cual Apache mirara en el directorio de cada
usuario, por ejemplo public html.
Los permisos de sus ficheros pueden ser demasiado restrictivos. El servidor web debe poder recorrer su directorio
personal y los directorios que esten bajo public html, ademas de tener permiso para leer aquellos que esten adentro.
A continuacion una receta rapida para hacer que sus permisos esten acordes con las necesidades basicas.
1 chmod 755 ˜
2 find ˜/public_html -type d -print0 | xargs -0r chmod 755
3 find ˜/public_html -type f -print0 | xargs -0r chmod 644
Otra posibilidad con los permisos es que obtenga una ventana completamente en blanco cuando trata de cargar
el guion. En este caso, es posible que los permisos que tiene son demasiado permisivos. El subsistema suexec de
Apache no ejecutara un guion que tenga permisos de escritura para el grupo o el planeta, por ejemplo.
Su servidor web puede estar configurado para evitar la ejecucion de programas CGI en los directorios de usuario.
A continuacion presento una configuracion predeterminada por usuario en mi sistema Fedora.
70
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 81/204
1 <Directory /home/*/public_html>
2 AllowOverride FileInfo AuthConfig Limit
3 Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
4 <Limit GET POST OPTIONS>
5 Order allow,deny
6 Allow from all7 </Limit>
8 <LimitExcept GET POST OPTIONS>
9 Order deny,allow
10 Deny from all
11 </LimitExcept>
12 </Directory>
Si encuentra un grupo de instrucciones de Directory similares en su configuracion de Apache, la directiva a revisar
es Options. Adicione ExecCGI al final de esta lista en caso de que haga falta y reinicie su servidor web.
Si resulta que Apache le muestra el texto del guion CGI en lugar de ejecutarlo, necesitara o bien descomentar (si
se encuentra presente) o adicionar una directiva como la siguiente:
1 AddHandler cgi-script .cgi
Otra posibilidad es que observe una traza de Python en colores informando que no puede importar un m odulo
relacionado con mercurial. ¡Esto es un gran progreso! El servidor es capaz de ejecutar su gui on CGI. Este error
solamente ocurrira si esta ejecutando una instalacion privada de Mercurial en lugar de una instalacion para todo el
sistema. Recuerde que el servidor que ejecuta el programa CGI no cuenta con variables de entorno de las cuales usted
sı dispone en una sesion interactiva. Si este error le ocurre, edite su copia de hgweb.cgi y siga las indicaciones dentro
del mismo para establecer de forma adecuada su variable de entorno PYTHONPATH.
Finalmente, puede que se encuentre con otra traza a todo color de Python al visitar el URL: esta seguramente
se referira a que no puede encontrar /path/to/repository 1. Edite su guion hgweb.cgi y reemplace la cadena
/path/to/repository con la ruta completa al repositorio que desea servir.
En este punto, cuando trate de recargar la pagina, debera tener una linda vista HTML del historial de su repositorio.
¡Uff!
Configuracion de lighttpd
En mi intencion de ser exhaustivo, intente configurar lighttpd, un servidor web con creciente aceptacion, para
servir los repositorios de la misma forma en que lo describı anteriormente con Apache. Ya supere los problemas que
mostre con Apache, muchos de los cuales no son especıficos del servidor. Por lo tanto estaba seguro de que mis
permisos para directorios y ficheros eran correctos y que mi guion hgweb.cgi tambien lo era.
Dado que ya Apache estaba en ejecucion correctamente, lograr que lighttpd sirviera mi repositorio fue rapido (en
otras palabras, si esta tratando de usar lighttpd, debera leer la seccion de Apache). Primero tuve que editar la seccion
mod access para habilitar mod cgi y mod userdir, los cuales estaban inhabilitados en mi instalacion predeterminada.
Anadı posteriormente unas lıneas al final del fichero de configuracion, para hacer lo propio con los modulos.
1 userdir.path = "public_html"
2 cgi.assign = ( ".cgi" => "" )
Hecho esto, lighttpd funciono inmediatamente para mı. Si hubiera configurado lighttpd antes que Apache, habrıa
tenido casi los mismos problemas a nivel de configuracion del sistema que con Apache. De todas maneras, considero
que lighttpd es bastante mas sencillo de configurar que Apache, a pesar de haber usado Apache por lo menos por
una decada, y de que esta fue mi primera experiencia con lighttpd.
1N. del T. Ruta al repositorio.
71
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 82/204
6.6.3. Compartir varios repositorios con un guion CGI
El guion hgweb.cgi permite publicar unicamente un repositorio, una restriccion frustrante. Si desea publicar mas
de uno sin complicarse con varias copias del mismo guion, cada una con un nombre distinto, resulta mucho mejor usar
el guion hgwebdir.cgi.
El procedimiento para configurar hgwebdir.cgi tiene una porcion adicional respecto al trabajo requerido con
hgweb.cgi. Primero se debe obtener una copia del guion. Si no tiene una a mano, puede descargarla del ftp principal
del repositorio de Mercurial en http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi.
Necesitara una copia del guion en su directorio public html, y debe asegurarse de que tenga permisos de ejecu-
cion.
1 cp .../hgwebdir.cgi ˜/public_html
2 chmod 755 ˜/public_html ˜/public_html/hgwebdir.cgi
Con la configuracion basica, intente visitar en su navegador http://myhostname/ ˜myuser/hgwebdir.cgi . Deberıa
mostrar una lista vacıa de repositorios. Si obtiene una ventana en blanco o un mensaje de error, verifique la lista de
problemas potenciales en la seccion 6.6.2.
El guion hgwebdir.cgi se apoya en un fichero externo de configuracion. De forma predeterminada, busca un
fichero llamado hgweb.config en el mismo directorio. Tendra que crear el fichero, y permitir lectura de todo el
mundo. El formato del fichero es similar a un fichero “ini” de Windows, que puede ser interpretado por el m odulo
ConfigParser [Pyt] de Python.
La forma mas sencilla de configurar hgwebdir.cgi es mediante una seccion llamada collections. Esta pub-
licara automaticamente todos los repositorios en los directorios que usted especifique. La secci on deberıa lucir ası:
1 [collections]
2 /mi/ruta = /mi/ruta
Mercurial lo interpreta buscando el nombre del directorio que este a la derecha del sımbolo “=”; ubicando repositorios
en la jerarquıa de directorios; y usando el texto a la izquierda para eliminar el texto de los nombres que mostrara en la
interfaz web. El componente restante de la ruta despues de esta eliminacion usualmente se llama “ruta virtual”.
Dado el ejemplo de arriba, si tenemos un repositorio cuya ruta local es /mi/ruta/este/repo , el guion CGI
eliminara la porcion inicial /mi/ruta del nombre y publicara el repositorio con una ruta virtual este/repo. Si el
URL base de nuestro guion CGI es http://myhostname/ ˜myuser/hgwebdir.cgi , el URL completo al repositoriosera http://myhostname/ ˜myuser/hgwebdir.cgi/this/repo .
Si reemplazamos /mi/ruta en el lado izquierdo de este ejemplo con /mi, hgwebdir.cgi eliminara solamente
/mi del nombre del repositorio, y nos ofrecera la ruta virtual ruta/este/repo en lugar de este/repo.
El guion hgwebdir.cgi buscara recursivamente en cada directorio listado en la seccion collections de su fichero
de configuracion, pero no hara el recorrido recursivo dentro de los repositorios que encuentre.
El mecanismo de collections permite publicar facilmente repositorios de una forma “hacer y olvidar”. Sola-
mente requiere configurar el guion CGI y el fichero de configuracion una vez. Despues de eso puede publicar y sacar
de publicacion un repositorio en cualquier momento incluyendolo o excluyendolo de la jerarquıa de directorios en la
cual le haya indicado a hgwebdir.cgi que mirase.
Especificacion explıcita de los repositorios a publicar
Ademas del mecanismo collections, el guion hgwebdir.cgi le permite publicar una lista especıfica de reposi-torios. Para hacerlo, cree una seccion paths, con los contenidos de la siguiente forma:
1 [paths]
2 repo1 = /mi/ruta/a/un/repo
3 repo2 = /ruta/a/otro/repo
72
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 83/204
En este caso, la ruta virtual (el componente que aparecera en el URL) esta en el lado derecho de cada definicion,
mientras que la ruta al repositorio esta a la derecha. Note que no tiene que haber relacion alguna entre la ruta virtual
que elija y el lugar del repositorio en su sistema de ficheros.
Si lo desea, puede usar tanto collections como paths simultaneamente en un solo fichero de configuracion.
Nota: Si varios repositorios tienen la misma ruta virtual, hgwebdir.cgi no repor-
tara ningun error. Pero se comportara de manera impredecible.
6.6.4. Descarga de ficheros fuente
La interfaz web de Mercurial permite a los usuarios descargar un conjunto de cualquier revision. Este conjunto
contendra una replica del directorio de trabajo en la revision en cuestion, pero no contendra una copia de los datos del
repositorio.
Esta caracterıstica no esta habilitada de forma predeterminada. Para habilitarla adicione un allow archive a la
seccion [web] de su fichero hgrc.
6.6.5. Opciones de configuracion en Web
Las interfaces web de Mercurial (la orden “hg serve”, y los guiones hgweb.cgi y hgwebdir.cgi) tienen varias
opciones de configuracion disponibles. Todas ellas van en la seccion [web].
allow archive Determina que mecanismos de descarga soportara Mercurial. Si habilita esta caracterıstica, los usuarios de
la interfaz web podran descargar una copia de la revision del repositorio que esten viendo. Para activar la
caracterıstica de descarga de conjunto, el valor tendra una secuencia de palabras extraıdas de la lista de abajo.
bz2 Un fichero tar con el metodo de compresion bzip2. Tiene la mejor tasa de compresion, pero usa mas
tiempo de procesamiento en el servidor.
gz Un fichero tar, comprimido con gzip.
zip Un fichero zip, comprimido con LZW. Este formato posee la peor tasa de compresi on, pero es muy usado
en el mundo Windows.
Si da una lista vacıa o no tiene la entrada allow archive, esta caracterıstica se deshabilitara. A continuacion se
presenta un ejemplo de como habilitar los tres formatos soportados.
1 [web]
2 allow_archive = bz2 gz zip
allowpull Booleano. Determina si la interfaz web permite a los usuarios remotos emplear “ hg pull” y “hg clone” sobre
el repositorio HTTP. Si se coloca no o false, solamente se habilita la porcion de los procesos “orientados-a-
humanos” de la interfaz web.
contact Cadena. Una cadena en forma libre (pero preferiblemente corta) que identifica a la persona o grupo a cargo
del repositorio. Usualmente contiene el nombre y la direcci on de correo electronico de una persona o de una
lista de correo. A veces tiene sentido colocar esta opcion en el fichero .hg/hgrc del repositorio, pero en otras
oportunidades es mejor hacerlo en el hgrc global si todos los repositorios tienen un unico mantenedor.
maxchanges Entero. La cantidad maxima de conjuntos de cambios a mostrar de forma predeterminada en cada pagina.
maxfiles Entero. La cantidad maxima predeterminada de ficheros modificados a desplegar en una p agina.
stripes Entero. Si la interfaz web despliega “franjas” para facilitar la visualizaci on alineada de filas cuando se ve una
tabla, este valor controla la cantidad de filas en cada franja.
style Controla la plantilla que Mercurial usa para desplegar la interfaz web. Mercurial viene con dos plantillas web,
llamadas default y gitweb (La primera es mas atractiva visualmente). Puede especificar una plantilla propia;
consulte el capıtulo 11. A continuacion mostramos como habilitar el estilo gitweb.
73
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 84/204
1 [web]
2 style = gitweb
templates Ruta. Directorio en el que se buscaran los ficheros plantilla. De forma predeterminada, el guion busca en el
directorio en el cual fue instalado.
Si usa hgwebdir.cgi, puede anadir otras opciones de configuracion en la seccion [web] del fichero hgweb.config
en lugar del fichero hgrc si lo considera mas conveniente. Estas opciones son motd y style.
Opciones especıficas para repositorios individuales
Ciertas opciones de configuracion de [web] deben estar ubicadas en el .hg/hgrc de un repositorio en lugar del
fichero del usuario o el hgrc global.
description Cadena. Una cadena de forma libre (preferiblemente corta) que describa los contenidos o el proposito del repos-
itorio.
name Cadena. El nombre para visualizar en la interfaz web del repositorio. Sustituye el nombre predeterminado, el
cual es el ultimo componente de la ruta del repositorio.
Opciones especıficas a la orden “hg serve”
Algunas opciones en la seccion [web] de un fichero hgrc son de uso exclusivo de la orden “hg serve”.
accesslog Ruta. El nombre del fichero en el cual se escribe la bit acora de acceso. En principio, la orden “hg serve”
escribe esta informacion a la salida estandar, no a un fichero. Las l ıneas de la bitacora se escriben en un formato
de fichero “combinado” estandar, usado por casi todos los servidores web.
address Cadena. La direccion local en la cual el servidor debe escuchar peticiones entrantes. De forma predeterminada,
el servidor escucha en todas las direcciones.
errorlog Ruta. El nombre de un fichero en el cual escribir la bitacora de error. En principio, la orden “hg serve” escribe
esta informacion en la salida de error estandar, no a un fichero.
ipv6 Booleano. Si se usa o no el protocolo IPv6. IPv6 no se usa de manera predeterminada.
port Entero. El numero del puerto TCP en el cual el servidor esperara conexiones. El puerto predeterminado es
el 8000.
Elegir el fichero hgrc correcto para las configuraciones de [web]
Es importante recordar que un servidor web como Apache o lighttpd se ejecutara bajo un ID de usuario que
generalmente no es el suyo Los guiones CGI ejecutados por su servidor, tales como hgweb.cgi, se ejecutaran tambien
con ese ID de usuario.
Si anade opciones [web] a su fichero personal hgrc los guiones CGI no leeran tal fichero hgrc. Tales configu-
raciones solamente afectaran el comportamiento de la orden “hg serve” cuando usted la ejecuta. Para logar que los
guiones CGI vean sus configuraciones, o bien cree un fichero hgrc en el directorio personal del usuario bajo cuyo ID
se ejecuta su servidor web, o anada tales opciones al fichero global hgrc.
74
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 85/204
Capıtulo 7
Nombres de ficheros y asociacion de
patrones
Mercurial provee mecanismos que le permiten trabajar con nombres de ficheros en una manera consistente y
expresiva.
7.1. Nombrado de ficheros simple
Mercurial usa un mecanismo unificado “bajo el capo” para manejar nombres de ficheros. Cada comando se com-
porta de manera uniforme con respecto a los nombres de fichero. La manera en que los comandos operan con nombres
de fichero es la siguiente.
Si usted especifica explıcitamente nombres reales de ficheros en la lınea de comandos, Mercurial opera unicamente
sobre dichos ficheros, como usted esperarıa.
1 $ hg add COPYING README examples/simple.py
Cuando usted provee el nombre de un directorio, Mercurial interpreta eso como “opere en cada fichero en este di-
rectorio y sus subdirectorios”. Mercurial va por todos los ficheros y subdirectorios de un directorio en orden alfabetico.Cuando encuentra un subdirectorio, lo recorrera antes de continuar con el directorio actual.
1 $ hg status src
2 ? src/main.py
3 ? src/watcher/_watcher.c
4 ? src/watcher/watcher.py
5 ? src/xyzzy.txt
7.2. Ejecucion de comandos sin ningun nombre de fichero
Los comandos de Mercurial que trabajan con nombres de fichero tienen comportamientos por defecto adecuados
cuando son utilizados sin pasar ningun patron o nombre de fichero. El tipo de comportamiento depende de lo que
haga el comando. Aquı presento unas cuantas reglas generales que usted puede usar para que es lo que probablemente
hara un comando si usted no le pasa ningun nombre de fichero con el cual trabajar.
Muchos comandos operaran sobre el directorio de trabajo completo. Por ejemplo, esto es lo que hace el comando
“hg add”,
75
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 86/204
Si el comando tiene efectos dif ıciles o incluso imposibles de revertir, se le obligara a usted a proveer explıcita-
mente al menos un nombre o patron (ver mas abajo). Esto lo proteje a usted de, por ejemplo, borrar ficheros
accidentalmente al ejecutar “hg remove” sin ningun argumento.
Es f acil evitar este comportamiento por defecto, si no es el adecuado para usted. Si un comando opera normalmente
en todo el directorio de trabajo, usted puede llamarlo para que trabaje solo en el directorio actual y sus subdirectorio
pasandole el nombre “.”.
1 $ cd src
2 $ hg add -n
3 adding ../MANIFEST.in
4 adding ../examples/performant.py
5 adding ../setup.py
6 adding main.py
7 adding watcher/_watcher.c
8 adding watcher/watcher.py
9 adding xyzzy.txt
10 $ hg add -n .
11 adding main.py
12 adding watcher/_watcher.c
13 adding watcher/watcher.py
14 adding xyzzy.txt
Siguiendo la misma lınea, algunos comandos normalmente imprimen las rutas de ficheros con respecto a la ra ız del
repositorio, aun si usted los llama dentro de un subdirectorio. Dichos comandos imprimiran las rutas de los ficheros
respecto al directorio en que usted se encuentra si se les pasan nombres expl ıcitos. Vamos a ejecutar el comando “hg
status” desde un subdirectorio, y a hacer que opere en el directorio de trabajo completo, a la vez que todas las rutas
de ficheros se imprimen respecto a nuestro subdirectorio, pasandole la salida del comando “hg root”.
1 $ hg status
2 A COPYING
3 A README
4 A examples/simple.py5 ? MANIFEST.in
6 ? examples/performant.py
7 ? setup.py
8 ? src/main.py
9 ? src/watcher/_watcher.c
10 ? src/watcher/watcher.py
11 ? src/xyzzy.txt
12 $ hg status ‘hg root‘
13 A ../COPYING
14 A ../README
15 A ../examples/simple.py
16 ? ../MANIFEST.in
17 ? ../examples/performant.py18 ? ../setup.py
19 ? main.py
20 ? watcher/_watcher.c
21 ? watcher/watcher.py
22 ? xyzzy.txt
76
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 87/204
7.3. Reportar que esta pasando
El ejemplo con el comando “hg add” en la seccion anterior ilustra algo mas que es util acerca de los comandos de
Mercurial. Si un comando opera en un fichero que usted no paso explıcitamente en la lınea de comandos, usualmente
se imprimira el nombre del fichero, para que usted no sea sorprendido por lo que sucede.
Esto es el principio de m´ ınima sorpresa. Si usted se ha referido explıcitamente a un fichero en la lınea de comandos,
no tiene mucho sentido repetir esto de vuelta a usted. Si Mercurial est a actuando en un fichero impl´ ıcitamente, porqueusted no paso nombres, ni directorios, ni patrones (ver masabajo), lo mas seguro es decirle a usted que se esta haciendo.
Usted puede silenciar a los comandos que se comportan de esta manera usando la opcion -q. Tambien puede hacer
que impriman el nombre de cada fichero, aun aquellos que usted indico explıcitamente, usando la opcion -v.
7.4. Uso de patrones para identificar ficheros
Ademas de trabajar con nombres de ficheros y directorios, Mercurial le permite usar patrones para identificar
ficheros. El manejo de patrones de Mercurial es expresivo.
En sistemas tipo Unix (Linux, MacOS, etc.), el trabajo de asociar patrones con nombres de ficheros recae sobre el
interprete de comandos. En estos sistemas, usted debe indicarle expl ıcitamente a Mercurial que el nombre que se le
pasa es un patron. En Windows, el interprete no expande los patrones, ası que Mercurial identificara automaticamente
los nombres que son patrones, y hara la expansion necesaria.Para pasar un patron en vez de un nombre normal en la lınea de comandos, el mecanismo es simple:
1 syntax:patternbody
Un patron es identificado por una cadena de texto corta que indica que tipo de patron es, seguido por un dos puntos,
seguido por el patron en sı.
Mercurial soporta dos tipos de sintaxis para patrones. La que se usa con mas frecuencia se denomina glob1; es el
mismo tipo de asociacion de patrones usado por el interprete de Unix, y tambien deberıa ser familiar para los usuarios
de la lınea de comandos de Windows.
Cuando Mercurial hace asociacion automatica de patrones en Windows, usa la sintaxis glob. Por esto, usted puede
omitir el prefijo “glob:” en Windows, pero tambien es seguro usarlo.
La sintaxis re2 es mas poderosa; le permite especificar patrones usando expresiones regulares, tambi en conocidas
como regexps.A proposito, en los ejemplos siguientes, por favor note que yo tengo el cuidado de rodear todos mis patrones con
comillas sencillas, para que no sean expandidos por el interprete antes de que Mercurial pueda verlos.
7.4.1. Patrones glob estilo interprete
Este es un vistazo general de los tipos de patrones que usted puede usar cuando est a usando asociacion con patrone
glob.
La secuencia “*” se asocia con cualquier cadena, dentro de un unico directorio.
1 $ hg add ’glob:*.py’
2 adding main.py
La secuencia “**” se asocia con cualquier cadena, y cruza los l ımites de los directorios. No es una elementoestandar de los tokens de glob de Unix, pero es aceptado por varios int erpretes Unix populares, y es muy util.
1 $ cd ..
2 $ hg status ’glob:**.py’
1N. del T. Grupo, coleccion, aglomeracion.2N. del T. Expresiones regulares.
77
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 88/204
3 A examples/simple.py
4 A src/main.py
5 ? examples/performant.py
6 ? setup.py
7 ? src/watcher/watcher.py
La secuencia “?” se asocia con cualquier caracter sencillo.
1 $ hg status ’glob:**.?’
2 ? src/watcher/_watcher.c
El caracter “[” marca el inicio de una clase de caracteres. Ella se asocia con cualquier caracter sencillo dentro de
la clase. La clase se finaliza con un caracter “]”. Una clase puede contener multiples rangos de la forma “a-f”, que
en este caso es una abreviacion para “abcdef”.
1 $ hg status ’glob:**[nr-t]’
2 ? MANIFEST.in
3 ? src/xyzzy.txt
Si el primer caracter en aparecer despues de “[” en la clase de caracteres es un “!”, se niega la clase, haciendo que seasocie con cualquier caracter sencillo que no se encuentre en la clase.
Un “{” marca el inicio de un grupo de subpatrones, en donde todo el grupo es asociado si cualquier subpatron en
el grupo puede ser asociado. El caracter “,” separa los subpatrones, y el “}” finaliza el grupo.
1 $ hg status ’glob:*.{in,py}’
2 ? MANIFEST.in
3 ? setup.py
Cuidado!
No olvide que si usted desea asocia un patron con cualquier directorio, no deberıa usar el elemento para asociar
con cualquier cadena “*”, ya que este solo generara asociaciones dentro de un solo directorio. En vez de eso, use el
caracter para asociar con cualquier cadena “**”. Este pequeno ejemplo ilustra la diferencia entre los dos.
1 $ hg status ’glob:*.py’
2 ? setup.py
3 $ hg status ’glob:**.py’
4 A examples/simple.py
5 A src/main.py
6 ? examples/performant.py
7 ? setup.py
8 ? src/watcher/watcher.py
7.4.2. Asociacion con patrones de expresiones regulares re
Mercurial acepta la misma sintaxis para expresiones regulares del lenguaje de programacion Python (internamente
se usa el motor de expresiones regulares de Python). Esta sintaxis est a basada en la misma del lenguaje Perl, que es el
dialecto mas popular en uso (por ejemplo, tambien se usa en Java).
No discutire el dialecto de expresiones regulares de Mercurial en detalle aquı, ya que las mismas no son usadas
frecuentemente. Las expresiones regulares al estilo Perl se encuentran documentadas exhaustivamente en una multitud
de sitios web, y en muchos libros. En vez de eso, me enfocare en unas cuantas cosas que usted deberıa conocer si tiene
la necesidad de usar expresiones regulares en Mercurial.
78
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 89/204
Una expresion regular es comparada contra un nombre de fichero completo, relativo a la ra ız del repositorio. En
otras palabras, aun si usted se encuentra en un subdirectorio foo, si desea asociar ficheros en este directorio, su patron
debe empezar con “foo/”.
Un detalle a tener en cuenta es que, si le son familiares las expresiones regulares al estilo Perl, las de Mercurial
estan enraızadas. Esto es, que la asociacion de una expresion se hace desde el inicio de la cadena; no se buscan
coincidencias dentro de la cadena. Para buscar coincidencias en cualquier sitio dentro de una cadena, empiece su
patron con un “.*”.
7.5. Filtrado de ficheros
Mercurial no solo le provee una variedad de formas para especificar ficheros; le permite limitar aun mas dichos
ficheros mediante el uso de filtros. Los comandos que operan con nombres de fichero aceptan dos opciones de filtrado.
-I, o --include, le permite especificar un patron con el que deben coincidir los ficheros para ser procesados.
-X, o --exclude, le brinda una manera de evitar procesar ficheros, si coinciden con este patron.
Usted puede pasar multiples veces las opciones -I y -X en la lınea de comandos, e intercalarlos como desee. Por
defecto, Mercurial interpreta los patrones que usted pase usando la sintaxis glob (pero usted puede usar expresiones
regulares si lo necesita).El filtro -I puede verse como un “procese todos los ficheros que coincidan con este filtro”.
1 $ hg status -I ’*.in’
2 ? MANIFEST.in
El filtro -X puede verse como “procese unicamente los ficheros que no coincidan con este patron”.
1 $ hg status -X ’**.py’ src
2 ? src/watcher/_watcher.c
3 ? src/xyzzy.txt
7.6. Ignorar ficheros y directorios no deseados
XXX.
7.7. Sensibilidad a mayusculas
Si usted esta trabajando en un ambiente de desarrollo mixto que contiene tanto sistemas Linux (u otro Unix) y
sistemas Mac o Windows, deberıa tener en mente el hecho de que ellos tratan case (“N” versus “n”) of file names in
incompatible ways. This is not very likely to affect you, and it’s easy to deal with if it does, but it could surprise you
if you don’t know about it.
Operating systems and filesystems differ in the way they handle the case of characters in file and directory names.
There are three common ways to handle case in names.
Completely case insensitive. Uppercase and lowercase versions of a letter are treated as identical, both when
creating a file and during subsequent accesses. This is common on older DOS-based systems.
Case preserving, but insensitive. When a file or directory is created, the case of its name is stored, and can be
retrieved and displayed by the operating system. When an existing file is being looked up, its case is ignored.
This is the standard arrangement on Windows and MacOS. The names foo and FoO identify the same file. This
treatment of uppercase and lowercase letters as interchangeable is also referred to as case folding.
79
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 90/204
Case sensitive. The case of a name is significant at all times. The names foo and FoO identify different files.
This is the way Linux and Unix systems normally work.
On Unix-like systems, it is possible to have any or all of the above ways of handling case in action at once. For
example, if you use a USB thumb drive formatted with a FAT32 filesystem on a Linux system, Linux will handle
names on that filesystem in a case preserving, but insensitive, way.
7.7.1. Almacenamiento portable y seguro de repositorios
El mecanismo de almacenamiento de los repositorios en Mercurial es robusto frente a sensibilidad/insensibilidad
a may´ usculas. Los nombres de fichero son traducidos para que puedan ser almacenados de manera segura tanto en
sistemas sensibles como insensibles a mayusculas. Esto significa que usted puede usar herramientas normales de
copia de ficheros para transferir un repositorio Mercurial a, por ejemplo, una memoria USB, y trasladar de manera
segura la memoria y el repositorio de ida y vuelta entre un Mac, un PC ejecutando Windows, y un sistema Linux
7.7.2. Deteccion de conflictos de mayusculas/minusculas
Al operar en el directorio de trabajo, Mercurial respeta la pol ıtica de nombrado del sistema de ficheros en que
se encuentre el directorio de trabajo. Si el sistema de ficheros conserva las diferencias entre may usculas, pero no es
sensible a ellas, Mercurial tratara los nombres que solo difieren en mayusculas como uno solo y el mismo.Un aspecto importante de este enfoque es que es posible consignar un conjunto de cambios en un sistema de
ficheros sensible a mayusculas (tıpicamente Linux o Unix) que terminara causando problemas para usuarios en sis-
temas insensibles a mayusculas (usualmente en Windows o MacOS). Si un usuario de Linux consigna cambios a dos
ficheros, uno de ellos llamado myfile.c y el otro llamado MyFile.C, ambos seran almacenados correctamente en
el repositorio. Y seran representados correctamente como ficheros separados, en los directorios de trabajo de otros
usuarios de Linux.
Si un usuario de Windows o Mac jalan este cambio, no tendran problemas inicialmente, porque el mecanismo de
almacenamiento de Mercurial es seguro frente a sensibilidad/insensibilidad a mayusculas. Sin embargo, una vez que
ellos traten de actualizar (“hg update”) el directorio de trabajo con ese conjunto de cambios, o hagan fusion (“hg
merge”) con ese conjunto de cambios, Mercurial vera el conflicto entre los dos nombres de fichero que el sistema de
ficheros tratarıa como el mismo, e impedira que ocurra la actualizacion o fusion.
7.7.3. Arreglar un conflicto de mayusculas/minusculas
Si usted esta usando Windows o Mac en un entorno mixto donde algunos de sus colaboradores est an usando Linux
o Unix, y Mercurial reporta un conflicto de mayusculas/minusculas cuando usted trata de actualizar (“hg update”) o
fusionar (“hg merge”), el procedimiento para arreglar el problema es simple.
Solo busque un sistema Linux o Unix cercano, clone el repositorio problema all ı, y use el comando “hg rename”
de Mercurial para cambiar los nombres de cualquiera de los ficheros o directorios problematicos para que no causen
mas conflictos. Consigne este cambio, y jalelo (“hg pull”) o empujelo (“hg push”) a su sistema Windows o MacOS,
y actualıcelo (“hg update”) a la revision con los nombres que ya no generan conflictos.
El conjunto de cambios con los nombres con conflictos de may usculas/minusculas permanecera en el historial de
su proyecto, y usted no podra actualizar (“hg update”) su directorio de trabajo a dicho conjunto de cambios en un
sistema Windows o MacOS, pero puede continuar el desarrollo sin impedimentos.
Nota: Antes de la version 0.9.3, Mercurial no usaba un mecanismos seguro frente
a sensibilidad/insensibilidad a mayusculas o minusculas, y no detectaba los con-flictos con nombres de ficheros. Si usted esta usando una version mas antigua de
Mercurial en Windows o MacOS, le recomiendo energicamente que se actualice.
80
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 91/204
Capıtulo 8
Administracion de versiones y desarrollo
ramificado
Mercurial ofrece varios mecanismos que le permiten administrar un proyecto que avanza en multiples frentes
simultaneamente. Para entender estos mecanismos, demos un vistazo a la estructura usual de un proyecto de software.
Muchos proyectos de software liberan una version “mayor” que contiene nuevas caracterısticas substanciales. En
paralelo, pueden liberar versiones “menores”. Usualmente estas son identicas a las versiones mayores en las cuales
estan basadas, pero con arreglos para algunos fallos.
En este capıtulo, comenzaremos hablando de como mantener registro de etapas del proyecto como las liberaciones
de una version. Continuaremos hablando del flujo de trabajo entre las diferentes fases de un proyecto, y como puede
ayudar Mercurial a aislar y administrar tal trabajo.
8.1. Dar un nombre persistente a una revision
Cuando usted decide otorgar a una revision el nombre particular de una “version”, es buena idea grabar la identidad
de tal revision. Esto le permitira reproducir dicha version en una fecha posterior, para cualquiera que sea el proposito
que se tenga en ese momento (reproducir un fallo, portar a una nueva plataforma, etc).
1 $ hg init mytag
2 $ cd mytag
3 $ echo hello > myfile
4 $ hg commit -A -m ’Initial commit’
5 adding myfile
Mercurial le permite dar un nombre permanente a cualquier revision usando la orden “hg tag”. Sin causa de
sorpresa, esos nombres se llaman “tags” (etiquetas).
1 $ hg tag v1.0
Una etiqueta no es mas que un “nombre simbolico” para una revision. Las etiquetas existen unicamente para su
conveniencia, brindandole una forma permanente y sencilla de referirse a una revision; Mercurial no interpreta de
ninguna manera los nombres de las etiquetas que usted use. Mercurial tampoco impone restriccion alguna al nombre
de una etiqueta, mas alla de lo necesario para asegurar que una etiqueta pueda procesarse sin ambiguedades. El nombre
de una etiqueta no puede tener ninguno de los siguientes caracteres:
Dos puntos (ASCII 58, “:”)
Retorno de carro (return) (ASCII 13, “\r”)
81
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 92/204
Nueva lınea (ASCII 10, “\n”)
Puede usar la orden “hg tags” para ver las etiquetas presentes en su repositorio. Al desplegarse, cada revision
marcada se identifica primero con su nombre, despues con el numero de revision y finalmente con un hash unico de la
revision.
1 $ hg tags
2 tip 1:515e5c86f4963 v1.0 0:1d3fd3640aaa
Note que tip aparece en en listado generado por “hg tags”. La etiqueta tip es una etiqueta “flotante” especial, que
identifica siempre la revision mas reciente en el repositorio.
Al desplegar la orden “hg tags”, las etiquetas se listan en orden inverso, por numero de revision. Lo que significa
usualmente que las etiquetas mas recientes se listan antes que las mas antiguas. Tambien significa que la etiqueta tip
siempre aparecera como primera etiqueta listada al desplegar la orden “hg tags”.
Cuando usted ejecuta “hg log”, si se muestra una revision que tenga etiquetas asociadas a ella, se imprimiran
tales etiquetas.
1 $ hg log
2 changeset: 1:515e5c86f496
3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:29 2009 +0000
6 summary: Added tag v1.0 for changeset 1d3fd3640aaa
7
8 changeset: 0:1d3fd3640aaa
9 tag: v1.0
10 user: Bryan O’Sullivan <[email protected]>
11 date: Tue Feb 10 18:23:29 2009 +0000
12 summary: Initial commit
13
Siempre que requiera indicar un ID de revision a una orden de Mercurial, aceptara un nombre de etiqueta en sulugar. Internamente, Mercurial traducira su nombre de etiqueta en el ID de revisi on correspondiente, y lo usara.
1 $ echo goodbye > myfile2
2 $ hg commit -A -m ’Second commit’
3 adding myfile2
4 $ hg log -r v1.0
5 changeset: 0:1d3fd3640aaa
6 tag: v1.0
7 user: Bryan O’Sullivan <[email protected]>
8 date: Tue Feb 10 18:23:29 2009 +0000
9 summary: Initial commit
10
No hay lımites en la cantidad de etiquetas por repositorio, o la cantidad de etiquetas que una misma revisi on pueda
tener. Siendo practicos, no es muy buena idea tener “demasiadas” (la cantidad variar a de un proyecto a otro), debido a
que la intencion es ayudarle a encontrar revisiones. Si tiene demasiadas etiquetas, la facilidad de usarlas para identificar
revisiones disminuira rapidamente.
Por ejemplo, si su proyecto tiene etapas (milestones) frecuentes, de pocos d ıas, es perfectamente razonable asig-
narle una etiqueta a cada una de ellas. Pero si tiene un sistema de construccion automatica de binarios que asegura
82
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 93/204
que cada revision puede generarse limpiamente, estarıa introduciendo mucho ruido si se usara una etiqueta para ca-
da generacion exitosa. Mas bien, podrıa usar tags para generaciones fallidas (¡en caso de que estas sean raras!), o
simplemente evitar las etiquetas para llevar cuenta de la posibilidad de generacion de binarios.
Si quiere eliminar una etiqueta que no desea, use “hg tag --remove”.
1 $ hg tag --remove v1.0
2 $ hg tags
3 tip 3:31eda97c4db9
Tambien puede modificar una etiqueta en cualquier momento, para que identifique una revision distinta, simplemente
usando una nueva orden “hg tag”. Debera usar la opcion -f para indicarle a Mercurial que realmente desea actualizar
la etiqueta.
1 $ hg tag -r 1 v1.1
2 $ hg tags
3 tip 4:eb33d1c642f4
4 v1.1 1:515e5c86f496
5 $ hg tag -r 2 v1.1
6 abort: tag ’v1.1’ already exists (use -f to force)
7 $ hg tag -f -r 2 v1.1
8 $ hg tags9 tip 5:b26c4daf4a9d
10 v1.1 2:55d99d62d333
De todas maneras habra un registro permanente de la antigua identidad de la etiqueta, pero Mercurial no la usara.
Por lo tanto no hay problema al marcar con una etiqueta una revision incorrecta; lo unico que debe hacer es mover la
etiqueta hacia la revision correcta tan pronto como localice el error.
Mercurial almacena las etiquetas en un fichero controlado por revisiones en su repositorio. Si ha creado etiquetas,
las encontrara en un fichero llamado .hgtags. Cuando invoca la orden “hg tag”, Mercurial modifica este fichero,
y hace la consignacion del cambio al mismo automaticamente. Esto significa que cada vez que ejecuta “hg tag”,
vera un conjunto de cambios correspondiente en la salida de “hg log”.
1 $ hg tip
2 changeset: 5:b26c4daf4a9d3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:30 2009 +0000
6 summary: Added tag v1.1 for changeset 55d99d62d333
7
8.1.1. Manejo de conflictos entre etiquetas durante una fusion
Usualmente no tendra que preocuparse por el fichero .hgtags, pero a veces hace su aparicion durante una fusion.
El formato del fichero es sencillo: Consiste de una serie de l ıneas. Cada lınea comienza con un hash de conjunto de
cambios, seguido por un espacio, seguido por el nombre de una etiqueta.
Si esta resolviendo un conflicto en el fichero .hgtags durante una fusion, hay un detalle para tener en cuenta almodificar el fichero .hgtags: cuando Mercurial procesa las etiquetas en el repositorio, nunca lee la copia de trabajo
del fichero .hgtags. En cambio, lee la version consignada m´ as reciente del fichero.
Una consecuencia desafortunada de este diseno es que usted no puede verificar que su fichero .hgtags fusion-
ado sea correcto hasta despu´ es de haber consignado un cambio. Ası que si se encuentra resolviendo un conflicto en
.hgtags durante una fusion, asegurese de ejecutar la orden “hg tags” despues de consignar. Si encuentra un error
en el fichero .hgtags, la orden reportara el lugar del error, que podra arreglar y despues consignar. Posteriormente
ejecute de nuevo la orden “hg tags” para asegurarse de que su arreglo fue aplicado correctamente .
83
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 94/204
8.1.2. Etiquetas y clonado
Puede haber notado que la orden “hg clone” tiene la opcion -r que le permite clonar una copia exacta del
repositorio hasta un conjunto de cambios especıfico. El nuevo clon no tendra historial posterior a la revision que usted
haya especificado. Esto tiene una interaccion con etiquetas que puede sorprender a los desprevenidos.
Recuerde que una etiqueta se almacena como una revision al fichero .hgtags, ası que cuando usted crea una eti-
queta, el conjunto de cambios en el cual esta se almacena necesariamente se refiere a un conjunto de cambios anterior.
Cuando ejecuta “hg clone -r foo” para clonar un repositorio hasta la etiqueta foo, el nuevo clon no contendr´ a el
historial que creo la etiqueta que uso para clonar el repositorio. El resultado es que tendr a exactamente el subconjunto
correcto del historial del proyecto en el nuevo repositorio, pero, no la etiqueta que podrıa haber esperado.
8.1.3. Cuando las etiquetas permanentes son demasiado
Dado que las etiquetas de Mercurial estan controladas por revisiones y se llevan en el historial del proyecto, todas
las personas involucradas veran las etiquetas que usted haya creado. El hecho de dar nombres a las revisiones tiene
usos mas alla que simplemente hacer notar que la revision 4237e45506ee es realmente v2.0.2. Si esta tratando de
encontrar un fallo sutil, posiblemente desearıa colocar una etiqueta recordandole algo como “Ana vio los sıntomas en
esta revision”.
Para estos casos, lo que usted posiblemente desearıa serıan etiquetas locales. Puede crear una etiqueta local con
la opcion -l de la orden “hg tag”. Esto guardara la etiqueta en un fichero llamado .hg/localtags. A diferencia de
.hgtags, .hg/localtags no esta controlado por revisiones. Cualquier etiqueta que usted cree usando -l se manten-
dra local al repositorio en el que este trabajando en ese momento.
8.2. El flujo de cambios—El gran cuadro vs. el peque ˜ no
Retomando lo mencionado en el comienzo de un capıtulo, pensemos en el hecho de que un proyecto tiene muchas
piezas concurrentes de trabajo en desarrollo al mismo tiempo.
Puede haber prisa por una nueva version “principal”; una nueva version con un arreglo de fallo a la ultima version;
y una version de “mantenimiento correctivo” a una version antigua que ha entrado en modo de mantenimiento.
Usualmente la gente se refiere a esas direcciones concurrentes de desarrollo como “ramas”. Sin embargo, ya hemos
visto que en varias ocasiones Mercurial trata a todo el historial como una serie de ramas y fusiones. Realmente lo que
tenemos aquı es dos ideas que se relacionan perifericamente, pero que en esencia comparten un nombre.
“El gran cuadro” Las ramas representan un barrido de la evolucion del proyecto; la gente les da nombres y
hablan acerca de ellas en sus conversaciones.
“El cuadro pequeno” Las ramas son artefactos de las actividades diarias de desarrollar y fusionar cambios.
Exponen la narrativa de como se desarrollo el codigo.
8.3. Administrar ramas en repositorios estilo gran cuadro
En Mercurial la forma mas sencilla de aislar una rama del “gran cuadro” es a traves de un repositorio dedica-
do. Si cuenta con un repositorio compartido existente —llamemoslo myproject—que alcanzo la etapa “1.0”, puede
comenzar a prepararse para versiones de mantenimiento futuras a partir de la version 1.0 marcando con una etiqueta
la revision con la cual preparo la version 1.0.
1 $ cd myproject
2 $ hg tag v1.0
Ahora puede clonar un repositorio compartido nuevo myproject-1.0.1 con tal etiqueta.
84
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 95/204
1 $ cd ..
2 $ hg clone myproject myproject-1.0.1
3 updating working directory
4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
Posteriormente, si alguien necesita trabajar en la reparacion de un fallo deberıa dirigirse a la liberacion de ver-sion 1.0.1 que viene en camino, ellos clonarıan el repositorio myproject-1.0.1, harıan sus cambios y los empujarıan
de vuelta.
1 $ hg clone myproject-1.0.1 my-1.0.1-bugfix
2 updating working directory
3 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 $ cd my-1.0.1-bugfix
5 $ echo ’I fixed a bug using only echo!’ >> myfile
6 $ hg commit -m ’Important fix for 1.0.1’
7 $ hg push
8 pushing to /tmp/branch-repo07QkL5/myproject-1.0.1
9 searching for changes
10 adding changesets11 adding manifests
12 adding file changes
13 added 1 changesets with 1 changes to 1 files
Mientras tanto, el desarrollo para la siguiente version mayor puede continuar aislado e incolume, en el repositorio
myproject.
1 $ cd ..
2 $ hg clone myproject my-feature
3 updating working directory
4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ cd my-feature
6 $ echo ’This sure is an exciting new feature!’ > mynewfile7 $ hg commit -A -m ’New feature’
8 adding mynewfile
9 $ hg push
10 pushing to /tmp/branch-repo07QkL5/myproject
11 searching for changes
12 adding changesets
13 adding manifests
14 adding file changes
15 added 1 changesets with 1 changes to 1 files
8.4. No repita trabajo: fusion entre ramasEn muchos casos, cuando tiene un fallo para arreglar en una rama de mantenimiento, es muy probable que el
fallo tambien este en la rama principal (y posiblemente en otras ramas de mantenimiento tambi en). Solamente un
desarrollador extrano desearıa corregir el mismo fallo muchas veces, por tanto, veremos varias alternativas con las que
Mercurial puede ayudarle a administrar tales arreglos de fallo sin duplicar su trabajo.
En el caso mas sencillo, basta con jalar los cambios de la rama de mantenimiento a la rama objetivo en su clon
local.
85
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 96/204
1 $ cd ..
2 $ hg clone myproject myproject-merge
3 updating working directory
4 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ cd myproject-merge
6 $ hg pull ../myproject-1.0.17 pulling from ../myproject-1.0.1
8 searching for changes
9 adding changesets
10 adding manifests
11 adding file changes
12 added 1 changesets with 1 changes to 1 files (+1 heads)
13 (run ’hg heads’ to see heads, ’hg merge’ to merge)
A continuacion debera mezclar las cabezas de las dos ramas, y empujar de nuevo a la rama principal.
1 $ hg merge
2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 (branch merge, don’t forget to commit)4 $ hg commit -m ’Merge bugfix from 1.0.1 branch’
5 $ hg push
6 pushing to /tmp/branch-repo07QkL5/myproject
7 searching for changes
8 adding changesets
9 adding manifests
10 adding file changes
11 added 2 changesets with 1 changes to 1 files
8.5. Nombrar ramas dentro de un repositorio
La aproximacion correcta en casi todas las oportunidades es aislar las ramas en los repositorios. Es f acil de entender
gracias a su simplicidad; y es dif ıcil cometer errores. Hay una relacion uno a uno entre las ramas y los directorios con
los que esta trabajando en su sistema. Esto le permite usar emplear herramientas usuales (que no son conscientes de
Mercurial) para trabajar con los ficheros dentro de una rama/repositorio.
Si se encuentra mas en la categorıa “usuario diestro” ( y sus colaboradores tambien), puede considerar otra alter-
nativa para administrar las ramas. He mencionado con anterioridad la distincion a nivel humano entre las ramas estilo
“cuadro pequeno” y “gran cuadro”. Mientras que Mercurial trabaja con muchas ramas del estilo “cuadro pequeno”
en el repositorio todo el tiempo (por ejemplo cuando usted jala cambios, pero antes de fusionarlos), tambi´ en puede
trabajar con varias ramas del “cuadro grande”.
El truco para trabajar de esta forma en Mercurial se logra gracias a que puede asignar un nombre persistente a una
rama. Siempre existe una rama llamada default. Incluso antes de que empiece a nombrar ramas por su cuenta, puede
encontrar indicios de la rama default si los busca.
Por ejemplo, cuando invoca la orden “hg commit”, y se lanza su editor para introducir el mensaje de la consignacion,busque la lınea que contiene el texto “HG: branch default” al final. Le esta indicando que su consignacion ocur-
rira en la rama llamada default.
Use la orden “hg branches” para empezar a trabajar con ramas nombradas. Esta orden mostrara las ramas pre-
sentes en su repositorio, indicandole que conjunto de cambios es la punta de cada una.
1 $ hg tip
2 changeset: 0:c54ce9a68981
86
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 97/204
3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:16 2009 +0000
6 summary: Initial commit
7
8 $ hg branches
9 default 0:c54ce9a68981
Dado que todavıa no ha creado ramas nombradas, la unica que vera sera default.
Para hallar cual es la rama “actual”, invoque la orden “hg branch”, sin argumento alguno. Le informara en que ra-
ma se encuentra el padre del conjunto de cambios actual.
1 $ hg branch
2 default
Para crear una nueva rama, invoque la orden “hg branch” de nuevo. En esta oportunidad, ofrezca un argumento:
el nombre de la rama que desea crear.
1 $ hg branch foo
2 marked working directory as branch foo3 $ hg branch
4 foo
Despues de crear la rama, usted podrıa desear ver el efecto que tuvo la orden “hg branch”. ¿Que reportan las
ordenes “hg status” y “hg tip”?
1 $ hg status
2 $ hg tip
3 changeset: 0:c54ce9a68981
4 tag: tip
5 user: Bryan O’Sullivan <[email protected]>
6 date: Tue Feb 10 18:23:16 2009 +0000
7 summary: Initial commit8
Nada cambia en el directorio actual, y no se ha anadido nada al historial. Esto sugiere que al ejecutar la orden “ hg
branch” no hay un efecto permanente; solamente le indica a que nombre de rama usara la pr´ oxima vez que consigne
un conjunto de cambios.
Cuando consigna un cambio, Mercurial almacena el nombre de la rama en la cual consigno. Una vez que haya
cambiado de la rama default y haya consignado, vera que el nombre de la nueva rama se mostrara cuando use la
orden “hg log”, “hg tip”, y otras ordenes que desplieguen la misma clase de informacion.
1 $ echo ’hello again’ >> myfile
2 $ hg commit -m ’Second commit’
3 $ hg tip
4 changeset: 1:b108bc883cbc5 branch: foo
6 tag: tip
7 user: Bryan O’Sullivan <[email protected]>
8 date: Tue Feb 10 18:23:17 2009 +0000
9 summary: Second commit
10
87
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 98/204
Las ordenes del tipo “hg log” imprimiran el nombre de la rama de cualquier conjunto de cambios que no este en la
rama default. Como resultado, si nunca usa ramas nombradas, nunca vera esta informacion.
Una vez que haya nombrado una rama y consignado un cambio con ese nombre, todas las consignaciones subse-
cuentes que desciendan de ese cambio heredaran el mismo nombre de rama. Puede cambiar el nombre de una rama en
cualquier momento con la orden “hg branch”.
1
$ hg branch2 foo
3 $ hg branch bar
4 marked working directory as branch bar
5 $ echo new file > newfile
6 $ hg commit -A -m ’Third commit’
7 adding newfile
8 $ hg tip
9 changeset: 2:7f37f4b1f9a3
10 branch: bar
11 tag: tip
12 user: Bryan O’Sullivan <[email protected]>
13 date: Tue Feb 10 18:23:17 2009 +0000
14 summary: Third commit15
Esto es algo que no hara muy seguido en la practica, debido que los nombres de las ramas tienden a tener vidas largas.
(Esto no es una regla, solamente una observacion.)
8.6. Tratamiento de varias ramas nombradas en un repositorio
Si tiene mas de una rama nombrada en un repositorio, Mercurial recordara la rama en la cual esta su directorio de
trabajo cuando invoque una orden como “hg update” o “hg pull -u”. Se actualizara su directorio de trabajo actual
a la punta de esta rama, sin importar cual sea la punta “a lo largo del repositorio”. Para actualizar a una revisi on que
esta en una rama con distinto nombre, puede necesitar la opcion -C de “hg update”.
Este comportamiento puede ser sutil, ası que veamoslo en accion. Primero, recordemos en que rama estamostrabajando, y que ramas estan en nuestro repositorio.
1 $ hg parents
2 changeset: 2:7f37f4b1f9a3
3 branch: bar
4 tag: tip
5 user: Bryan O’Sullivan <[email protected]>
6 date: Tue Feb 10 18:23:17 2009 +0000
7 summary: Third commit
8
9 $ hg branches
10 bar 2:7f37f4b1f9a3
11 foo 1:b108bc883cbc (inactive)12 default 0:c54ce9a68981 (inactive)
Estamos en la rama bar, pero existe otra rama mas antigua llamada “hg foo”.
Podemos hacer “hg update” entre los tipos de las ramas foo y bar sin necesidad de usar la opcion -C, puesto que
esto solamente implica ir linealmente hacia adelante y atras en nuestro historial de cambios.
88
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 99/204
1 $ hg update foo
2 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
3 $ hg parents
4 changeset: 1:b108bc883cbc
5 branch: foo
6 user: Bryan O’Sullivan <[email protected]>7 date: Tue Feb 10 18:23:17 2009 +0000
8 summary: Second commit
9
10 $ hg update bar
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 $ hg parents
13 changeset: 2:7f37f4b1f9a3
14 branch: bar
15 tag: tip
16 user: Bryan O’Sullivan <[email protected]>
17 date: Tue Feb 10 18:23:17 2009 +0000
18 summary: Third commit
19
Si volvemos a la rama foo e invocamos la orden “hg update”, nos mantendra en foo, sin movernos a la punta de
bar.
1 $ hg update foo
2 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
3 $ hg update
4 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
Al consignar un cambio a la rama foo se introducira una nueva cabeza.
1 $ echo something > somefile
2 $ hg commit -A -m ’New file’3 adding somefile
4 created new head
5 $ hg heads
6 changeset: 3:1ca81328634a
7 branch: foo
8 tag: tip
9 parent: 1:b108bc883cbc
10 user: Bryan O’Sullivan <[email protected]>
11 date: Tue Feb 10 18:23:17 2009 +0000
12 summary: New file
13
14 changeset: 2:7f37f4b1f9a3
15 branch: bar
16 user: Bryan O’Sullivan <[email protected]>
17 date: Tue Feb 10 18:23:17 2009 +0000
18 summary: Third commit
19
89
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 100/204
8.7. Nombres de ramas y fusiones
Posiblemente ha notado que las fusiones en Mercurial no son simetricas. Supongamos que su repositorio tiene dos
cabezas, 17 y 23. Si yo invoco “hg update” a 17 y aplico “hg merge” a 23, Mercurial almacena 17 como el primer
padre de la fusion, y 23 como el segundo. Mientras que si hago “ hg update” a 23 y despues aplico “hg merge” con
17, grabara a 23 como el primer padre, y 17 como el segundo.
Esto afecta el como elige Mercurial el nombre de la rama cuando usted hace la fusion. Despues de una fusion,Mercurial mantendra el nombre de la rama del primer padre cuando consigne el resultado de la fusion. Si el primer
nombre de su padre es foo, y fusiona con bar, el nombre de la rama continuara siendo foo despues de fusionar.
No es inusual que un repositorio contenga varias cabezas, cada una con el mismo nombre de rama. Digamos que
estoy trabajando en la rama foo, y usted tambien. Consignamos cambios distintos; yo jalo sus cambios; Ahora tengo
dos cabezas, cada una afirmando estar en la rama foo. El resultado de una fusion sera una unica cabeza en la rama foo
como usted esperarıa.
Pero si estoy trabajando en la rama bar, y fusiono el trabajo de la rama foo, el resultado permanecera en la rama
bar.
1 $ hg branch
2 bar
3 $ hg merge foo
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 (branch merge, don’t forget to commit)
6 $ hg commit -m ’Merge’
7 $ hg tip
8 changeset: 4:a6a8b6aebf33
9 branch: bar
10 tag: tip
11 parent: 2:7f37f4b1f9a3
12 parent: 3:1ca81328634a
13 user: Bryan O’Sullivan <[email protected]>
14 date: Tue Feb 10 18:23:17 2009 +0000
15 summary: Merge
16
En un ejemplo mas concreto, si yo estoy trabajando en la rama bleeding-edge, y deseo traer los arreglos mas
recientes de la rama estable, Mercurial elegira el nombre de rama “correcto” (bleeding-edge) cuando yo jale una
fusion desde estable.
8.8. Normalmente es util nombrar ramas
No deberıa considerar que las ramas nombradas son aplicables unicamente en situaciones con muchas ramas de
larga vida cohabitando en un mismo repositorio. Son muy utiles incluso en los casos de una rama por repositorio.
En el caso mas sencillo, dar un nombre a cada rama ofrece un registro permanente acerca de en que conjunto de
cambios se genero la rama. Esto le ofrece mas contexto cuando este tratando de seguir el historial de un proyecto
ramificado de larga vida.
Si esta trabajando con repositorios compartidos, puede configurar el gancho pretxnchangegroup para que cadauno bloquee los cambios con nombres de rama “incorrectos” que estan por adicionarse. Este provee una defensa
sencilla, pero efectiva, para evitar que la gente publique accidentalmente cambios de una rama “super nueva” a la
rama “estable”. Tal gancho podrıa verse de la siguiente forma dentro de un repositorio compartido de hgrc.
1 [hooks]
2 pretxnchangegroup.branch = hg heads --template ’branches ’ | grep mybranch
90
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 101/204
Capıtulo 9
Encontrar y arreglar sus equivocaciones
Errar es humano, pero tratar adecuadamente las consecuencias requiere un sistema de control de revisiones de
primera categorıa. En este capıtulo, discutiremos algunas tecnicas que puede usar cuando encuentra que hay un prob-
lema enraizado en su proyecto. Mercurial tiene unas caracterısticas poderosas que le ayudaran a isolar las fuentes de
los problemas, y a dar cuenta de ellas apropiadamente.
9.1. Borrar el historial local
9.1.1. La consignacion accidental
Tengo el problema ocasional, pero persistente de teclear mas rapido de lo que pienso, que aveces resulta en
consignar un conjunto de cambios incompleto o simplemente malo. En mi caso, el conjunto de cambios incompleto
consiste en que cree un nuevo fichero fuente, pero olvide hacerle “hg add”. Un conjunto de cambios“simplemente
malo” no es tan comun, pero sı resulta muy molesto.
9.1.2. Hacer rollback una transaccion
En la seccion 4.2.2, mencione que Mercurial trata modificacion a un repositorio como una transacci´ on. Cada vez
que consigna un conjunto de cambios o lo jala de otro repositorio, Mercurial recuerda lo que hizo. Puede deshacer,
o hacer roll back 1, exactamente una de tales acciones usando la orden “hg rollback”. (Ver en la seccion 9.1.4 una
anotacion importante acerca del uso de esta orden.)
A continuacion una equivocacion que me sucede frecuentemente: consignar un cambio en el cual he creado un
nuevo fichero, pero he olvidado hacerle “hg add”.
1 $ hg status
2 M a
3 $ e c h o b > b
4 $ hg commit -m ’Add file b’
La salida de “hg status” despues de la consignacion confirma inmediatamente este error.
1 $ hg status
2 ? b
3 $ hg tip
4 changeset: 1:be1cdd4c4fea
5 tag: tip
1N. del T. El significado igual que en los ambientes de sistemas manejadores de bases de datos se refiere a la atomicidad e integridad al devolver
un conjunto de acciones que permitan dejar el repositorio en un estado consistente previo
91
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 102/204
6 user: Bryan O’Sullivan <[email protected]>
7 date: Tue Feb 10 18:23:29 2009 +0000
8 summary: Add file b
9
La consignacion capturo los cambios en el fichero a, pero no el nuevo fichero b. Si yo publicara este conjunto de
cambios a un repositorio compartido con un colega, es bastante probable que algo en a se refiriera a b, el cual podrıano estar presente cuando jalen mis cambios del repositorio. Me convertirıa el sujeto de cierta indignacion.
Como sea, la suerte me acompana—Encontre mi error antes de publicar el conjunto de cambios. Uso la orden “hg
rollback”, y Mercurial hace desaparecer el ultimo conjunto de cambios.
1 $ hg rollback
2 rolling back last transaction
3 $ hg tip
4 changeset: 0:c40e0a2ea41e
5 tag: tip
6 user: Bryan O’Sullivan <[email protected]>
7 date: Tue Feb 10 18:23:29 2009 +0000
8 summary: First commit
9
10 $ hg status
11 M a
12 ? b
El conjunto de cambios ya no esta en el historial del repositorio, y el directorio de trabajo cree que el fichero a ha
sido modificado. La consignacion y el roll back dejaron el directorio de trabajo exactamente como estaba antes de la
consignacion; el conjunto de cambios ha sido eliminado totlamente. Ahora puedo hacer “hg add” al fichero b, y hacer
de nuevo la consignacion.
1 $ hg add b
2 $ hg commit -m ’Add file b, this time for real’
9.1.3. Erroneamente jalado
Mantener ramas de desarrollo separadas de un proyecto en distintos repositorios es una practica comun con Mercu-
rial. Su equipo de desarrollo puede tener un repositorio compartido para la versi on “0.9” y otra con cambios distintos
para la version “1.0”.
Con este escenario, puede imaginar las consecuencias si tuviera un repositorio local “0.9”, y jalara accidentalmente
los cambios del repositorio compartido de la version “1.0” en este. En el peor de los casos, por falta de atenci on, es
posible que publique tales cambios en el arbol compartido “0.9”, confundiendo a todo su equipo de trabajo (pero no
se preocupe, volveremos a este terrorıfico escenario posteriormente). En todo caso, es muy probable que usted se de
cuenta inmediatamente, dado que Mercurial mostrara el URL de donde esta jalando, o que vea jalando una sospechosa
gran cantidad de cambios en el repositorio.
La orden “hg rollback” excluira eficientemente los conjuntos de cambios que haya acabado de jalar. Mercurial
agrupa todos los cambios de un “hg pull” a una unica transaccion y bastara con un “hg rollback” para deshaceresta equivocacion.
9.1.4. Despues de publicar, un roll back es futil
El valor de “hg rollback” se anula cuando ha publicado sus cambios a otro repositorio. Un cambio desaparece
totalmente al hacer roll back, pero solamente en el repositorio en el cual aplica “hg rollback”. Debido a que un roll
back elimina el historial, no hay forma de que la desaparicion de un cambio se propague entre repositorios.
92
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 103/204
Si ha publicado un cambio en otro repositorio—particularmente si es un repositorio publico—esencialmente
esta “en terreno agreste,” y tendra que reparar la equivocacion de un modo distinto. Lo que pasara si publica un
conjunto de cambios en algun sitio, hacer rollback y despues volver a jalar del repositorio del cual habıa publicado, es
que el conjunto de cambios reaparecera en su repositorio.
(Si esta absolutamente segruro de que el conjunto de cambios al que desea hacer rollback es el cambio m as reciente
del repositorio en el cual publico, y sabe que nadie mas pudo haber jalado de tal repositorio, puede hacer rollback del
conjunto de cambios allı, pero es mejor no confiar en una solucion de este estilo. Si lo hace, tarde o temprano unconjunto de cambios lograra colarse en un repositorio que usted no controle directamente (o del cual se ha olvidado),
y volvera a hostigarle.)
9.1.5. Solamente hay un roll back
Mercurial almacena exactamente una transaccion en su bitacora de transacciones; tal transaccion es la mas reciente
de las que haya ocurrido en el repositorio. Esto significa que solamente puede hacer roll back a una transaccion. Si
espera poder hacer roll back a una transaccion despues al antecesor, observara que no es el comportamiento que
obtendra.
1 $ hg rollback
2 rolling back last transaction
3 $ hg rollback
4 no rollback information available
Una vez que haya aplicado un rollback en una transaccion a un repositorio, no podra volver a hacer rollback hasta que
haga una consignacion o haya jalado.
9.2. Revertir un cambio equivocado
Si modifica un fichero y se da cuenta que no quer ıa realmente cambiar tal fichero, y todavıa no ha consignado
los cambios, la orden necesaria es “hg revert”. Observa el conjunto de cambios padre del directorio y restaura los
contenidos del fichero al estado de tal conjunto de cambios. (Es una forma larga de decirlo, usualmente deshace sus
modificaciones.)
Ilustremos como actua la orden “hg revert” con un ejemplo pequeno. Comenzaremos modificando un fichero al
cual Mercurial ya esta siguiendo.
1 $ cat file
2 original content
3 $ echo unwanted change >> file
4 $ hg diff file
5 diff -r f8694d2c79ed file
6 --- a/file Tue Feb 10 18:23:21 2009 +0000
7 +++ b/file Tue Feb 10 18:23:21 2009 +0000
8 @@ -1,1 +1,2 @@
9 original content
10 +unwanted change
Si no queremos ese cambio, podemos aplicar “hg revert” al fichero.
1 $ hg status
2 M file
3 $ hg revert file
4 $ cat file
5 original content
93
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 104/204
La orden “hg revert” nos brinda un grado adicional de seguridad guardando nuestro fichero modificado con la
extension .orig.
1 $ hg status
2 ? file.orig
3 $ cat file.orig
4 original content
5 unwanted change
Este es un resumen de casos en los cuales la orden “hg revert” es de utilidad. Describiremos cada uno de ellos
con mas detalle en la seccion siguiente.
Si usted modifica un fichero, lo restaurara a su estado sin modificacion previo.
Si usted hace “hg add” a un fichero, revertira el estado de “adicionado” del fichero, pero no lo tocara
Si borra un fichero sin decirle a Mercurial, restaurara el fichero con sus contenidos sin modificacion.
Si usa la orden “hg remove” para eliminar un fichero, deshara el estado “removido” del fichero, y lo restau-
rara con sus contenidos sin modificacion.
9.2.1. Errores al administrar ficheros
La orden “hg revert” es util para mas que ficheros modificados. Le permite reversar los resultados de todas las
ordenes de administracion de ficheros que provee Mercurial—“hg add”, “hg remove”, y las demas.
Si usted hace “hg add” a un fichero, y no deseaba que Mercurial le diera seguimiento, use “hg revert” para
deshacer la adicion. No se preocupe; Mercurial no modificara de forma alguna el fichero. Solamente lo “desmarcara”.
1 $ echo oops > oops
2 $ hg add oops
3 $ hg status oops
4 A oops
5 $ hg revert oops
6 $ hg status
7 ? oops
De forma similar, Si le solicita a Mercurial hacer “hg remove” a un fichero, puede usar “hg revert” para restaru-
rarlo a los contenidos que tenıa la revision padre del directorio de trabajo.
1 $ hg remove file
2 $ hg status
3 R file
4 $ hg revert file
5 $ hg status
6 $ ls file
7 file
Funciona de la misma manera para un fichero que usted haya eliminado manualmente, sin decirle a Mercurial (recuerde
que en la terminologıa de Mercurial esta clase de fichero se llama “faltante”).
1 $ rm file
2 $ hg status
3 ! file
4 $ hg revert file
94
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 105/204
5 $ ls file
6 file
Si usted revierte un “hg copy”, el fichero a donde se copio permanece en su directorio de trabajo, pero sin
seguimiento. Dado que una copia no afecta el fichero fuente de copiado de ninguna maner, Mercurial no hace na-
da con este.
1 $ hg copy file new-file
2 $ hg revert new-file
3 $ hg status
4 ? new-file
Un caso ligeramente especial:revertir un renombramiento
Si hace “hg rename” a un fichero, hay un detalle que debe tener en cuenta. Cuando aplica “ hg revert” a un
cambio de nombre, no es suficiente proveer el nombre del fichero destino, como puede verlo en el siguiente ejemplo.
1 $ hg rename file new-file
2 $ hg revert new-file
3 $ hg status4 ? new-file
Como puede ver en la salida de “hg status”, el fichero con el nuevo nombre no se identifica m as como agregado,
pero el fichero con el nombre-inicial se elimna! Esto es contra-intuitivo (por lo menos para mı), pero por lo menos es
f acil arreglarlo.
1 $ hg revert file
2 no changes needed to file
3 $ hg status
4 ? new-file
Por lo tanto, recuerde, para revertir un “hg rename”, debe proveer ambos nombres, la fuente y el destino.
(A proposito, si elimina un fichero, y modifica el fichero con el nuevo nombre, al revertir ambos componentesdel renombramiento, cuando Mercurial restaure el fichero que fue eliminado como parte del renombramiento, no
sera modificado. Si necesita que las modificaciones en el fichero destino del renombramiento se muestren, no olvide
copiarlas encima.)
Estos aspectos engorrosos al revertir un renombramiento se constituyen discutiblemente en un fallo de Mercurial.
9.3. Tratar cambios consignados
Considere un caso en el que ha consignado el cambio a, y otro cambio b sobre este; se ha dado cuenta que el
cambio a era incorrecto. Mercurial le permite “retroceder” un conjunto de cambios completo autom aticamente, y
construir bloques que le permitan revertir parte de un conjunto de cambios a mano.
Antes de leer esta seccion, hay algo para tener en cuenta: la orden “hg backout” deshace cambios adicionando
al historial, sin modificar o borrar. Es la herramienta correcta si esta arreglando fallos, pero no si esta tratando dedeshacer algun cambio que tiene consecuencias catastroficas. Para tratar con esos, vea la seccion 9.4.
9.3.1. Retroceder un conjunto de cambios
La orden “hg backout” le permite “deshacer” los efectos de todo un conjunto de cambios de forma automatizada.
Dado que el historial de Mercurial es inmutable, esta orden no se deshace del conjunto de cambios que usted desea
deshacer. En cambio, crea un nuevo conjunto de cambios que reversa el conjunto de cambios que usted indique.
95
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 106/204
La operacion de la orden “hg backout” es un poco intrincada, y lo ilustraremos con algunos ejemplos. Primero
crearemos un repositorio con algunos cambios sencillos.
1 $ hg init myrepo
2 $ cd myrepo
3 $ echo first change >> myfile
4
$ hg add myfile5 $ hg commit -m ’first change’
6 $ echo second change >> myfile
7 $ hg commit -m ’second change’
La orden “hg backout” toma un ID de conjunto de cambios como su argumento; el conjunto de cambios a
retroceder. Normalmente “hg backout” le ofrecera un editor de texto para escribir el mensaje de la consignacion,
para dejar un registro de por que esta retrocediendo. En este ejemplo, colocamos un mensaje en la consignacion
usando la opcion -m.
9.3.2. Retroceder el conjunto de cambios punta
Comenzamos retrocediendo el ultimo conjunto de cambios que consignamos.
1 $ hg backout -m ’back out second change’ tip
2 reverting myfile
3 changeset 2:1d9ee76a7513 backs out changeset 1:cab6a78bf14b
4 $ cat myfile
5 first change
Puede ver que la segunda lınea de myfile ya no esta presente. La salida de “hg log” nos da una idea de lo que la
orden “hg backout” ha hecho.
1 $ hg log --style compact
2 2[tip] 1d9ee76a7513 2009-02-10 18:23 +0000 bos
3 back out second change
4
5 1 cab6a78bf14b 2009-02-10 18:23 +0000 bos
6 second change
7
8 0 60b8d10ede6c 2009-02-10 18:23 +0000 bos
9 first change
10
Vea que el nuevo conjunto de cambios que “hg backout” ha creado es un hijo del conjunto de cambios que retroced-
imos. Es mas sencillo de ver en la figura 9.1, que presenta una vista grafica del historial de cambios. Como puede ver,
el historial es bonito y lineal.
9.3.3. Retroceso de un cambio que no es la puntaSi desea retrocede un cambio distinto al ultimo que ha consignado, use la opcion --merge a la orden “hg backout”.
1 $ cd ..
2 $ hg clone -r1 myrepo non-tip-repo
3 requesting all changes
4 adding changesets
96
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 107/204
primer cambio
segundo cambio
reversar
segundo cambio
Figura 9.1: Retroceso de un cambio con la orden “hg backout”
5 adding manifests
6 adding file changes
7 added 2 changesets with 2 changes to 1 files
8 updating working directory
9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 $ cd non-tip-repo
Que resulta en un retroceso de un conjunto de cambios “en un solo tiro”, una operacion que resulta normalmente
rapida y sencilla.
1 $ echo third change >> myfile
2 $ hg commit -m ’third change’
3 $ hg backout --merge -m ’back out second change’ 1
4 reverting myfile
5 created new head
6 changeset 3:688f1a6067e5 backs out changeset 1:cab6a78bf14b
7 merging with changeset 3:688f1a6067e5
8 merging myfile
9 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
10 (branch merge, don’t forget to commit)
Si ve los contenidos del fichero myfile despues de finalizar el retroceso, vera que el primer y el tercer cambio
estan presentes, pero no el segundo.
1 $ cat myfile
2 first change
3 third change
Como lo muestra el historial grafico en la figura 9.2, Mercurial realmente consigna dos cambios en estas situaciones
(los nodos encerrados en una caja son aquellos que Mercurial consigna automaticamente). Antes de que Mercurial
comience el proceso de retroceso, primero recuerda cual es el padre del directorio de trabajo. Posteriormente hace un
97
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 108/204
retroceso al conjunto de cambios objetivo y lo consigna como un conjunto de cambios. Finalmente, fusiona con el
padre anterior del directorio de trabajo, y consigna el resultado de la fusion.
primer cambio
segundo cambio
tercer cambioreversar
segundo cambio
fusión
automatizar
fusión
Figura 9.2: Retroceso automatizado de un cambio a algo que no es la punta con la orden “ hg backout”
El resultado es que usted termina “donde estaba”, solamente con un poco de historial adicional que deshace el
efecto de un conjunto de cambios que usted querıa evitar.
Use siempre la opcion --merge
De hecho, dado que la opcion --merge siempre hara lo “correcto” este o no retrocediendo el conjunto de cambios
punta (p.e. no tratara de fusionar si esta retrocediendo la punta, dado que no es necesario), usted deberıa usar siempre
esta opcion cuando ejecuta la orden “hg backout”.
9.3.4. Mas control sobre el proceso de retroceso
A pesar de que recomiendo usar siempre la opcion --merge cuando esta retrocediendo un cambio, la orden “hg
backout” le permite decidir como mezclar un retroceso de un conjunto de cambios. Es muy extrano que usted necestite
tomar control del proceso de retroceso de forma manual, pero puede ser util entender lo que la orden “hg backout”
esta haciendo automaticamente para usted. Para ilustrarlo, clonemos nuestro primer repositorio, pero omitamos el
retroceso que contiene.
1 $ cd ..
2 $ hg clone -r1 myrepo newrepo
3 requesting all changes
4 adding changesets
5 adding manifests
6 adding file changes
7 added 2 changesets with 2 changes to 1 files
98
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 109/204
8 updating working directory
9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 $ cd newrepo
Como en el ejemplo anterior, consignaremos un tercer cambio, despues haremos retroceso de su padre, y veremos
que pasa.
1 $ echo third change >> myfile
2 $ hg commit -m ’third change’
3 $ hg backout -m ’back out second change’ 1
4 reverting myfile
5 created new head
6 changeset 3:688f1a6067e5 backs out changeset 1:cab6a78bf14b
7 the backout changeset is a new head - do not forget to merge
8 (use "backout --merge" if you want to auto-merge)
Nuestro nuevo conjunto de cambios es de nuevo un descendiente del conjunto de cambio que retrocedimos; es por lo
tanto una nueva cabeza, no un descendiente del conjunto de cambios que era la punta. La orden “hg backout” fue
muy explıcita diciendolo.
1 $ hg log --style compact
2 3[tip]:1 688f1a6067e5 2009-02-10 18:23 +0000 bos
3 back out second change
4
5 2 72a18afb4ae5 2009-02-10 18:23 +0000 bos
6 third change
7
8 1 cab6a78bf14b 2009-02-10 18:23 +0000 bos
9 second change
10
11 0 60b8d10ede6c 2009-02-10 18:23 +0000 bos
12 first change
13
De nuevo, es mas sencillo lo que paso viendo una grafica del historial de revisiones, en la figura 9.3. Esto nos
aclara que cuando usamos “hg backout” para retroceder un cambio a algo que no sea la punta, Mercurial a nade una
nueva cabeza al repositorio (el cambio que consigno esta encerrado en una caja).
Despues de que la orden “hg backout” ha terminado, deja un nuevo conjunto de cambios de “retroceso” como el
padre del directorio de trabajo.
1 $ hg parents
2 changeset: 2:72a18afb4ae5
3 user: Bryan O’Sullivan <[email protected]>
4 date: Tue Feb 10 18:23:13 2009 +0000
5 summary: third change6
Ahora tenemos dos conjuntos de cambios aislados.
1 $ hg heads
2 changeset: 3:688f1a6067e5
3 tag: tip
99
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 110/204
primer cambio
segundo cambio
tercer cambioreversar
segundo cambio
Figura 9.3: Retroceso usando la orden “hg backout”
4 parent: 1:cab6a78bf14b
5 user: Bryan O’Sullivan <[email protected]>
6 date: Tue Feb 10 18:23:13 2009 +0000
7 summary: back out second change
8
9 changeset: 2:72a18afb4ae5
10 user: Bryan O’Sullivan <[email protected]>
11 date: Tue Feb 10 18:23:13 2009 +0000
12 summary: third change
13
Reflexionemos acerca de lo que esperamos ver como contenidos de myfile. El primer cambio deberıa estar pre-
sente, porque nunca le hicimos retroceso. El segundo cambio debio desaparecer, puesto que es el que retrocedimos.Dado que la grafica del historial muestra que el tercer camlio es una cabeza separada, no esperamos ver el tercer
cambio presente en myfile.
1 $ cat myfile
2 first change
3 second change
4 third change
Para que el tercer cambio este en el fichero, hacemos una fusion usual de las dos cabezas.
1 $ hg merge
2 merging myfile
3 0 files updated, 1 files merged, 0 files removed, 0 files unresolved4 (branch merge, don’t forget to commit)
5 $ hg commit -m ’merged backout with previous tip’
6 $ cat myfile
7 first change
8 third change
Despues de eso, el historial grafica de nuestro repositorio luce como la figura 9.4.
100
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 111/204
primer cambio
segundo cambio
tercer cambioreversar
segundo cambio
fusión
manual
Figura 9.4: Fusion manual de un retroceso
9.3.5. Por que “hg backout” hace lo que hace
Esta es una descripcion corta de como trabaja la orden “hg backout”.
1. Se asegura de que el directorio de trabajo es “limpio”, esto es, que la salida de “hg status” deberıa ser vacıa.
2. Recuerda el padre actual del directorio de trabajo. A este conjunto de cambio lo llamaremos orig
3. Hace el equivalente de un “hg update” para sincronizar el directorio de trabajo con el conjunto de cambios que
usted quiere retroceder. Lo llamaremos backout
4. Encuentra el padre del conjunto de cambios. Lo llamaremos parent.
5. Para cada fichero del conjunto de cambios que el retroceso afecte, hara el equivalente a “hg revert -r
parent” sobre ese fichero, para restaurarlo a los contenidos que tenıa antes de que el conjunto de cambios fuera
consignado.
6. Se consigna el resultado como un nuevo conjunto de cambios y tiene a backout como su padre.
7. Si especifica --merge en la lınea de comandos, se fusiona con orig, y se consigna el resultado de la fusion.
Una vıa alternativa de implementar la orden “hg backout” serıa usar “hg export” sobre el conjunto de cambios
a retroceder como un diff y despues usar laa opcion --reverse de la orden patch para reversar el efecto del cambio
sin molestar el directorio de trabajo. Suena mucho mas simple, pero no funcionarıa bien ni de cerca.
La razon por la cual “hg backout” hace una actualizacion, una consignacion, una fusion y otra consignacion es
para dar a la maquinaria de fusion la mayor oportunidad de hacer un buen trabajo cuando se trata con todos los cambios
entre el cambio que esta retrocediendo y la punta actual.
101
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 112/204
Si esta retrocediendo un conjunto de cambios que esta a unas 100 atras en su historial del proyecto, las posibili-
dades de que una orden patch sea capaz de ser aplicada a un diff reverso, claramente no son altas, porque los cambios
que intervienen podrıan “no coincidir con el contexto” que patch usa para determinar si puede aplicar un parche (si
esto suena como chachara, vea una discusion de la orden patch en 12.4). Adicionalmente, la maquinaria de fusion
de Mercurial manejara ficheros y directorios renombrados, cambios de permisos, y modificaciones a ficheros binarios,
nada de lo cual la orden patch puede manejar.
9.4. Cambios que nunca debieron ocurrir
En la mayorıa de los casos, la orden “hg backout” es exactamente lo que necesita para deshacer los efectos de
un cambio. Deja un registro permanente y exacto de lo que usted hizo, cuando se consign o el conjunto de cambios
original y cuando se hizo la limpieza.
En ocasiones particulares, puede haber consignado un cambio que no deberıa estar de ninguna forma en el repos-
itorio. Por ejemplo, serıa muy inusual, y considerado como una equivocacion, consignar los ficheros objeto junto con
el codigo fuente. Los ficheros objeto no tienen valor intr ınseco y son grandes, por lo tanto aumentan el tamano del
repositorio y la cantidad de tiempo que se emplea al clonar o jalar cambios.
Antes de discutir las opciones que tiene si consigno cambio del tipo “bolsa de papel deschable” (el tipo que es
tan malo que le gustarıa colocarse una bolsa de papel desechable en su cabeza), permıtame discutir primero unas
aproximaciones que probablemente no funcionen.Dado que Mercurial trata de forma acumulativa al historial—cada cambio se coloca encima de todos los cambios
que le preceden—usualmente usted no puede hacer que unos cambios desastrosos desaparezcan. La unica excepcion
es cuando usted ha acabado de consignar un cambio y este no ha sido publicado o jalado en otro repositorio. Ahı es
cuando puede usar la orden “hg rollback” con seguridad, como detalle en la seccion 9.1.2.
Despues de que usted haya publicado un cambio en otro repositorio, usted podr ıa usar la orden “hg rollback”
para hacer que en su copia local desaparezca el cambio, pero no tendra las consecuencias que desea. El cambio
estara presente en un repositorio remoto, y reaparecera en su repositorio local la proxima vez que jale
Si una situacion como esta se presenta, y usted sabe en que repositorios su mal cambio se ha propagado, puede
intentar deshacerse del conjunto de cambios de todos los repositorios en los que se pueda encontrar. Esta por supuesto,
no es una solucion satisfactoria: si usted deja de hacerlo en un solo repositorio, mientras est e eliminandolo, el cambio
todavıa estara “allı afuera”, y podrıa propagarse mas tarde.
Si ha consignado uno o mas cambios despu´ es del cambio que desea desaparecer, sus opciones son aun mas reduci-
das. Mercurial no provee una forma de “cabar un hueco” en el historial, dejando los conjuntos de cambios intactos.XXX This needs filling out. The hg-replay script in the examples directory works, but doesn’t handle merge
changesets. Kind of an important omission.
9.4.1. Como protegerse de cambios que han “escapado”
Si ha consignado cambios a su repositorio local y estos han sido publicados o jalados en cualquier otro sitio, no es
necesariamente un desastre. Puede protegerse de antemano de ciertas clases de conjuntos de cambios malos. Esto es
particularmente sencillo si su equipo de trabajo jala cambios de un repositorio central.
Al configurar algunos ganchos en el repositorio central para validar conjuntos de cambios (ver capıtulo 10), puede
prevenir la publicacion automaticamente de cierta clase de cambios malos. Con tal configuracion, cierta clase de
conjuntos de cambios malos tenderan naturalmente a“morir” debido a que no pueden propagarse al repositorio central.
Esto sucedera sin necesidad de intervencion explıcita.
Por ejemplo, un gancho de cambios de entrada que verifique que un conjunto de cambios compila, puede prevenirque la gente “rompa la compilacion” inadvertidamente.
9.5. Al encuentro de la fuente de un fallo
Aunque es muy bueno poder retroceder el conjunto de cambios que origino un fallo, se requiere que usted sepa
cual conjunto de cambios retroceder. Mercurial brinda una orden invaluable, llamada “ hg bisect”, que ayuda a
102
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 113/204
automatizar este proceso y a alcanzarlo muy eficientemente.
La idea tras la orden “hg bisect” es que el conjunto de cambios que ha introducido un cambio de comportamiento
pueda identificarse con una prueba binaria sencilla. No tiene que saber que pieza de codigo introdujo el cambio, pero si
requiere que sepa como probar la existencia de un fallo. La orden “hg bisect” usa su prueba para dirigir su busqueda
del conjunto de cambios que introdujo el codigo causante del fallo.
A continuacion un conjunto de escenarios que puede ayudarle a entender como puede aplicar esta orden.
La version mas reciente de su programa tiene un fallo que usted recuerda no estaba hace unas semanas, pero no
sabe cuando fue introducido. En este caso, su prueba binaria busca la presencia de tal fallo.
Usted arreglo un fallo en un apurto, y es hora de dar por cerrado el caso en la base de datos de fallos de su
equipo de trabajo. La base de datos de fallos requiere el ID del conjunto de cambios que permita dar por cerrado
el caso, pero usted no recuerda que conjunto de cambios arreglo tal fallo. De nuevo la prueba binaria revisa la
presencia del fallo.
Su programa funciona correctamente, pero core 15 % mas lento que la ultima vez que lo midio. Usted desea
saber que conjunto de cambios introdujo esta disminucion de desempeno. En este caso su prueba binaria mide
el desempeno de su programa, para ver donde es “rapido” y donde es “lento”.
Los tamanos de los componentes del proyecto que usted lleva se expandieron recientemente, y sospecha que
algo cambio en la forma en que se construye su proyecto.
Para estos ejemplos deberıa ser claro que la orden “hg bisect” es util no solamente para encontrar la fuente de
los fallos. Puede usarla para encontrar cualquier “propiedad emergente” de un repositorio (Cualquier cosa que usted
no pueda encontrar con una busqueda de texto sencilla sobre los ficheros en el arbol) para la cual pueda escribir una
prueba binaria.
A continuacion introduciremos algo terminologıa, para aclarar que partes del proceso de busqueda son su respon-
sabilidad y cuales de Mercurial. Una prueba es algo que usted ejecuta cuando “hg bisect” elige un conjunto de
cambios. Un sondeo es lo que “hg bisect” ejecuta para decidir si una revision es buena. Finalmente, usaremos la
palabra “biseccionar’, en frases como “buscar con la orden “hg bisect””.
Una forma sencilla de automatizar el proceso de busqueda serıa probar cada conjunto de cambios. Lo cual escala
muy poco. Si le tomo diez minutos hacer pruebas sobre un conjunto de cambios y tiene 10.000 conjuntos de cambios
en su repositorio, esta aproximacion exhaustiva tomarıa en promedio 35 d ıas para encontrar el conjunto de cambios
que introdujo el fallo. Incluso si supiera que el fallo se introdujo en un de los ultimos 500 conjuntos de cambios y
limitara la busqueda a ellos, estarıa tomabdi mas de 40 horas para encontrar al conjunto de cambios culpable.La orden “hg bisect” usa su conocimiento de la “forma” del historial de revisiones de su proyecto para hacer
una busqueda proporcional al logaritmo del numero de conjunto de cambios a revisar (el tipo de busqueda que realiza
se llama busqueda binaria). Con esta aproximacion, el buscar entre 10.000 conjuntos de cambios tomara menos de
3 horas, incluso a diez minutos por prueba (La b usqueda requerira cerca de 14 pruebas). Al limitar la busqueda a la
ultima centena de conjuntos de cambios, tomara a lo sumo una hora (Apenas unas 7 pruebas).
La orden “hg bisect” tiene en cuenta la naturaleza “ramificada” del historial de revisiones del proyecto con
Mercurial, ası que no hay problemas al tratar con ramas, fusiones o cabezas multiples en un repositorio. Puede evitar
ramas enteras de historial con un solo sondeo.
9.5.1. Uso de la orden “hg bisect”
A continuacion un ejemplo de “hg bisect” en accion.
Nota: En las versiones 0.9.5 y anteriores de Mercurial, “hg bisect” no era una
orden incluıda en la distribucion principal: se ofrecıa como una extension de Mer-
curial. Esta seccion describe la orden embebida y no la extension anterior.
Creamos un repostorio para probar el comando “hg bisect” de forma aislada
1 $ hg init mybug
2 $ cd mybug
103
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 114/204
Simularemos de forma sencilla un proyecto con un fallo: haremos cambios triviales en un ciclo, e indicaremos que
un cambio especıfico sea el “fallo”. Este ciclo crea 35 conjuntos de cambios, cada uno a nade un unico fichero al
repositorio. Representaremos nuestro “fallo” con un fichero que contiene el texto “tengo un gub”.
1 $ buggy_change=22
2 $ f o r ( ( i = 0 ; i < 3 5 ; i + + ) ) ; d o
3
> if [[ $i = $buggy_change ]]; then4 > echo ’i have a gub’ > myfile$i
5 > hg commit -q -A -m ’buggy changeset’
6 > else
7 > echo ’nothing to see here, move along’ > myfile$i
8 > hg commit -q -A -m ’normal changeset’
9 > fi
10 > done
A continuacion observaremos como usar la orden “hg bisect”. Podemos usar el mecanismo de ayuda embebida
que trae Mercurial.
1 $ hg help bisect
2 hg bisect [-gbsr] [REV]3
4 subdivision search of changesets
5
6 This command helps to find changesets which introduce problems.
7 To use, mark the earliest changeset you know exhibits the problem
8 as bad, then mark the latest changeset which is free from the
9 problem as good. Bisect will update your working directory to a
10 revision for testing. Once you have performed tests, mark the
11 working directory as bad or good and bisect will either update to
12 another candidate changeset or announce that it has found the bad
13 revision.
14
15 options:16
17 -r --reset reset bisect state
18 -g --good mark changeset good
19 -b --bad mark changeset bad
20 -s --skip skip testing changeset
21 -U --noupdate do not update to target
22
23 use "hg -v help bisect" to show global options
La orden “hg bisect” trabaja en etapas, de la siguiente forma:
1. Usted ejecuta una prueba binaria.
Si la prueba es exitosa, usted se lo indicara a “hg bisect” ejecutando la orden “hg bisect good”.
Si falla, ejecutara la orden “hg bisect --bad”.
2. La orden usa su informacion para decidir que conjuntos de cambios deben probarse a continuacion.
3. Actualiza el directorio de trabajo a tal conjunto de cambios y el proceso se lleva a cabo de nuevo.
104
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 115/204
El proceso termina cuando “hg bisect” identifica un unico conjunto de cambios que marca el punto donde se encon-
tro la transicion de “exitoso” a “fallido”.
Para comenzar la busqueda, es indispensable ejecutar la orden “hg bisect --reset”.
1 $ if hg -v | head -1 | grep -e "version 0.*"
2 > then
3
#On mercurial 1.0 --init disappeared4 > hg bisect --init
5 > fi
En nuestro caso, la prueba binaria es sencilla: revisamos si el fichero en el repositorio contiene la cadena “tengo
un gub”. Si la tiene, este conjunto de cambios contiene aquel que “caus o el fallo”. Por convencion, un conjunto de
cambios que tiene la propiedad que estamos buscando es “malo”, mientras que el otro que no la tiene es “bueno”.
En la mayorıa de casos, la revision del directorio actual (usualmente la punta) exhibe el problema introducido por
el cambio con el fallo, por lo tanto la marcaremos como “mala”.
1 $ hg bisect --bad
Nuestra proxima tarea es nominar al conjunto de cambios que sabemos no tiene el fallo; la orden “hg bisect”
“acotara” su busqueda entre el primer par de conjuntos de cambios buenos y malos. En nuestro caso, sabemos que larevision 10 no tenıa el fallo. (Mas adelante dire un poco mas acerca de la eleccion del conjunto de cambios “bueno”.)
1 $ hg bisect --good 10
2 Testing changeset 22:ec1c6526e0eb (24 changesets remaining, ˜4 tests)
3 0 files updated, 0 files merged, 12 files removed, 0 files unresolved
Note que esta orden mostro algo.
Nos dijo cuantos conjuntos de cambios debe considerar antes de que pueda identifica aquel que introdujo el
fallo, y cuantas pruebas se requeriran.
Actualizo el directorio de trabajo al siguiente conjunto de cambios, y nos dijo que conjunto de cambios esta eval-
uando.
Ahora ejecutamos nuestra prueba en el directorio de trabajo. Usamos la orden grep para ver si nuestro fichero
“malo” esta presente en el directorio de trabajo. Si lo esta, esta revision es mala; si no esta revision es buena.
1 $ if grep -q ’i have a gub’ *2 > then
3 > result=bad
4 > else
5 > result=good
6 > fi
7 $ echo this revision is $result
8 this revision is bad
9 $ hg bisect --$result
10 Testing changeset 16:8fb73e2ea5f9 (12 changesets remaining, ˜3 tests)
11 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
Esta prueba luce como candidata perfecta para automatizarse, por lo tanto la convertimos en una funcion de interfaz
de comandos.
105
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 116/204
1 $ mytest() {2 > if grep -q ’i have a gub’ *3 > then
4 > result=bad
5 > else
6 > result=good7 > fi
8 > echo this revision is $result
9 > hg bisect --$result
10 > }
Ahora podemos ejecutar un paso entero de pruebas con un solo comando, mytest.
1 $ mytest
2 this revision is good
3 Testing changeset 19:ffbbdeaade97 (6 changesets remaining, ˜2 tests)
4 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
Unas invocaciones mas de nuestra prueba, y hemos terminado.
1 $ mytest
2 this revision is good
3 Testing changeset 20:c0c13593daf1 (3 changesets remaining, ˜1 tests)
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ mytest
6 this revision is good
7 Testing changeset 21:d70e5938b22b (2 changesets remaining, ˜1 tests)
8 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
9 $ mytest
10 this revision is good
11 The first bad revision is:
12 changeset: 22:ec1c6526e0eb
13 user: Bryan O’Sullivan <[email protected]>
14 date: Tue Feb 10 18:23:14 2009 +0000
15 summary: buggy changeset
16
Aunque tenıamos unos 40 conjuntos de cambios en los cuales buscar, la orden “hg bisect” nos permitio encontrar
el conjunto de cambios que introdujo el “fallo” con solo cinco pruebas. Porque el numero de pruebas que la orden “hg
bisect” ejecuta crece logarıtmicamente con la cantidad de conjuntos de cambios a buscar, la ventaja que esto tiene
frente a la busqueda por“fuerza bruta” crece con cada conjunto de cambios que usted adicione.
9.5.2. Limpieza despues de la busqueda
Cuando haya terminado de usar la orden “hg bisect” en un repositorio, puede usar la orden “hg bisect reset”
para deshacerse de la informacion que se estaba usando para lograr la busqueda. Lar orden no usa mucho espacio,
ası que no hay problema si olvida ejecutar la orden. En todo caso, “hg bisect” no le permitira comenzar una nueva
busqueda sobre el repositorio hasta que no aplique “hg bisect reset”.
1 $ hg bisect --reset
106
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 117/204
9.6. Consejos para encontrar fallos efectivamente
9.6.1. Dar una entrada consistente
La orden “hg bisect” requiere que usted ofrezca un reporte correcto del resultado de cada prueba que aplique.
Si usted le dice que una prueba falla cuando en realidad era acertada, podr ıa detectar la inconsistencia. Si puede
identificar una inconsistencia en sus reportes, le dira que un conjunto de cambios particular es a la vez bueno y malo.
Aunque puede no hacerlo; estarıa tratando de reportar un conjunto de cambios como el responsable de un fallo aunque
no lo sea.
9.6.2. Automatizar tanto como se pueda
Cuando comence a usar la orden “hg bisect”, intente ejecutar algunas veces las pruebas a mano desde la lınea
de comandos. Es una aproximacion a la cual no esta acostumbrado. Despues de algunos intentos, me di cuenta que
estaba cometiendo tantas equivocaciones que tenıa que comenzar de nuevo con mis busquedas varias veces antes de
llegar a los resultados deseados.
Mi problema inicial al dirigir a la orden “hg bisect” manualmente ocurrieron incluso con busquedas en reposito-
rios pequenos; si el problema que esta buscando es mas sutil, o el numero de pruebas que “hg bisect” debe aplicar,
la posibilidad de errar es mucho mas alta. Una vez que comence a automatizar mis pruebas, obtuve mejores resultados.
La clave para las pruebas automatizadas se puede resumir en:pruebe siempre buscando el mismo sıntoma y
ofrezca siempre datos consistentes a la orden “hg bisect”.
En mi tutorial de ejemplo anterior, la orden grep busca el sıntoma, y la construccion if toma el resultado de esta
prueba y verifica que siempre alimentamos con los mismos datos a la orden “hg bisect”. La funcion mytest los une
de una forma reproducible, logrando que cada prueba sea uniforme y consistente.
9.6.3. Verificar los resultados
Dado que la salida de la busqueda de “hg bisect” es tan buena como los datos ofrecidos por usted, no confıe en
esto como si fuera la verdad absoluta. Una forma sencilla de asegurarse es ejecutar manualmente su prueba a cada uno
de los siguientes conjuntos de cambios:
El conjunto de cambios que se reporto como la primera version erronea. Su prueba deberıa dar un reporte de
fallo.
El conjunto de cambios padre (cada padre, si es una fusion). Su prueba deberıa reportar este(os) conjunto(s) de
cambios como bueno(s).
Un hijo del conjunto de cambios. Su prueba deberıa reportar al conjunto de cambios hijo como malo.
9.6.4. Tener en cuenta la interferencia entre fallos
Es posible que su busqueda de un fallo pueda viciarse por la presencia de otro. Por ejemplo, digamos que su
programa se revienta en la revision 100, y que funciono correctamente en la revision 50. Sin su conocimiento, alguien
introdujo un fallo con consecuencias grandes en la revision 60, y lo arreglo en la revision 80. Sus resultados estarıandistorcionados de una o muchas formas.
Es posible que este fallo “enmascare” completamente al suyo, y que podrıa haberse revelado antes de que su propio
fallo haya tenido oportunidad de manifestarse. Si no puede saltar el otro fallo (por ejemplo, este evita que su proyecto
se arme o compile), y de esta forma no se pueda revisar si su fallo est e presente en un conjunto particular de cambios,
la orden “hg bisect” no podra ayudarle directamente. En cambio, puede marcar este conjunto de cambios como al
ejecutar “hg bisect --skip”.
107
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 118/204
Un problema distinto podrıa surgir si su prueba de la presencia de un fallo no es suficientemente especıfica. Si
usted busca “mi programa se revienta”, entonces tanto su fallo como el otro fallo sin relacion que terminan presentando
sıntomas distintos, podrıa terminar confundiendo a “hg bisect”.
Otra situacion en la cual serıa de mucha utilidad emplear a “hg bisect --skip” surge cuando usted no puede
probar una revision porque su proyecto estaba en una situacion de rompimiento y por lo tanto en un estado en el
cual era imposible hacer la prueba en esa revision, tal vez porque alguien consigno un cambio que hacıa imposible la
construccion del proyecto.
9.6.5. Acotar la busqueda perezosamente
Elegir los primeros “buenos” y “malos” conjuntos de cambios que marcaran los lımites de su busqueda en general
es sencillo, pero vale la pena discutirlo. Desde la perspectiva de “ hg bisect”, el conjunto de cambios “mas nuevo”
por convencion es el “malo”, y el otro conjunto de cambios es el “bueno”.
Si no recuerda cual podrıa ser el cambio “bueno”, para informar a “hg bisect”, podrıa hacer pruebas aleatorias
en el peor de los casos. Pero recuerde eliminar aquellos conjuntos de cambios que podr ıan no exhibir el fallo (tal vez
porque la caracterıstica donde se presenta el fallo todavıa no esta presente) y aquellos en los cuales otro fallo puede
enmascararlo (como se discutio anteriormente).
Incluso si termina “muy atras” por miles de conjuntos de cambios o meses de historial, solamente esta ra adicio-
nando unas pruebas contadas para “hg bisect”, gracias al comportamiento logarıtmico.
108
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 119/204
Capıtulo 10
Manejo de eventos en repositorios mediante
ganchos
Mercurial ofrece un poderoso mecanismo para permitirle a usted automatizar la ejecucion de acciones en respuesta
a eventos que ocurran en un repositorio. En algunos casos, usted puede controlar incluso la respuesta de Mercurial a
dichos eventos.
Mercurial usa el termino gancho para identificar estas acciones. Los ganchos son conocidos como “disparadores”
en algunos sistemas de control de revisiones, pero los dos nombres se refieren al mismo concepto.
10.1. Vistazo general de ganchos en Mercurial
A continuacion se encuentra una breve lista de los ganchos que Mercurial soporta. Volveremos a cada uno de estos
ganchos con mas detalle despues, en la seccion 10.8.
changegroup Es ejecutado luego de que un grupo de conjuntos de cambios ha sido tra ıdo al repositorio desde algun otro sitio.
commit Es ejecutado despues de la creacion de un conjunto de cambios en el repositorio local.
incoming Es ejecutado una vez por cada conjunto de cambios traıdo al repositorio desde otra ubicacion. Note la diferencia
respecto al gancho changegroup, que es ejecutado una vez por cada grupo de conjuntos de cambios que se
traiga.
outgoing Es ejecutado luego de que un grupo de conjuntos de cambios ha sido transmitido desde el repositorio.
prechangegroup Es ejecutado antes de iniciar la recepcion de un grupo de conjuntos de cambios en el repositorio.
precommit De control. Es ejecutado antes de iniciar una consignacion.
preoutgoing De control. Es ejecutado antes de iniciar la transmision de un grupo de conjuntos de cambios desde el repositorio.
pretag De control. Es ejecutado antes de crear una etiqueta.
retxnchangegroupDe control. Es ejecutado despu
´es de haber recibido un grupo de conjuntos de cambios en el repositorio local,pero antes de que la transaccion se complete y los cambios sean permanentes dentro del repositorio.
pretxncommit De control. Es ejecutado luego de la creacion de un conjunto de cambios en el repositorio local, pero antes de
que la transaccion que hace permanente el cambio sea completada.
preupdate De control. Es ejecutado antes de iniciar una actualizacion o fusion en el directorio de trabajo.
tag Es ejecutado despues de la creacion de una etiqueta.
109
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 120/204
update Es ejecutado despues de que termina una actualizacion o una fusion.
Cada uno de los ganchos cuya descripcion empieza con la frase “de control” tiene la facultad de determinar si una
actividad puede continuar. Si el gancho se ejecuta con exito, la actividad puede continuar; si falla, o bien la actividad
no es permitida, o se deshacen los cambios que se puedan haber llevado a cabo, dependiendo del gancho involucrado.
10.2. Ganchos y seguridad
10.2.1. Los ganchos se ejecutan con sus privilegios de usuario
Cuando usted ejecuta un comando de Mercurial en un repositorio, y el comando causa la ejecucion de un gancho,
dicho gancho se ejecuta en su sistema, en su cuenta de usuario, con sus privilegios. Ya que los ganchos son elementos
arbitrarios de codigo ejecutable, usted deberıa tratarlos con un nivel adecuado de desconfianza. No instale un gancho
a menos en que conf ıe en quien lo creo y en lo que el gancho hace.
En algunos casos, usted puede estar expuesto a ganchos que usted no instal o. Si usted usa Mercurial en un sistema
extrano, tenga en cuenta que Mercurial ejecutara los ganchos definidos en el fichero hgrc.
Si esta trabajando con un repositorio propiedad de otro usuario, Mercurial podra ejecutar los ganchos definidos
en el repositorio de dicho usuario, pero los ejecutara como “usted”. Por ejemplo, si usted jala (“hg pull”) desde ese
repositorio, y el .hg/hgrc define un gancho saliente (outgoing), dicho gancho se ejecuta bajo su cuenta de usuario,
aun cuando usted no es el propietario del repositorio.
Nota: Esto solo aplica si usted esta jalando desde un repositorio en un sistema
de ficheros local o de red. Si esta jalando a traves de http o ssh, cualquier gan-
cho saliente (outgoing) se ejecutara bajo la cuenta que esta ejecutando el proceso
servidor, en el servidor.
XXX Para ver que ganchos han sido definidos en un repositorio, use el comando “ hg config hooks”. Si usted
esta trabajando en un repositorio, pero comunicandose con otro que no le pertenece (por ejemplo, usando “hg pull”
o “hg incoming”), recuerde que los ganchos que debe considerar son los del otro repositorio, no los del suyo.
10.2.2. Los ganchos no se propagan
En Mercurial, no se hace control de revisiones de los ganchos, y no se propagan cuando usted clona, o jala de, un
repositorio. El motivo para esto es simple: un gancho es codigo ejecutable arbitrario. Se ejecuta bajo su identidad, consu nivel de privilegios, en su maquina.
Serıa extremadamente descuidado de parte de cualquier sistema distribuido de control de revisiones el implementar
control de revisiones para ganchos, ya que esto ofrecer ıa maneras f acilmente aprovechables de subvertir las cuentas
de los usuarios del sistema de control de revisiones.
Ya que Mercurial no propaga los ganchos, si usted esta colaborando con otras personas en un proyecto comun,
no deberıa asumir que ellos estan usando los mismos ganchos para Mercurial que usted usa, o que los de ellos est an
configurado correctamente. Usted deberıa documentar los ganchos que usted espera que la gente use.
En una intranet corporativa, esto es algo mas f acil de manejar, ya que usted puede, por ejemplo, proveer una
instalacion “estandar” de Mercurial en un sistema de ficheros NFS, y usar un fichero hgrc global para definir los
ganchos que veran todos los usuarios. Sin embargo, este enfoque tiene sus lımites; vea mas abajo.
10.2.3. Es posible hacer caso omiso de los ganchos
Mercurial le permite hacer caso omiso de la deficinion de un gancho, a traves de la redefinicion del mismo. Usted
puede deshabilitar el gancho fijando su valor como una cadena vacıa, o cambiar su comportamiento como desee.
Si usted instala un fichero hgrc a nivel de sistema o sitio completo que define algunos ganchos, debe entender que
sus usuarios pueden deshabilitar o hacer caso omiso de los mismos.
110
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 121/204
10.2.4. Asegurarse de que ganchos crıticos sean ejecutados
Algunas veces usted puede querer hacer respetar una polıtica, y no permitir que los demas sean capaces de evitarla.
Por ejemplo, usted puede tener como requerimiento que cada conjunto de cambios debe pasar un riguroso conjunto de
pruebas. Definir este requerimientos a traves de un gancho en un fichero hgrc global no servira con usuarios remotos
en computadoras portatiles, y por supuesto que los usuarios locales pueden evitar esto a voluntad haciendo caso omiso
del gancho.
En vez de eso, usted puede definir las polıticas para usar Mercurial de tal forma que se espere que los usuar-
ios propaguen los cambios a traves de un servidor “canonico” bien conocido que usted ha asegurado y configurado
apropiadamente.
Una manera de hacer esto es a traves de una combinacion de ingenierıa social y tecnologıa. Cree una cuenta de
acceso restringido; los usuarios pueden empujar cambios a traves de la red a los repositorios administrados por esta
cuenta, pero no podran ingresar a dicha cuenta para ejecutar ordenes en el interprete de comandos. En este escenario,
un usuario puede enviar un conjunto de cambios que contenga la porquerıa que el desee.
Cuando alguien empuja un conjunto de cambios al servidor del que todos jalan, el servidor probara el conjunto de
cambios antes de aceptarlo como permanente, y lo rechazara si no logra pasar el conjunto de pruebas. Si la gente solo
jala cambios desde este servidor de filtro, servira para asegurarse de que todos los cambios que la gente jala han sido
examinados automaticamente
10.3. Precauciones con ganchos pretxn en un repositorio de acceso com-partido
Si usted desea usar ganchos para llevar a cabo autom aticamente algun trabajo en un repositorio al que varias
personas tienen acceso compartido, debe tener cuidado con la forma de hacerlo.
Mercurial solo bloquea un repositorio cuando esta escribiendo al mismo, y solo las partes de Mercurial que escriben
al repositorio le prestan atencion a los bloqueos. Los bloqueos de escritura son necesarios para evitar que multiples
escritores simultaneos interfieran entre sı, corrompiendo el repositorio.
Ya que Mercurial tiene cuidado con el orden en que lee y escribe datos, no necesita adquirir un bloqueo cuando
desea leer datos del repositorio. Las partes de Mercurial que leen del repositorio nunca le prestan atenci on a los
bloqueos. Este esquema de lectura libre de bloqueos incremententa en gran medida el desempeno y la concurrencia.
Sin embargo, para tener un gran desempeno es necesario hacer sacrificios, uno de los cuales tiene el potencial de
causarle problemas a menos de que usted este consciente de el. Describirlo requiere algo de detalle respecto a comoMercurial anade conjuntos de cambios al repositorio y como lee esos cambios de vuelta.
Cuando Mercurial escribe metadatos, los escribe directamente en el fichero de destino. Primero escribe los datos
del fichero, luego los datos del manifiesto (que contienen punteros a los nuevos datos del fichero), luego datos de la
bitacora de cambios (que contienen punteros a los nuevos datos del manifiesto). Antes de la primera escritura a cada
fichero, se guarda un registro de donde estaba el final de fichero en su registro de transacciones. Si la transacci on
debe ser deshecha, Mercurial simplemente trunca cada fichero de vuelta al tamano que tenıa antes de que empezara la
transaccion.
Cuando Mercurial lee metadatos, lee la bitacora de cambios primero, y luego todo lo demas. Como un lector solo
accedera a las partes del manifiesto o de los metadatos de fichero que el puede ver en la bitacora de cambios, nunca
puede ver datos parcialmente escritos.
Algunos ganchos de control (pretxncommit y pretxnchangegroup ) se ejecutan cuando una transaccion esta casi
completa. Todos los metadatos han sido escritos, pero Mercurial aun puede deshacer la transaccion y hacer que los
datos recien escritos desaparezcan.Si alguno de estos ganchos permanece en ejecucion por mucho tiempo, abre una ventana de tiempo en la que un
lector puede ver los metadatos de conjuntos de cambios que aun no son permanentes y que no deberıa considerarse
que esten “realmante ahı”. Entre mas tiempo tome la ejecucion del gancho, mas tiempo estara abierta esta ventana.
111
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 122/204
10.3.1. Ilustracion del problema
En principio, un buen uso del gancho pretxnchangegroup serıa ensamblar y probar automaticamente todos los
cambios entrantes antes de que sean aceptados en un repositorio central. Esto le permitirıa a usted garantizar que nadie
pueda empujar cambios que “rompan el ensamblaje”. Pero si un cliente puede jalar cambios mientras estan siendo
probados, la utilidad de esta prueba es nula; alguien confiado puede jalar cambios sin probar, lo que potencialmente
podrıa romper su proceso de ensamblaje.
La respuesta tecnica mas segura frente a este retos es montar dicho repositorio “guardian” como unidireccional.
Permita que reciba cambios desde el exterior, pero no permita que nadie jale cambios de el (use el gancho preoutgoing
para bloquear esto). Configure un gancho changegroup para que si el ensamblaje o prueba tiene exito, el gancho em-
puje los nuevos cambios a otro repositorio del que la gente pueda jalar.
En la practica, montar un cuello de botella centralizado como este a menudo no es una buena idea, y la visibilidad
de las transacciones no tiene nada que ver con el problema. A medida que el tamano de un proyecto—y el tiempo
que toma ensamblarlo y probarlo—crece, usted se acerca rapidamente a un lımite con este enfoque “pruebe antes de
comprar”, en el que tiene mas conjuntos de cambios a probar que tiempo para ocuparse de ellos. El resultado inevitable
es frustracion para todos los que esten involucrados.
Una aproximacion que permite manejar mejor el crecimiento es hacer que la gente ensamble y pruebe antes de
empujar, y ejecutar el ensamble y pruebas automaticas centralmente despu´ es de empujar, para asegurarse de que todo
este bien. La ventaja de este enfoque es que no impone un lımite a la rata en la que un repositorio puede aceptar
cambios.
10.4. Tutorial corto de uso de ganchos
Escribir un gancho para Mercurial es f acil. Empecemos con un gancho que se ejecute cuando usted termine un
“hg commit”, y simplemente muestre el hash del conjunto de cambios que usted acaba de crear. El gancho se lla-
mara commit.
1 $ hg init hook-test
2 $ cd hook-test
3 $ echo ’[hooks]’ >> .hg/hgrc
4 $ echo ’commit = echo committed $HG_NODE’ >> .hg/hgrc
5 $ cat .hg/hgrc
6 [hooks]
7 commit = echo committed $HG_NODE
8 $ e c h o a > a
9 $ hg add a
10 $ hg commit -m ’testing commit hook’
11 committed 233120f5d09c76e782c6ea86ccee729e735bf48f
Figura 10.1: Un gancho simple que se ejecuta al hacer la consignacion de un conjunto de cambios
Todos los ganchos siguen el patron del ejemplo 10.1. Usted puede anadir una entrada a la seccion [hooks] de su
fichero hgrc. A la izquierda esta el nombre del evento respecto al cual dispararse; a la derecha est a la accion a llevar
a cabo. Como puede ver, es posible ejecutar cualquier orden de la l ınea de comandos en un gancho. Mercurial le pasainformacion extra al gancho usando variables de entorno (busque HG NODE en el ejemplo).
10.4.1. Llevar a cabo varias acciones por evento
A menudo, usted querra definir mas de un gancho para un tipo de evento particular, como se muestra en el ejem-
plo 10.2. Mercurial le permite hacer esto anadiendo una extensi ´ on al final del nombre de un gancho. Usted extiende
112
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 123/204
el nombre del gancho poniendo el nombre del gancho, seguido por una parada completa (el caracter “ .”), seguido
de algo mas de texto de su eleccion. Por ejemplo, Mercurial ejecutara tanto commit.foo como commit.bar cuando
ocurra el evento commit.
1 $ echo ’commit.when = echo -n "date of commit: "; date’ >> .hg/hgrc
2 $ echo a >> a
3 $ hg commit -m ’i have two hooks’4 committed df4f3f8972104d2a43d114e51edd05719efccd42
5 date of commit: Tue Feb 10 18:23:23 GMT 2009
Figura 10.2: Definicion de un segundo gancho commit
Para dar un orden bien definido de ejecucion cuando hay multiples ganchos definidos para un evento, Mercurial
ordena los ganchos de acuerdo a su extension, y los ejecuta en dicho orden. En el ejemplo de arribam commit.bar se
ejecutara antes que commit.foo, y commit se ejecutara antes de ambos.
Es una buena idea usar una extension descriptiva cuando usted define un gancho. Esto le ayudara a recordar para
que se usa el gancho. Si el gancho falla, usted recibir a un mensaje de error que contiene el nombre y la extensi on del
gancho, ası que usar una extension descriptiva le dara una pista inmediata de porque el gancho fallo (vea un ejemplo
en la seccion 10.4.2).
10.4.2. Controlar cuando puede llevarse a cabo una actividad
En los ejemplos anteriores, usamos el gancho commit, que es ejecutado despues de que se ha completado una
consignacion. Este es uno de los varios ganchos que Mercurial ejecuta luego de que una actividad termina. Tales
ganchos no tienen forma de influenciar la actividad como tal.
Mercurial define un numero de eventos que ocurren antes de que una actividad empiece; o luego de que empiece,
pero antes de que termine. Los ganchos que se disparan con estos eventos tienen la capacidad adicional de elegir si la
actividad puede continuar, o si su ejecucion es abortada.
El gancho pretxncommit se ejecuta justo antes de que una consignacion se ejecute. En otras palabras, los metadatos
que representan el conjunto de cambios han sido escritos al disco, pero no se ha terminado la transaccion. El gancho
pretxncommit tiene la capacidad de decidir si una transaccion se completa, o debe deshacerse.Si el gancho pretxncommit termina con un codigo de salida de cero, se permite que la transaccion se complete; la
consignacion termina; y el gancho commit es ejecutado. Si el gancho pretxncommit termina con un codigo de salida
diferente de cero, la transaccion es revertida; los metadatos representando el conjunto de cambios son borrados; y el
gancho commit no es ejecutado.
El gancho en el ejemplo 10.3 revisa si el mensaje de consignacion contiene el ID de algun fallo. Si lo contiene, la
consignacion puede continuar. Si no, la consignacion es cancelada.
10.5. Escribir sus propios ganchos
Cuando usted escriba un gancho, puede encontrar util el ejecutar Mercurial o bien pasandole la opcion -v, o con el
valor de configuracion verbose fijado en “true” (verdadero). Cuando lo haga, Mercurial imprimira un mensaje antes
de llamar cada gancho.
10.5.1. Escoger como debe ejecutarse su gancho
Usted puede escribir un gancho que funcione como un programa normal —tıpicamente un guion de lınea de
comandos—o como una funcion de Python que se ejecuta dentro del proceso Mercurial.
Escribir un gancho como un programa externo tiene la ventaja de que no requiere ning un conocimiento del fun-
cionamiento interno de Mercurial. Usted puede ejecutar comandos Mercurial normales para obtener la informcion
113
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 124/204
1 $ cat check_bug_id
2 #!/bin/sh
3 # check that a commit comment mentions a numeric bug id
4 hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]"
5 $ echo ’pretxncommit.bug_id_required = ./check_bug_id $HG_NODE’ >> .hg/hgrc
6 $ echo a >> a
7 $ hg commit -m ’i am not mentioning a bug id’8 transaction abort!
9 rollback completed
10 abort: pretxncommit.bug_id_required hook exited with status 1
11 $ hg commit -m ’i refer you to bug 666’
12 committed d558e8617cbdf0b482db27a79d17f9a28af4701f
13 date of commit: Tue Feb 10 18:23:23 GMT 2009
Figura 10.3: Uso del gancho pretxncommit para controlar consignaciones
extra que pueda necesitar. La contraparte de esto es que los ganchos externos son mas lentos que los ganchos internos
ejecutados dentro del proceso.Un gancho Python interno tiene acceso completo a la API de Mercurial, y no se “externaliza” a otro proceso,
ası que es inherentemente mas rapido que un gancho externo. Adicionalmente es mas f acil obtener la mayorıa de
la informacion que un gancho requiere a traves de llamadas directas a la API de Mercurial que hacerlo ejecutando
comandos Mercurial.
Si se siente a gusto con Python, o requiere un alto desempeno, escribir sus ganchos en Python puede ser una buena
eleccion. Sin embargo, cuando usted tiene un gancho bastante directo por escribir y no le importa el desempe no (el
caso de la mayorıa de los ganchos), es perfectamente admisible un guion de lınea de comandos.
10.5.2. Parametros para ganchos
Mercurial llama cada gancho con un conjunto de parametros bien definidos. En Python, un parametro se pasa
como argumento de palabra clave a su funcion de gancho. Para un programa externo, los parametros son pasados
como variables de entornos.
Sin importar si su gancho esta escrito en Python o como guion de lınea de comandos, los nombres y valores de
los parametros especıficos de los ganchos seran los mismos. Un parametro booleano sera representado como un valor
booleano en Python, pero como el numero 1 (para “verdadero”) o 0 (para falso) en una variable de entorno para un
gancho externo. Si un parametro se llama foo, el argumento de palabra clave para un gancho en Python tambien se
llamara foo, mientras que la variable de entorno para un gancho externo se llamara HG FOO.
10.5.3. Valores de retorno de ganchos y control de actividades
Un gancho que se ejecuta exitosamente debe terminar con un codigo de salida de cero, si es externo, o retornar
el valor booleano “falso”, si es interno. Un fallo se indica con un codigo de salida diferente de cero desde un gancho
externo, o un valor de retorno booleano “verdadero”. Si un gancho interno genera una excepcion, se considera que el
gancho ha fallado.
Para los ganchos que controlan si una actividad puede continuar o no, cero/falso quiere decir “permitir”, mientras
que no-cero/verdadero/excepcion quiere decir “no permitir”.
10.5.4. Escribir un gancho externo
Cuando usted define un gancho externo en su fichero hgrc y el mismo es ejecutado, dicha definicion pasa a su
interprete de comandos, que hace la interpretacion correspondiente. Esto significa que usted puede usar elementos
114
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 125/204
normales del interprete en el cuerpo del gancho.
Un gancho ejecutable siempre es ejecutado con su directorio actual fijado al directorio ra ız del repositorio.
Cada parametro para el gancho es pasado como una variable de entorno; el nombre esta en mayusculas, y tiene
como prefijo la cadena “HG ”.
Con la excepcion de los parametros para los ganchos, Mercurial no define o modifica ninguna variable de entorno
al ejecutar un gancho. Es util recordar esto al escribir un gancho global que podrıa ser ejecutado por varios usuarios
con distintas variables de entorno fijadas. En situaciones con multiples usuarios, usted no deberıa asumir la existenciade ninguna variable de entorno, ni que sus valores sean los mismos que tenıan cuando usted probo el gancho en su
ambiente de trabajo.
10.5.5. Indicar a Mercurial que use un gancho interno
La sintaxis para definir un gancho interno en el fichero hgrc es ligeramente diferente de la usada para un gan-
cho externo. El valor del gancho debe comenzar con el texto “ python:”, y continuar con el nombre completamente
cualificado de un objeto invocable que se usara como el valor del gancho.
El modulo en que vive un gancho es importado automaticamente cuando se ejecuta un gancho. Siempre que usted
tenga el nombre del modulo y la variable de entorno PYTHONPATH ajustada adecuadamente, todo deberıa funcionar sin
problemas.
El siguiente fragmento de ejemplo de un fichero hgrc ilustra la sintaxis y significado de los conceptos que
acabamos de describir.
1 [hooks]
2 commit.example = python:mymodule.submodule.myhook
Cuando Mercurial ejecuta el gancho commit.example, importa mymodule.submodule , busca el objeto invocable
llamado myhook, y lo invoca (llama).
10.5.6. Escribir un gancho interno
El gancho interno mas sencillo no hace nada, pero ilustra la estructura basica de la API1 para ganchos:
1 def myhook(ui, repo, **kwargs):
2 pass
El primer argumento para un gancho Python siempre es un objeto mercurial.ui.ui. El segundo es un objeto repos-
itorio; de momento, siempre es una instancia de mercurial.localrepo.localrepository . Despues de estos dos
argumentos estan los argumentos de palabra clave. Los argumentos que se pasen dependeran del tipo de gancho que se
este llamando, pero un gancho siempre puede ignorar los argumentos que no le interesen, relegandolos a un diccionario
de argumentos por palabras clave, como se hizo arriba con **kwargs.
10.6. Ejemplos de ganchos
10.6.1. Escribir mensajes de consignacion significativos
Es difıcil de imaginar un mensaje de consignacion util y al mismo tiempo muy corto. El simple gancho pretxncommitde la figura 10.4 evitara que usted consigne un conjunto de cambios con un mensaje de menos de 10 bytes de longitud.
1N. del T. Application Progamming Interface, Interfaz para Programacion de Aplicaciones
115
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 126/204
1 $ cat .hg/hgrc
2 [hooks]
3 pretxncommit.msglen = test ‘hg tip --template {desc} | wc -c‘ -ge 10
4 $ e c h o a > a
5 $ hg add a
6 $ hg commit -A -m ’too short’
7 transaction abort!8 rollback completed
9 abort: pretxncommit.msglen hook exited with status 1
10 $ hg commit -A -m ’long enough’
Figura 10.4: Un gancho que prohıbe mensajes de consignacion demasiado cortos
10.6.2. Comprobar espacios en blanco finales
Un uso interesante para ganchos relacionados con consignaciones es ayudarle a escribir codigo mas limpio. Un
ejemplo simple de “codigo mas limpio” es la regla de que un cambio no debe anadir lıneas de texto que contengan
“espacios en blanco finales”. El espacio en blanco final es una serie de caracteres de espacio y tabulacion que seencuentran al final de una lınea de texto. En la mayorıa de los casos, el espacio en blanco final es innecesario, ruido
invisible, pero ocasionalmente es problematico, y la gente en general prefiere deshacerse de el.
Usted puede usar cualquiera de los ganchos precommit o pretxncommit para revisar si tiene el problema de los
espacios en blanco finales. Si usa el gancho precommit, el gancho no sabra que ficheros se estan consignando, por lo
que se tendra que revisar cada fichero modificado en el repositorio para ver si tiene espacios en blanco finales. Si usted
solo quiere consignar un cambio al fichero foo, y el fichero bar contiene espacios en blanco finales, hacer la revision
en el gancho precommit evitara que usted haga la consignacion de foo debido al problem en bar. Este no parece el
enfoque adeucado.
Si usted escogiera el gancho pretxncommit, la revision no ocurrirıa sino hasta justo antes de que la transaccion
para la consignacion se complete. Esto le permitira comprobar por posibles problemas solo en los ficheros que seran
consignados. Sin embargo, si usted ingreso el mensaje de consignacion de manera interactiva y el gancho falla, la
transaccion sera deshecha; usted tendra que reingresar el mensaje de consignacion luego de que corrija el problema
con los espacios en blanco finales y ejecute “hg commit” de nuevo.
1 $ cat .hg/hgrc
2 [hooks]
3 pretxncommit.whitespace = hg export tip | (! egrep -q ’ˆ\+.*[ \t]$’)
4 $ e c h o ’ a ’ > a
5 $ hg commit -A -m ’test with trailing whitespace’
6 adding a
7 transaction abort!
8 rollback completed
9 abort: pretxncommit.whitespace hook exited with status 1
10 $ echo ’a’ > a
11 $ hg commit -A -m ’drop trailing whitespace and try again’
Figura 10.5: Un gancho simple que revisa si hay espacios en blanco finales
La figura 10.5 presenta un gancho pretxncommit simple que comprueba la existencia de espacios en blanco
finales. Este gancho es corto, pero no brinda mucha ayuda. Termina con un codigo de salida de error si un cambio
anade una lınea con espacio en blanco final a cualquier fichero, pero no muestra ninguna informacion que pueda ser
116
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 127/204
util para identificar el fichero o la lınea de texto origen del problema. Tambien tiene la agradable propiedad de no
prestar atencion a las lıneas que no sufrieron modificaciones; solo las lıneas que introducen nuevos espacios en blanco
finales causan problemas.
1 $ cat .hg/hgrc
2 [hooks]
3 pretxncommit.whitespace = .hg/check_whitespace.py4 $ e c h o ’ a ’ > > a
5 $ hg commit -A -m ’add new line with trailing whitespace’
6 a, line 2: trailing whitespace added
7 commit message saved to .hg/commit.save
8 transaction abort!
9 rollback completed
10 abort: pretxncommit.whitespace hook exited with status 1
11 $ sed -i ’s, *$,,’ a
12 $ hg commit -A -m ’trimmed trailing whitespace’
13 a, line 2: trailing whitespace added
14 commit message saved to .hg/commit.save
15 transaction abort!
16 rollback completed17 abort: pretxncommit.whitespace hook exited with status 1
Figura 10.6: Un mejor gancho para espacios en blanco finales
El ejemplo de la figura 10.6 es mucho mas complejo, pero tambien mas util. El gancho procesa un diff unificado
para revisar si alguna lınea anade espacios en blanco finales, e imprime el nombre del fichero y el numero de lınea
de cada ocurrencia. Aun mejor, si el cambio anade espacios en blanco finales, este gancho guarda el mensaje de
consignacion e imprime el nombre del fichero en el que el mensaje fue guardado, antes de terminar e indicarle a
Mercurial que deshaga la transaccion, para que uste pueda usar “hg commit -l nombre fichero” para reutilizar
el mensaje de consignacion guardado anteriormente, una vez usted haya corregido el problema.
Como anotacion final, note en la figura 10.6 el uso de la caracterıstica de edicion in-situ deperl
para eliminar losespacios en blanco finales en un fichero. Esto es lo suficientemente conciso y poderoso para que lo presente aquı.
1 perl -pi -e ’s,\s+$,,’ nombre fichero
10.7. Ganchos adicionales
Mercurial se instala con varios ganchos adicionales. Usted puede encontrarlos en el directorio hgext del arbol de
ficheros fuente de Mercurial. Si usted esta usando un paquete binario de Mercurial, los ganchos estaran ubicados en el
directorio hgext en donde su instalador de paquetes haya puesto a Mercurial.
10.7.1. acl—control de acceso a partes de un repositorio
La extension acl le permite controlar a que usuarios remotos les esta permitido empujar conjuntos de cambios a
un servidor en red. Usted puede proteger cualquier porcion de un repositorio (incluyendo el repositorio completo), de
tal manera que un usuario remoto especıfico pueda empujar cambios que no afecten la porcion protegida.
Esta extension implementa control de acceso basado en la identidad del usuario que empuja los conjuntos de
cambios, no en la identidad de quien hizo la consignacion de los mismos. Usar este gancho tiene sentido solo si se
tiene un servidor adecuadamente asegurado que autentique a los usuarios remotos, y si usted desea segurarse de que
solo se le permita a ciertos usuarios empujar cambios a dicho servidor.
117
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 128/204
Configuracion del gancho acl
Para administrar los conjuntos de cambios entrantes, se debe usar el gancho acl como un gancho de tipo pretxnchangegro
Esto le permite ver que ficheros son modificados por cada conjunto de cambios entrante, y deshacer el efecto de un
grupo de conjuntos de cambios si alguno de ellos modifica algun fichero “prohibido”. Ejemplo:
1 [hooks]
2 pretxnchangegroup.acl = python:hgext.acl.hook
La extension acl es configurada mediante tres secciones.
La seccion [acl] solo tiene una entrada, sources2, que lista las fuentes de los conjuntos de cambios entrantes a
las que el gancho debe prestar atencion. Usualmente usted no necesita configurar esta seccion.
serve Controlar conjuntos de cambios entrantes que estan llegando desde un repositorio a traves de http o ssh. Este es
el valor por defecto de sources, y usualmente es el unico valor de configuracion que necesitara para este ıtem.
pull Controlar conjuntos de cambios entrantes que lleguen vıa un pull (jalado) desde un repositorio local.
push Controlar conjuntos de cambios entrantes que lleguen vıa un push (empuje) desde un repositorio local.
bundle Controlar conjuntos de cambios entrantes que lleguen desde otro repositorio a traves de un paquete.
La seccion [acl.allow] controla los usuarios a los que les esta permitido anadir conjuntos de cambios al repos-
itorio. Si esta seccion no esta presente, se le permite acceso a todos los usuarios excepto a los que se les haya negado
explıcitamente el acceso. Si esta seccion no esta presente, se niega el acceso a todos los usuarios excepto a todos a los
que se les haya permitido de manera explıcita (ası que una seccion vacıa implica que se niega el acceso a todos los
usuarios).
La seccion [acl.deny] determina a que usuarios no se les permite anadir conjuntos de cambios al repositorio. Si
esta seccion no esta presente o esta vacıa, no se niega el acceso a ningun usuario.
La sintaxis para los ficheros [acl.allow] y [acl.deny] es identica. A la izquierda de cada entrada se encuentra
un patron glob que asocia ficheros o directorios, respecto a la raız del repositorio; a la derecha, un nombre usuario.
En el siguiente ejemplo, el usuario escritordoc solo puede empujar cambios al directorio docs del repositorio,
mientras que practicante puede enviar cambios a cualquier fichero o directorio excepto fuentes/sensitivo .
1 [acl.allow]2 docs/** = escritordoc
3
4 [acl.deny]
5 fuentes/sensitivo/** = practicante
Pruebas y resolucion de problemas
Si usted desea probar el gancho acl, ejecutelo habilitando la opcion de salida de depuracion habilitada. Ya que
usted probablemente lo estara ejecutando en un servidor donde no es conveniente (o incluso posible) pasar la opcion
--debug, no olvide que usted puede habilitar la salida de depuracion en su hgrc:
1 [ui]
2 debug = true
Con esto habilitado, el gancho acl imprimira suficiente informacion para permitirle saber porque esta permitiendo o
denegando la operacion de empujar a usuarios especıficos.
2N. del T. Fuentes.
118
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 129/204
10.7.2. bugzilla—integracion con Bugzilla
La extension bugzilla anade un comentario a un fallo Bugzilla siempre que encuentre una referencia al ID de
dicho fallo en un mensaje de consignacion. Usted puede instalar este gancho en un servidor compartido, para que cada
vez que un usuario remoto empuje cambios al servidor, el gancho sea ejecutado.
Se anade un comentario al fallo que se ve ası (usted puede configurar los contenidos del comentario—vea mas
abajo):
1 Changeset aad8b264143a, made by Joe User <[email protected]> in
2 the frobnitz repository, refers to this bug.
3
4 For complete details, see
5 http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
6
7 Changeset description:
8 Fix bug 10483 by guarding against some NULL pointers
El valor de este gancho se encuentra en que automatiza el proceso de actualizar un fallo cuando un conjunto de cambios
se refiera a el. Si usted configura este gancho adecuadamente, hara f acil para la gente navegar directamente desde un
fallo Bugzilla a un conjunto de cambios que se refiere a ese fallo.Usted puede usar el codigo de este gancho como un punto de partida para otras recetas de integraci on con Bugzilla
aun mas exoticas. Aca hay algunas posibilidades:
Requerir que cada conjunto de cambios tenga un ID de fallo en su mensaje de consignacion. En este caso, usted
querra configurar el gancho como uno de tipo pretxncommit. Esto le permitira al gancho rechazar cambios que
no contiene IDs de fallos.
Permitir a los conjuntos de cambios entrantes modificar automaticamente el estado de un fallo, ası como simple-
mente anadir un comentario. Por ejemplo, el gancho podrıa reconocer la cadena “corregido fallo 31337” como
la senal de que deberıa actualizar el estado del fallo 31337 a “requiere pruebas”.
Configuracion del gancho bugzilla
Usted deberıa configurar este gancho en el hgrc de su servidor como un gancho incoming3, por ejemplo comosigue:
1 [hooks]
2 incoming.bugzilla = python:hgext.bugzilla.hook
Debido a la naturaleza especializada de este gancho, y porque Bugzilla no fue escrito con este tipo de integracion
en mente, configurar este gancho es un proceso algo complejo.
Antes de empezar, usted debe instalar la interfaz de Python para MySQL en los sistemas en los que se vaya a
ejecutar el gancho. Si no esta disponible como paquete binario para su sistema, usted puede descargar el paquete
desde [Dus].
La informacion para configurar este gancho se ubica en la seccion [bugzilla] de su hgrc.
version La version de Bugzilla instalada en el servidor. El esquema de base de datos que Bugzilla usa cambia ocasion-almente, ası que este gancho debe saber exactamente que esquema usar. A la fecha, la unica version soportada
es la 2.16.
host El nombre de maquina (hostname) del servidor MySQL que almacena sus datos Bugzilla. La base de datos debe
ser configurada para permitir conexiones desde las maquinas en las que usted ejecute el gancho bugzilla.
3N. del T. Entrante.
119
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 130/204
user El nombre de usuario que se usara para conectarse al servidor MySQL. La base de datos debe ser configurada
para permitir a dicho usuario conectarse desde cualquiera de las maquinas en las que se ejecute el gancho
bugzilla. Este usuario debe tener acceso y poder modificar las tablas de Bugzilla. El valor por defecto para
este ıtem es bugs, que es el nombre estandar del usuario para Bugzilla en una base de datos MySQL.
password La contrasena MySQL para el usuario configurado anteriormente. Esta es almacenada como texto plano, ası que
usted debera asegurarse de que los usuarios no autorizados no puedan leer el fichero hgrc en donde usted guarda
esta informacion.
db El nombre de la base de datos Bugzilla en el servidor MySQL. El nombre por defecto para este ıtem es bugs,
que es el nombre estandar de la base de datos MySQL en donde Bugzilla almacena sus datos.
notify Si usted desea que Bugzilla envıe un correo de notificacion a los suscriptores despues de que el gancho haya
anadido un comentario a un fallo, necesitara que este gancho ejecute un comando siempre que actualice la base
de datos. El comando que se ejecute depende de en donde haya sido instalado Bugzilla, pero tıpicamente se
vera ası, si usted ha instalado Bugzilla en /var/www/html/bugzilla :
1 cd /var/www/html/bugzilla && ./processmail %s [email protected]
El programa processmail de Bugzilla espera recibir un ID de fallo (el gancho reemplaza “ %s” por el ID del
fallo) y una direccion de correo. Tambien espera poder escribir a ciertos ficheros en el directorio en que seejecuta. Si Bugzilla y este gancho no estan instalados en la misma maquina, usted debera encontrar una manera
de ejecutar processmail en el servidor donde esta instalado Bugzilla.
Asociar nombres de consignadores a nombres de usuario Bugzilla
Por defecto, el gancho bugzilla trata de usar la direccion de correo electronico de la persona que hizo la
consignacion del conjunto de cambios como el nombre de usuario Bugzilla con el cual debe actualizar el fallo. Si
esto no se ajusta a sus necesidades, es posible asociar direcciones de correo a nombres de usuario Bugzilla usando una
seccion [usermap].
Cada ıtem en la seccion [usermap] contiene una direccion de correo electronico a la izquierda, y un nombre de
usuario Bugzilla a la derecha.
1 [usermap]2 [email protected] = jane
Usted puede mantener los datos de [usermap] en un fichero hgrc, o decirle al gancho bugzilla que lea la informa-
cion desde un fichero usermap externo. En este caso, usted puede almacenar los datos de usermap en (por ejemplo) un
repositorio modificable por los usuarios. Esto hace posible para sus usuarios mantener sus propias entradas usermap.
El fichero hgrc principal se verıa ası:
1 # fichero hgrc normal se refiere a un fichero usermap externo
2 [bugzilla]
3 usermap = /home/hg/repos/userdata/bugzilla-usermap.conf
Mientras que el fichero usermap al que se hace referencia se verıa ası:
1 # bugzilla-usermap.conf - dentro de un repositorio hg
2 [usermap]
3 [email protected] = steph
120
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 131/204
Configurar el texto que se a ˜ nade a un fallo
Usted puede configurar el texto que este gancho anade como comentario; usted los especifica como una plantilla
Mercurial. Varias entradas hgrc (aun en la seccion [bugzilla]) controlan este comportamiento.
strip La cantidad de elementos iniciales de ruta a remover de un nombre de ruta del repositorio para construir una ruta
parcial para una URL. Por ejemplo, si los repositorios en su servidor se ubican en /home/hg/repos, y usted
tiene un repositorio cuya ruta es /home/hg/repos/app/tests , entonces fijar strip a 4 resultara en una rutaparcial de app/tests. El gancho hara disponible esta ruta parcial cuando expanda una plantilla, como webroot.
template El texto de la plantilla a usar. En adicion a las variables usuales relacionadas con conjuntos de cambios, esta
plantilla puede usar hgweb (el valor del ıtem de configuracion hgweb de arriba) y webroot (la ruta construida
usando strip arriba).
Adicionalmente, usted puede anadir un ıtem baseurl a la seccion [web] de su hgrc. El gancho bugzilla pub-
licara esto cuando expanda una plantilla, como la cadena base a usar cuando se construya una URL que le permita a
los usuarios navegar desde un comentario de Bugzilla a la vista de un conjunto de cambios. Ejemplo:
1 [web]
2 baseurl = http://hg.domain.com/
A continuacion se presenta un ejemplo completo de configuracion para el gancho bugzilla.
1 [bugzilla]
2 host = bugzilla.example.com
3 password = mypassword
4 version = 2.16
5 # server-side repos live in /home/hg/repos, so strip 4 leading
6 # separators
7 strip = 4
8 hgweb = http://hg.example.com/
9 usermap = /home/hg/repos/notify/bugzilla.conf
10 template = Changeset {node|short}, made by {author} in the {webroot}11 repo, refers to this bug. nFor complete details, see
12 {hgweb}{webroot}?cmd=changeset;node={node|short} nChangeset
13 description: n t{desc|tabindent}
Pruebas y resolucion de problemas
Los problemas mas comunes que aparecen en la configuracion del gancho bugzilla suelen estar relacionados con
la ejecucion del guion de Bugzilla processmail y la asociacion de nombres de consignadores a nombres de usuario.
Recuerde que en la seccion 10.7.2 arriba el usuario que ejecuta el proceso Mercurial en el servidor es tambien
el usuario que ejecutara el guion processmail. El guion processmail algunas veces hace que Bugzilla escriba en
ficheros en su directorio de configuracion, y los ficheros de configuracion de Bugzilla usualmente son propiedad del
usuario bajo el cual se ejecuta el servidor web.
Usted puede hacer que processmail sea ejecutado con la identidad del usuario adecuado usando el comando
sudo. A continuacion se presenta una entrada de ejemplo para un fichero sudoers.
1 hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s
Esto permite que el usuario hg user ejecute el programa processmail-wrapper con la identidad del usuario httpd user.
Esta indireccion a traves de un guion envoltorio es necesaria, porque processmail espera que al ser ejecutado su
directorio actual sea aquel en el cual se instalo Bugzilla; usted no puede especificar ese tipo de condicion en un fichero
sudoers. Los contenidos del giuon envoltorio son simples:
121
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 132/204
1 #!/bin/sh
2 cd ‘dirname $0‘ && ./processmail "$1" [email protected]
No parece importar que direccion de correo se le pase a processmail.
Si su [usermap] no es configurada correctamente, los usuarios veran un mensaje de error del gancho bugzilla
cuando empujen cambios al servidor. El mensaje de error se ver a ası:
1 cannot find bugzilla user id for [email protected]
Lo que esto quiere decir es que la direccion del consignador, [email protected] , no es un nombre de
usuario Bugzilla valido, ni tiene una entrada en su [usermap] que lo asocie con un nombre de usuario valido Bugzilla.
10.7.3. notify—enviar notificaciones de correo electronico
Aunque el servidor web embebido de Mercurial provee notificaciones de cambios en cada repositorio, muchas
personas prefieren recibir las notificaciones de cambios vıa correo electronico. El gancho notify4 le permite a usted
enviar notificaciones a un conjunto de direcciones de correo cuando lleguen conjuntos de cambios en los que los
subscriptores esten interesados.
De la misma forma que con el gancho bugzilla, el gancho notify esta orientado a plantillas, ası que usted puedepersonalizar los contenidos del mensaje de notificacion que se envıa.
Por defecto, el gancho notify incluye un diff de cada conjunto de cambios que se envıa; usted puede limitar el
tamano del diff, o desactivar completamente esta caracterıstica. Es util para permitir a los subscriptores revisar los
cambios inmediatamente, en vez de tener que hacer clic para visitar una URL.
Configuracion del gancho notify
Usted puede configurar el gancho notify para enviar un mensaje de correo por conjunto de cambios entrante, o
uno por grupo entrante de conjuntos de cambios (todos los que llegaron en un unico empuje o jalado).
1 [hooks]
2 # enviar un correo por grupo de cambios
3 changegroup.notify = python:hgext.notify.hook4 # enviar un correo por cambio
5 incoming.notify = python:hgext.notify.hook
La informacion para configurar este gancho se ubica en la seccion [notify] de un fichero hgrc.
test Por defecto, este gancho no envıa correos en absoluto; en vez de eso, imprime el mensaje que se enviarıa. Fije
este ıtem en false para permitir el envıo de correos. El motivo por el que el envıo de correos esta desactivado es
que hacen falta varios intentos para configurar esta extension exactamente como usted desea, y serıa maleducado
enviar a los subscriptores una cantidad de notificaciones “rotas” mientras usted depura su configuracion.
config La ruta a un fichero de configuracion que contiene informacion de subscripcion. Esto se mantiene separado
del hgrc principal para que usted pueda mantenerlo en un repositorio. La gente puede clonar ese repositorio,
actualizar sus subscripciones, y empujar los cambios de vuelta a su servidor.
strip La cantidad de caracteres iniciales de separacion de ruta a remover de la ruta del repositorio, al decidir si un
repositorio tiene subscriptores. Por ejemplo, si los repositorios en su servidor estan en /home/hg/repos, y
notify esta trabajando con un repositorio llamado /home/hg/repos/shared/test , fijar strip a 4 hara que
notify elimine las partes iniciales de la ruta hasta shared/test, y asociara los subscriptores frente a dicha
ruta.
4N. del T. Notificacion.
122
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 133/204
template El texto de plantilla a usar cuando se envıen mensajes. Especifica los contenidos de la cabecera del mensaje y el
cuerpo del mismo.
maxdiff El numero maximo de lıneas de datos de diff a anadir al final de un mensaje. Si la longitud de un diff es mayor
a eso, se trunca. Por defecto, esta fijado en 300. Fije esto a 0 para omitir los diffs en los correos de notificacion.
sources Una lista de fuentes de conjuntos de cambios a considerar. Esto le permite a usted indicar a notify para que
solo envıe correos acerca de cambios que usuarios remotos hayan empujado al repositorio vıa un servidor, porejemplo. Vea la seccion 10.8.3 para las fuentes que usted puede especificar aquı.
Si usted fija el ıtem baseurl en la seccion [web], usted lo puede usar en una plantilla; estara disponible como
webroot.
A continuacion se presenta un ejemplo completo de configuracion para el gancho notify.
1 [notify]
2 # enviar correo
3 test = false
4 # datos de subscriptores estan en el repositorio notify
5 config = /home/hg/repos/notify/notify.conf
6 # repos estan en /home/hg/repos on server, ası que elimine 4
7 # caracteres"/"8 strip = 4
9 template = X-Hg-Repo: {webroot}10 Subject: {webroot}: {desc|firstline|strip}11 From: {author}12
13 changeset {node|short} in {root}14 details: {baseurl}{webroot}?cmd=changeset;node={node|short}15 description:
16 {desc|tabindent|strip}17
18 [web]
19 baseurl = http://hg.example.com/
Esto producira un mensaje que se vera como el siguiente:
1 X-Hg-Repo: tests/slave
2 Subject: tests/slave: Handle error case when slave has no buffers
3 Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT)
4
5 changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
6 details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5
7 description:
8 Handle error case when slave has no buffers
9 diffs (54 lines):
10
11 diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
12 --- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700
13 +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700
14 @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h)
15 [...snip...]
123
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 134/204
Pruebas y resolucion de problemas
No olvide que por defecto, la extension notify no enviar a ning´ un correo electr onico hasta que usted la configure
explıcitamente para hacerlo, fijando el valor de test a false. Hasta que usted haga eso, simplemente se imprimira el
mensaje que se enviar ıa.
10.8. Informacion para escritores de ganchos
10.8.1. Ejecucion de ganchos internos
Un gancho interno es llamado con argumentos de la siguiente forma:
1 def myhook(ui, repo, **kwargs):
2 pass
El parametro ui es un objeto mercurial.ui.ui. El parametro repo es un objeto mercurial.localrepo.localrepository .
Los nombres y valores de los parametros en **kwargs dependen del gancho que se invoque, con las siguientes carac-
terısticas en comun:
Si hay un parametro llamado node o parentN , contendra un ID hexadecimal de un conjunto de cambios. La
cadena vacıa es usada para representar un “ID de conjunto de cambios nulo” en vez de una cadena de ceros.
Si hay un parametro llamado url, contendra la URL de un repositorio remoto, si puede ser determinada.
Los parametros booleanos son representados como objetos bool de Python.
Un gancho interno es ejecutado sin cambiar el directorio de trabajo del proceso (a diferencia de los ganchos
externos, que son ejecutados desde la raız del repositorio). El gancho no debe cambiar el directorio de trabajo del
proceso, porque esto harıa que falle cualquier llamada que se haga a la API de Mercurial.
Si un gancho retorna el valor booleano “false”5, se considera que este tuvo exito. Si retorna “true”6 o genera una
excepcion, se considera que ha fallado. Una manera util de pensar en esta convencion de llamado es “dıgame si usted
fallo”.
Note que los IDs de conjuntos de cambios son pasados a los ganchos de Python como cadenas hexadecimales, no
como los hashes binarios que la API de Mercurial usa normalmente. Para convertir un hash de hexadecimal a binario,
use la funcion mercurial.node.bin .
10.8.2. Ejecucion de ganchos externos
Un gancho externo es pasado al interprete de comandos del usuario bajo el cual se ejecuta Mercurial. Las car-
acterısticas del interprete, como sustitucion de variables y redireccion de comandos, estan disponibles. El gancho es
ejecutado desde el directorio raız del repositorio (a diferencia de los ganchos internos, que se ejecutan desde el mismo
directorio en que Mercurial fue ejecutado).
Los parametros para el gancho se pasan como variables de entorno. El nombre de cada variable de entorno se pasa
a mayusculas y se le anade el prefijo “HG ”. Por ejemplo, si el nombre de un parametro es “node”, el nombre de la
variable de entorno que almacena el parametro se llamara “HG NODE”.
Un parametro booleano se representa con la cadena “1” para “true”, “0” para “false”. Si una variable se llama
HG NODE, HG PARENT1 o HG PARENT2, contendra un ID de conjunto de cambios representado como una cadena hex-
adecimal. La cadena vacıa es usada para representar un “ID de conjunto de cambios nulo” en vez de una cadena de
ceros. Si una variable de entorno se llama HG URL, contendra la URL de un repositorio remoto, si puede ser determi-
nada.
Si un gancho termina con un codigo de salida de cero, se considera que tuvo exito. Si termina con un codigo de
salida diferente de cero, se considera que fallo.
5N. del T. Falso.6N. del T. Verdadero.
124
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 135/204
10.8.3. Averiguar de donde vienen los conjuntos de cambios
Un gancho que involucra la transferencia de conjuntos de cambios entre un repositorio local y otro puede ser capaz
de averiguar informacion acerca de “el otro lado”. Mercurial sabe c´ omo son transferidos los conjuntos de cambios, y
en muchos casos tambien desde o hacia donde estan siendo transferidos.
Fuentes de conjuntos de cambios
Mercurial le indicara a un gancho cuales son, o fueron, los medios usados para transferir los conjuntos de cambios
entre repositorios. Esta informacion es provista por Mercurial en un parametro Python llamado source7, o una variable
de entorno llamada HG SOURCE.
serve Los conjuntos de cambios son transferidos desde o hacia un repositorio remoto a trav es de http o ssh.
pull Los conjuntos de cambios son transferidos vıa una operacion de jalado de un repositorio a otro.
push Los conjuntos de cambios son transferidos vıa un empuje de un repositorio a otro.
bundle Los conjuntos de cambios son transferidos desde o hacia un paquete.
A donde van los cambios—URLs de repositorios remotos
Cuando es posible, Mercurial le indicara a los ganchos la ubicacion de “el otro lado” de una actividad que transfieradatos de conjuntos de cambios entre repositorios. Esto es provisto por Mercurial en un parametro Python llamado url,
o en una variable de entorno llamada HG URL.
No siempre esta informacion esta disponible. Si un gancho es invocado un repositorio que es servido a trav es de
http o ssh, Mercurial no puede averiguar donde esta el repositorio remoto, pero puede saber desde donde se conecta el
cliente. En esos casos, la URL tendra una de las siguientes formas:
remote:ssh:ip-address—cliente ssh remoto, en la direccion IP dada.
remote:http:ip-address—cliente remoto http, en la direccion IP dada. Si el cliente esta usando SSL,
tendra la forma remote:https:ip-address.
Vacıo—no se pudo descubrir informacion acerca del cliente remoto.
10.9. Referencia de ganchos
10.9.1. changegroup—luego de a ˜ nadir conjuntos de cambios remotos
Este gancho es ejecutado luego de que un grupo de conjuntos de cambios preexistentes ha sido anadido al repos-
itorio, por ejemplo vıa un “hg pull” o “hg unbundle”. Este gancho es ejecutado una vez por cada operacion que
anade uno o mas conjuntos de cambios. Este gancho se diferencia del gancho incoming, que es ejecutado una vez por
cada conjunto de cambios, sin importar si los cambios llegan en grupo.
Algunos usos posibles para este gancho includen el probar o ensamblar los conjuntos de cambios a nadidos, actu-
alizar una base de datos de fallos, o notificar a subscriptores de que el repositorio contiene nuevos cambios.
Parametros para este gancho:
node Un ID de conjunto de cambios. El ID del primer conjunto de cambios que fue anadido en el grupo. Todos los
conjuntos de cambios entre este y la punta (tip), inclusive, fueron anadidos por un unico jalado (“hg pull”),empuje (“hg push”) o “hg unbundle”.
source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.
url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.
Veta tambien: incoming (seccion 10.9.3), prechangegroup (seccion 10.9.5), pretxnchangegroup (seccion 10.9.9)
7N. del T. Fuente.
125
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 136/204
10.9.2. commit—luego de la creacion de un nuevo conjunto de cambios
Este gancho es ejecutado luego de la creacion de un nuevo conjunto de cambios.
Parametros para este gancho:
node Un ID de conjunto de cambios. El ID de conjunto de cambios del conjunto de cambios que acab o de ser
consignado.
parent1 Un ID de conjunto de cambios. El ID de conjunto de cambios del primer padre del conjunto de cambios que
acaba de ser consignado.
parent2 Un ID de conjunto de cambios. El ID de conjunto de cambios del segundo padre del conjunto de cambios que
acaba de ser consignado.
Vea tambien: precommit (seccion 10.9.6), pretxncommit (seccion 10.9.10)
10.9.3. incoming—luego de que un conjunto de cambios remoto es a ˜ nadido
Este gancho es ejecutado luego de que un conjunto de cambios preexistente ha sido anadido al repositorio, por
ejemplo, vıa un “hg push”. Si un grupo de conjuntos de cambios fue anadido en una sola operacion, este gancho es
ejecutado una vez por cada conjunto de cambios anadido.
Usted puede usar este gancho para los mismos fines que el gancho changegroup (seccion 10.9.1); simplementealgunas veces es mas conveniente ejecutar un gancho una vez por cada grupo de conjuntos de cambios, mientras que
otras es mas util correrlo por cada conjunto de cambios.
Parametros para este gancho:
node Un ID de conjunto de cambios. El ID del conjunto de cambios reci en anadido.
source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.
url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.
Vea tambien: changegroup (seccion 10.9.1) prechangegroup (seccion 10.9.5), pretxnchangegroup(seccion 10.9.9)
10.9.4. outgoing—luego de la propagacion de los conjuntos de cambios
Este gancho es ejecutado luego de que un grupo de conjuntos de cambios ha sido propagado fuera de este reposi-
torio, por ejemplo por un comando “hg push” o “hg bundle”.
Un uso posible para este gancho es notificar a los administradores que los cambios han sido jalados.
Parametros para este gancho:
node Un ID de conjunto de cambios. El ID del primer conjunto de cambios del grupo que fue enviado.
source Una cadena. La fuente de la operacion (vea la seccion 10.8.3). Si un cliente remoto jalo cambios de este
repositorio, source sera serve. Si el cliente que obtuvo los cambios desde este repositorio era local, source
sera bundle, pull, o push, dependiendo de la operacion que llevo a cabo el cliente.
url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.
Vea tambien: preoutgoing (seccion 10.9.7)
126
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 137/204
10.9.5. prechangegroup—antes de empezar la adicion de conjuntos de cambios remotos
Este gancho de control es ejecutado antes de que Mercurial empiece a a nadir un grupo de conjuntos de cambios de
otro repositorio.
Este gancho no tiene ninguna informacion acerca de los conjuntos de cambios que van a ser anadidos, porque es
ejecutado antes de que se permita que empiece la transmision de dichos conjuntos de cambios. Si este gancho falla,
los conjuntos de cambios no seran transmitidos.
Un uso para este gancho es prevenir que se anadan cambios externos a un repositorio. Por ejemplo, usted podr ıa
usarlo para “congelar” temporal o permanentemente una rama ubicada en un servidor para que los usuarios no puedan
empujar cambios a ella, y permitiendo al mismo tiempo modificaciones al repositorio por parte de un administrador
local.
Parametros para este gancho:
source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.
url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.
Vea tambien: changegroup (seccion 10.9.1), incoming (seccion 10.9.3), , pretxnchangegroup (seccion 10.9.9)
10.9.6. precommit—antes de iniciar la consignacion de un conjunto de cambios
Este gancho es ejecutado antes de que Mercurial inicie la consignacion de un nuevo conjunto de cambios. Es
ejecutado antes de que Mercurial tenga cualquier de los metadatos para la consignacion, como los ficheros a ser
consignados, el mensaje de consignacion, o la fecha de consignacion.
Un uso para este gancho es deshabilitar la capacidad de consignar nuevos conjuntos de cambios, pero permi-
tiendo conjuntos de cambios entrantes. Otro es ejecutar un proceso de ensamble/compilacion o prueba, y permitir la
consignacion solo si el ensamble/compilacion o prueba tiene exito.
Parametros para este gancho:
parent1 Un ID de conjunto de cambios. El ID de conjunto de cambios del primer padre del directorio de trabajo.
parent2 Un ID de conjunto de cambios. El ID de conjunto de cambios del segundo padre del directorio de trabajo.
Si la consignacion continua, los padres del directorio de trabajo se convertiran en los padres del nuevo conjunto de
cambios.Vea tambien: commit (seccion 10.9.2), pretxncommit (seccion 10.9.10)
10.9.7. preoutgoing—antes de empezar la propagacion de conjuntos de cambios
Este gancho es ejecutado antes de que Mercurial conozca las identidades de los conjuntos de cambios que deben
ser transmitidos.
Un uso para este gancho es evitar que los cambios sean transmitidos a otro repositorio.
Parametros para este gancho:
source Una cadena. La fuente la operacion que esta tratando de obtener cambios de este repositorio (vea la sec-
cion 10.8.3). Revise la documentacion para el parametro source del gancho outgoing, en la seccion 10.9.4,
para ver los posibles valores de este parametro.
url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.
Vea tambien: outgoing (seccion 10.9.4)
127
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 138/204
10.9.8. pretag—antes de etiquetar un conjunto de cambios
Este gancho de control es ejecutado antes de la creacion de una etiqueta. Si el gancho termina exitosamente, la
creacion de la etiqueta continua. Si el gancho falla, no se crea la etiqueta.
Parametros para este gancho:
local Un booleano. Indica si la etiqueta es local a esta instancia del repositorio (p.e. almacenado en .hg/localtags)
o administrado por Mercurial (almacenado en .hgtags).
node Un ID de conjunto de cambios. El ID del conjunto de cambios a etiquetar.
tag Una cadena. El nombre de la etiqueta por crear.
Si la etiqueta que se va a crear se encuentra bajo control de revisiones, los ganchos precommit y pretxncommit
(secciones 10.9.2 y 10.9.10) tambien seran ejecutados.
Vea tambien: tag (seccion 10.9.12)
10.9.9. pretxnchangegroup—antes de completar la adicion de conjuntos de cambios
remotos
Este gancho de control es ejecutado antes de una transaccion—la que maneja la adicion de un grupo de conjuntos
de cambios nuevos desde fuera del repositorio—se complete. Si el gancho tiene exito, la transaccion se completa, y
todos los conjuntos de cambios se vuelven permanentes dentro de este repositorio. Si el gancho falla, la transacci on es
deshecha, y los datos para los conjuntos de cambios son eliminados.
Este gancho puede acceder a los metadatos asociados con los conjuntos de cambios casi a nadidos, pero no debe
hacer nada permanente con estos datos. Tampoco debe modificar el directorio de trabajo.
Mientras este gancho esta corriendo, si otro proceso Mercurial accesa el repositorio, podra ver los conjuntos de
cambios casi anadidos como si fueran permanentes. Esto puede llevar a condiciones de carrera si usted no toma
precauciones para evitarlas.
Este gancho puede ser usado para examinar automaticamente un grupo de conjuntos de cambios. Si el gancho falla,
todos los conjuntos de cambios son “rechazados” cuando la transacci on se deshace.
Parametros para este gancho:
node Un ID de conjunto de cambios. El ID del primer conjunto de cambios que fue anadido en el grupo. Todos los
conjuntos de cambios entre este y el tip, inclusive, fueron anadidos por un unico “hg pull”, “hg push” o “hg
unbundle”.
source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.
url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.
Vea tambien: changegroup (seccion 10.9.1), incoming (seccion 10.9.3), prechangegroup (seccion 10.9.5)
10.9.10. pretxncommit—antes de completar la consignacion de un nuevo conjunto de
cambios
Este gancho de control es ejecutado antes de que una transaccion—que maneja una nueva consignacion—se com-
plete. Si el gancho tiene exito, la transaccion se completa y el conjunto de cambios se hace permanente dentro de esterepositorio. Si el gancho falla, la transaccion es deshecha, y los datos de consignacion son borrados.
Este gancho tiene acceso a los metadatos asociados con el practicamente nuevo conjunto de cambios, pero no
deberıa hacer nada permanente con estos datos. Tampoco debe modificar el directorio de trabajo.
Mientras este gancho esta corriendo, si otro proceso Mercurial accesa este repositorio, podra ver el practicamente
nuevo conjunto de cambios como si fuera permanente. Esto puede llevar a condiciones de carrera si usted no toma
precauciones para evitarlas.
Parametros para este gancho:
128
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 139/204
node Un ID de conjunto de cambios. El ID del conjunto de cambios reci en consignado.
parent1 Un ID de conjunto de cambios. El ID de conjunto de cambios del primer padre del conjunto de cambios que
acaba de ser consignado.
parent2 Un ID de conjunto de cambios. El ID de conjunto de cambios del segundo padre del conjunto de cambios que
acaba de ser consignado.
Vea tambien: precommit (seccion 10.9.6)
10.9.11. preupdate—antes de actualizar o fusionar el directorio de trabajo
Este gancho de control es ejecutado antes de actualizar o fusionar el directorio de trabajo. Es ejecutado s olo si las
revisiones usuales de Mercurial antes de las actualizaciones determinan que la actualizacion o fusion pueden proceder.
Si el gancho termina exitosamente, la actualizacion o fusion pueden proceder.; si falla, la actualizacion o fusion no
empiezan.
Parametros para este gancho:
parent1 Un ID de conjunto de cambios. El ID del padre al que el directorio de trabajo sera actualizado. Si se esta fusio-
nando el directorio de trabajo, no cambiara este padre.
parent2 Un ID de conjunto de cambios. Solo esta definido si se esta fusionando el directorio de trabajo. El ID de larevision con la cual esta siendo fusionado el directorio de trabajo.
Vea tambien: update (seccion 10.9.13)
10.9.12. tag—luego de etiquetar un conjunto de cambios
Este gancho es ejecutado luego de la creacion de una etiqueta.
Parametros para este gancho:
local Un booleano. Indica si la etiqueta es local a esta instancia del repositorio (p.e. almacenado en .hg/localtags)
o administrado por Mercurial (almacenado en .hgtags).
node Un ID de conjunto de cambios. El ID del conjunto de cambios que fue etiquetado.
tag Una cadena. El nombre de la etiqueta que fue creada.
Si la etiqueta creada esta bajo control de revisiones, el gancho commit (seccion 10.9.2) es ejecutado antes de este
gancho.
Vea tambien: pretag (seccion 10.9.8)
10.9.13. update—luego de actualizar o fusionar el directorio de trabajo
Este gancho es ejecutado despues de una actualizacion o fusion en el directorio de trabajo. Ya que una fusion
puede fallar (si el comando externo hgmerge no puede resolver los conflictos en un fichero), este gancho indica si la
actualizacion o fusion fueron completados adecuadamente.
error Un booleano. Indica si la actualizacion o fusion fue completada exitosamente.
parent1 Un ID de conjunto de cambios. El ID del padre al cual fue actualizado el directorio de trabajo. Si se fusiono el
directorio de trabajo, no se habra cambiado este padre.
parent2 Un ID de conjunto de cambios. Solo esta definido si se fusiono el directorio de trabajo. El ID de la revision con
la que fue fusionado el directorio de trabajo.
Vea tambien: preupdate (seccion 10.9.11)
129
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 140/204
Capıtulo 11
Personalizar los mensajes de Mercurial
Mercurial provee un poderoso mecanismo que permite controlar como despliega la informacion. El mecanismo se
basa en plantillas. Puede usar plantillas para generar salida especıfica para una orden particular o para especificar la
visualizacion completa de la interfaz web embebida.
11.1. Usar estilos que vienen con Mercurial
Hay ciertos estilos listos que vienen con Mercurial. Un estilo es simplemente una plantilla predeterminada que
alguien escribio e instalo en un sitio en el cual Mercurial puede encontrarla.
Antes de dar un vistazo a los estilos que trae Mercurial, revisemos su salida usual.
1 $ hg log -r1
2 changeset: 1:522d8d7a8fda
3 tag: mytag
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:30 2009 +0000
6 summary: added line to end of <<hello>> file.
7
Es en cierta medida informativa, pero ocupa mucho espacio—cinco l ıneas de salida por cada conjunto de cambios.
El estilo compact lo reduce a tres lıneas, presentadas de forma suscinta.
1 $ hg log --style compact
2 3[tip] b638ce454bd0 2009-02-10 18:23 +0000 bos
3 Added tag v0.1 for changeset 4b75acdd4698
4
5 2[v0.1] 4b75acdd4698 2009-02-10 18:23 +0000 bos
6 Added tag mytag for changeset 522d8d7a8fda
7
8 1[mytag] 522d8d7a8fda 2009-02-10 18:23 +0000 bos
9 added line to end of <<hello>> file.
10
11 0 d0c3b909ac1b 2009-02-10 18:23 +0000 bos
12 added hello
13
El estilo de la bitacora de cambios vislumbra el poder expresivo del sistema de plantillas de Mercurial. Este
estilo busca seguir los estandares de bitacora de cambios del proyecto GNU[RS].
130
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 141/204
1 $ hg log --style changelog
2 2009-02-10 Bryan O’Sullivan <[email protected]>
3
4 * .hgtags:
5 Added tag v0.1 for changeset 4b75acdd4698
6 [b638ce454bd0] [tip]7
8 * .hgtags:
9 Added tag mytag for changeset 522d8d7a8fda
10 [4b75acdd4698] [v0.1]
11
12 * goodbye, hello:
13 added line to end of <<hello>> file.
14
15 in addition, added a file with the helpful name (at least i hope
16 that some might consider it so) of goodbye.
17 [522d8d7a8fda] [mytag]
18
19 * hello:20 added hello
21 [d0c3b909ac1b]
22
No es una sorpresa que el estilo predeterminado de Mercurial se llame default1.
11.1.1. Especificar un estilo predeterminado
Puede modificar el estilo de presentacion que Mercurial usara para toda orden vıa el fichero hgrc indicando el
estilo que prefiere usar.
1 [ui]
2 style = compact
Si escribe un estilo, puede usarlo bien sea proveyendo la ruta a su fichero de estilo o copiando su fichero de
estilo a un lugar en el cual Mercurial pueda encontrarlo (t ıpicamente el subdirectorio templates de su directorio de
instalacion de Mercurial).
11.2. Ordenes que soportan estilos y plantillas
Todas las ordenes de Mercurial“relacionadas con log” le permiten usar estilos y plantillas: “hg incoming”, “hg
log”, “hg outgoing” y “hg tip”.
Al momento de la escritura del manual estas son las unicas ordenes que soportan estilos y plantillas. Dado que son
las ordenes mas importantes que necesitan personalizacion, no ha habido muchas solicitudes desde la comunidad de
usuarios de Mercurial para anadir soporte de plantillas y estilos a otras ordenes.
11.3. Cuestiones basicas de plantillas
Una plantilla de Mercurial es sencillamente una pieza de texto. Cierta porcion nunca cambia, otras partes se
expanden, o reemplazan con texto nuevo cuando es necesario.
1N. del T. predeterminado
131
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 142/204
Antes de continuar, veamos de nuevo un ejemplo sencillo de la salida usual de Mercurial:
1 $ hg log -r1
2 changeset: 1:522d8d7a8fda
3 tag: mytag
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:30 2009 +00006 summary: added line to end of <<hello>> file.
7
Ahora, ejecutemos la misma orden, pero usemos una plantilla para modificar su salida:
1 $ hg log -r1 --template ’i saw a changeset\n’
2 i saw a changeset
El ejemplo anterior ilustra la plantilla mas sencilla posible; es solamente una porcion estatica de codigo que se
imprime una vez por cada conjunto de cambios. La opcion --template de la orden “hg log” indica a Mercurial usar
el texto dado como la plantilla cuando se imprime cada conjunto de cambios.
Observe que la cadena de plantilla anterior termina con el texto “ \n”. Es una secuencia de control, que le indicaa Mercurial imprimira una nueva lınea al final de cada objeto de la plantilla. Si omite esta nueva lınea, Mercurial
colocara cada pieza de salida seguida. Si desea mas detalles acerca de secuencias de control, vea la seccion 11.5.
Una plantilla que imprime una cadena fija de texto siempre no es muy util; intentemos algo un poco mas complejo.
1 $ hg log --template ’i saw a changeset: {desc}\n’
2 i saw a changeset: Added tag v0.1 for changeset 4b75acdd4698
3 i saw a changeset: Added tag mytag for changeset 522d8d7a8fda
4 i saw a changeset: added line to end of <<hello>> file.
5
6 in addition, added a file with the helpful name (at least i hope that some might consider it so) o
7 i saw a changeset: added hello
Como puede ver, la cadena “{desc}” en la plantilla ha sido reemplazada en la salida con la descricipci on de cadaconjunto de cambios. Cada vez que Mercurial encuentra texto encerrado entre corchetes (“{” y “}”), intentara reem-
plazar los corchetes y el texto con la expansion de lo que sea esta adentro. Para imprimir un corchete de forma literal,
debe escaparlo, como se describe en la seccion 11.5.
11.4. Palabras claves mas comunes en las plantillas
Puede empezar a escribir plantillas sencillas rapidamente con las palabras claves descritas a continuacion:
author Cadena. El autor NO modificado del conjunto de cambios.
branches Cadena. El nombre de la rama en la cual se consigno el conjunto de cambios. Sera vacıa si el nombre de la rama
es default.
date Informacion de fecha. La fecha en la cual se consigno el conjunto de cambios. No es legible por un humano, debe
pasarla por un firltro que la desplegara apropiadamente. En la seccion 11.6 hay mas detalles acerca de filtros. La
fecha se expresa como un par de numeros. El primer numero corresponde a una marca de tiempo UNIX UTC
(segundos desde el primero de enero de 1970); la segunda es el corrimiento horario de la zona horaria del UTC
en la cual se encontraba quien hizo la consignacion, en segundos.
desc Cadena. La descripcion en texto del conjunto de cambios.
132
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 143/204
1 $ hg log -r1 --template ’author: {author}\n’
2 author: Bryan O’Sullivan <[email protected]>
3 $ hg log -r1 --template ’desc:\n{desc}\n’
4 desc:
5 added line to end of <<hello>> file.
6
7 in addition, added a file with the helpful name (at least i hope that some might consider it so) o8 $ hg log -r1 --template ’files: {files}\n’
9 files: goodbye hello
10 $ hg log -r1 --template ’file_adds: {file_adds}\n’
11 file_adds: goodbye
12 $ hg log -r1 --template ’file_dels: {file_dels}\n’
13 file_dels:
14 $ hg log -r1 --template ’node: {node}\n’
15 node: 522d8d7a8fda9a24dcac9c5ccfcca067b933220b
16 $ hg log -r1 --template ’parents: { parents}\n’
17 parents:
18 $ hg log -r1 --template ’rev: {rev}\n’
19 rev: 1
20 $ hg log -r1 --template ’tags: {tags}\n’21 tags: mytag
Figura 11.1: Template keywords in use
files Lista de cadenas. Todos los ficheros modificados, adicionados o eliminados por este conjunto de cambios.
file adds Lista de cadenas. Ficheros adicionados por este conjunto de cambios.
file dels Lista de cadenas. Ficheros eliminados por este conjunto de cambios.
node Cadena. El hash de identificacion de este conjunto de cambios como una cadena hexadecimal de 40 caracteres.
parents Lista de cadenas. Los ancestros del conjunto de cambios.
rev Entero. El numero de revision del repositorio local.
tags Lista de cadenas. Todas las etiquetas asociadas al conjunto de cambios.
Unos experimentos sencillos nos mostraran que esperar cuando usamos estas palabras claves; puede ver los resul-
tados en la figura 11.1.
Como mencionamos anteriormente, la palabra clave de fecha no produce salida legible por un humano, debemos
tratarla de forma especial. Esto involucra usar un filtro, acerca de lo cual hay mas en la seccion 11.6.
1 $ hg log -r1 --template ’date: {date}\n’
2 date: 1234290210.00
3 $ hg log -r1 --template ’date: {date|isodate}\n’
4 date: 2009-02-10 18:23 +0000
11.5. Secuencias de Control
El motor de plantillas de Mercurial reconoce las secuencias de control mas comunmente usadas dentro de las
cadenas. Cuando ve un backslash (“\”), ve el caracter siguiente y sustituye los dos caracteres con un reemplazo
sencillo, como se describe a continuacion:
133
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 144/204
\\ Backslash, “\”, ASCII 134.
\n Nueva lınea, ASCII 12.
\r Cambio de lınea, ASCII 15.
\t Tab, ASCII 11.
\v Tab Vertical, ASCII 13.
\{ Corchete abierto, “{”, ASCII 173.
\} Corchete cerrado, “}”, ASCII 175.
Como se indico arriba, si desea que la expansion en una plantilla contenga un caracter literal “\”, “{”, o “{”, debe
escaparlo.
11.6. Uso de filtros con palabras claves
Algunos de los resultados de la expansion de la plantilla no son faciles de usar de inmediato. Mercurial le permite
especificar una cadena de filtros opcionales para modificar el resultado de expandir una palabra clave. Ya ha visto el
filtro usual isodate en accion con anterioridad para hacer legible la fecha.
A continuacion hay una lista de los filtros de Mercurial mas comunmente usados. Ciertos filtros pueden aplicarse
a cualquier texto, otros pueden usarse unicamente en circunstancias especıficas. El nombre de cada filtro esta seguido
de la indicacion de donde puede ser usado y una descripcion de su efecto.
addbreaks Cualquier texto. Anade una etiqueta XHTML “<br/>” antes del final de cada l ınea excepto en la final. Por
ejemplo, “foo\nbar” se convierte en “foo<br/>\nbar”.
age palabra clave date. Muestra la edad de la fecha, relativa al tiempo actual. Ofrece una cadena como “10 minutes”.
basename Cualquier texto, pero de utilidad sobre todo en palabras claves relativas a ficheros. Trata el texto como una
ruta, retornando el nombre base. Por ejemplo, “foo/bar/baz”, se convierte en “baz”.
date datepalabra clave. Mostrar la fecha en un formato similar a la orden
datede in a similar format to the Unix,pero con la zona horaria incluıda. Una cadena como “Mon Sep 04 15:13:13 2006 -0700”.
domain Cualquier texto, pero de mayor utilidad para la palabra clave author. Encuentra la primera cadena que luce
como una direccion de correo electronico, y extrae solamente el componente del dominio. Por ejemplo, de
“Bryan O’Sullivan <[email protected]>” se extrae “serpentine.com”.
email Cualquier texto, pero de mayor utilidad para la palabra clave author. Extrae la primera cadena que luce como
una direccion de correo. Por ejemplo, de “Bryan O’Sullivan <[email protected]>” extrae “[email protected]
escape Cualquier texto. Reemplaza los caracteres especiales de XML/XHTML: “&”, “<” y “>” con las entidades XML.
fill68 Cualquier texto. Lograr que el texto ocupe las primeras 68 columnas. Es util emplearlo antes de pasar el texto
por el filtro tabindent, y queremos que aun quepa en una ventana de fuente fija y 80 columnas.
fill76 Cualquier texto. Lograr que el texto quepa en 76 columnas.
firstline Cualquier texto. Mostrar la primera lınea de texto sin saltos de lınea.
hgdate date palabra clave. Mostrar la fecha como un par de numeros legibles. Muestra una cadena como “1157407993 25200”.
isodate date palabra clave. Mostrar la fecha como una cadena de texto en el formato. Muestra una cadena como
“2006-09-04 15:13:13 -0700”.
134
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 145/204
obfuscate Cualquier texto, pero de mayor utilidad para la palabra clave author. Muestra el campo de texto como una
secuencia de entidades XML. Esto ayuda a eliminar ciertos robots estupidos de adquisicion de correo.
person Cualquier texto, util sobre todo para la palabra clave author. Muestra el texto que hay antes de la direccion de
correo electronico. Por ejemplo, “Bryan O’Sullivan <[email protected]>” mostrarıa “Bryan O’Sullivan”.
rfc822date date palabra clave. Muestra una fecha con el mismo formato que se usa en los encabezados de correo. Mostrar ıa
una cadena como “Mon, 04 Sep 2006 15:13:13 -0700”.
short Hash del conjunto de cambios. Muestra la forma corta de un hash de conjunto de cambios, of a changeset hash,
p.e. una cadena hexadecimal de 12 bytes.
shortdate date palabra clave. Mostrar ano, mes y dıa de una fecha. Muestrauna cadena como “2006-09-04”.
strip Cualquier texto. Elimina todos los espacios en blanco al principio y al final de la cadena.
tabindent Cualquier texto. Muestra el texto con todas las lıneas excepto la primera que comience con el caracter tab.
urlescape Cualquier texto. Escapa todos los caracteres que se consideren como “especiales” por los parsers de URL. Por
ejemplo, foo bar se convierte en foo%20bar.
user Cualquier texto, util sobre todo para la palabra clave author. Retorna el “usuario” de una direccion de correo.
Por ejemplo, “Bryan O’Sullivan <[email protected]>” se convierte en “bos”.
Nota: Si trata de aplicar un filtro a una porcion de datos que no puede procesarse,
Mercurial fallara e imprimira una excepcion de Python. Por ejemplo, el tratar de
usar la salida de la palabra clave desc con el filtro isodate no resultara algo util.
11.6.1. Combinar filtros
Combinar filtros es para generar una salida en la forma como usted lo desea es muy sencillo. La cadena de fil-
tros siguientes arman una descripcion, despues aseguran que cabe limpiamente en 68 columnas, y las indenta con
8 caracteres (por lo menos en sistemas tipo Unix, en los que el tab por convencion se extiende en 8 caracteres).
1 $ hg log -r1 --template ’description:\n\t{desc|strip|fill68|tabindent}\n’
2
description:3 added line to end of <<hello>> file.
4
5 in addition, added a file with the helpful name (at least i hope
6 that some might consider it so) of goodbye.
Observe el uso de “\t” (un caracter tab) en la plantilla para forzar que la primera lınea se indente; esto es necesario
para lograr que la primera lınea luzca indentada; es necesario debido a que tabindent indenta todas las lıneas excepto
la primera.
Tenga en cuenta que el orden de los filtros importa. El primer filtro se aplica primero al resultado de la palabra clave;
el segundo al resultado de la aplicacion del primer filtro y ası sucesivamente. Por ejemplo, usar fill68|tabindent
es muy distinto al resultado de usar tabindent|fill68 .
11.7. De plantillas a estilos
Una plantilla provee una forma rapida y sencilla para dar formato a una salida. Las plantillas pueden volvers ver-
bosas, y es util poder darle un nombre a una plantilla. Un fichero de estilo es una plantilla con un nombre, almacenado
en un fichero.
Mas aun, al usar un fichero de estilo se dispara el poder del motor de plantillas en un nivel imposible de alcanzar
usando las opcion --template desde la lınea de ordenes.
135
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 146/204
1 $ hg log -r1 --template ’{author}\n’
2 Bryan O’Sullivan <[email protected]>
3 $ hg log -r1 --template ’{author|domain}\n’
4 serpentine.com
5 $ hg log -r1 --template ’{author|email}\n’
7 $ hg log -r1 --template ’{author|obfuscate}\n’ | cut -c-768 Bryan O'Sulli
9 $ hg log -r1 --template ’{author|person}\n’
10 Bryan O’Sullivan
11 $ hg log -r1 --template ’{author|user}\n’
12 bos
13 $ hg log -r1 --template ’looks almost right, but actually garbage:{date}\n’
14 looks almost right, but actually garbage: 1234290210.00
15 $ hg log -r1 --template ’{date|age}\n’
16 1 second
17 $ hg log -r1 --template ’{date|date}\n’
18 Tue Feb 10 18:23:30 2009 +0000
19 $ hg log -r1 --template ’{date|hgdate}\n’
20 1234290210 021 $ hg log -r1 --template ’{date|isodate}\n’
22 2009-02-10 18:23 +0000
23 $ hg log -r1 --template ’{date|rfc822date}\n’
24 Tue, 10 Feb 2009 18:23:30 +0000
25 $ hg log -r1 --template ’{date|shortdate}\n’
26 2009-02-10
27 $ hg log -r1 --template ’{desc}\n’ | cut -c-76
28 added line to end of <<hello>> file.
29
30 in addition, added a file with the helpful name (at least i hope that some m
31 $ hg log -r1 --template ’{desc|addbreaks}\n’ | cut -c-76
32 added line to end of <<hello>> file.<br/>
33 <br/>
34 in addition, added a file with the helpful name (at least i hope that some m
35 $ hg log -r1 --template ’{desc|escape}\n’ | cut -c-76
36 added line to end of <<hello>> file.
37
38 in addition, added a file with the helpful name (at least i hope that some m
39 $ hg log -r1 --template ’{desc|fill68}\n’
40 added line to end of <<hello>> file.
41
42 in addition, added a file with the helpful name (at least i hope
43 that some might consider it so) of goodbye.
44 $ hg log -r1 --template ’{desc|fill76}\n’
45
added line to end of <<hello>> file.46
47 in addition, added a file with the helpful name (at least i hope that some
48 might consider it so) of goodbye.
49 $ hg log -r1 --template ’{desc|firstline}\n’
50 added line to end of <<hello>> file.
51 $ hg log -r1 --template ’{desc|strip}\n’ | cut -c-76
52 added line to end of <<hello>> file.
53
54 in addition, added a file with the helpful name (at least i hope that some m
55 $ hg log -r1 --template ’{desc|tabindent}\n’ | expand | cut -c-76
56 added line to end of <<hello>> file.
57
58 in addition, added a file with the helpful name (at least i hope tha59 $ hg log -r1 --template ’{node}\n’
60 522d8d7a8fda9a24dcac9c5ccfcca067b933220b
136
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 147/204
11.7.1. Los ficheros de estilo mas sencillos
Nuestro fichero sencillo de estilo contiene una sola lınea:
1 $ echo ’changeset = "rev: {rev}\n"’ > rev
2 $ hg log -l1 --style ./rev
3 rev: 3
Se le indica a Mercurial, “si esta imprimiendo un conjunto de cambios, use el texto de la derecha como la plantilla”.
11.7.2. Sintaxis de ficheros de estilo
Las reglas de sintaxis para un fichero de estilo son sencillas:
El fichero se procesa lınea por lınea.
Se ignoran el espacio en blanco circundante.
Se omiten las lıneas en blanco.
Si una lınea comienza con los caracteres “#” o “;”, la lınea completa se trata como un comentario, y se omitecomo si fuera vacıa.
Una lınea comienza con una palabra clave. Esta debe comenzar con una caracter alfabetico o una raya al piso,
y puede contener subsecuentemente cualquier caracter alfanumerico o una raya al piso. (En notacion de expre-
siones regulares debe coincidir con [A-Za-z_][A-Za-z0-9_]* .)
El proximo elemento debe ser un caracter “=”, que puede estar precedido o seguido por una cantidad arbitraria
de espacio.
Si el resto de la lınea comienza y termina con caracteres encerrados entre caracteres de comillas (bien sea
sencillas o dobles), se trata como cuerpo de la plantilla.
Si el resto de la lınea no comienza con una comilla, se trata como el nombre de un fichero; los contenidos de
este fichero se leeran y se usaran como cuerpo de la plantilla.
11.8. Ejemplos de ficheros de estilos
Para ilustrar la creacion de un fichero de estilo, construiremos algunos ejemplos. En lugar de ofrecer un fichero
completo de estilo y analizarlo, replicaremos el proceso usual de desarrollo de un fichero de estilo comenzando con
algo muy sencillo, y avanzando por una serie de ejemplos sucesivos m as completos.
11.8.1. Identificar equivocaciones en ficheros de estilo
Si Mercurial encuentra un problema en un fichero de estilo en el cual usted est a trabajando, imprime un mensaje
de error suscinto, cuando usted identifique lo que significa, resulta muy util.
1 $ cat broken.style
2 changeset =
Tenga en cuenta que broken.style trata de definir la palabra clave changeset, pero omite dar un contenido para
esta. Cuando se le indica a Mercurial que use este fichero de estilo, se queja inmediatamente.
137
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 148/204
1 $ hg log -r1 --style broken.style
2 abort: broken.style:1: parse error
Este mensaje de error luce intimidante, pero no es muy dif ıcil de seguir:
El primer componente es la forma como Mercurial dice “me rindo”.
1 abort: broken.style:1: parse error
A continuacion viene el nombre del fichero que contiene el error.
1 abort: broken.style:1: parse error
Siguendo el nombre del fichero viene el numero de lınea en la que se encontro el error.
1 abort: broken.style:1: parse error
Finalmente, la descripcion de lo que fallo.
1 abort: broken.style:1: parse error
La descripcion del problema no siempre es clara (como en este caso), pero aunque sea cr ıptica, casi siempre es
trivial la inspeccion visual de la lınea en el fichero de estilo y encontrar lo que est a mal.
11.8.2. Identificar de forma unica un repositorio
Si desea identificar un repositorio de Mercurial “de forma unica” con una cadena corta como identificador, puede
usar la primera revision en el repositorio.
1 $ hg log -r0 --template ’{node}’
2 92cb4692d38c537be0935f906eeff2a47033600c
No es garantıa de unicidad, pero no es utill en ciertos casos: many cases.
No funcionara en un repositorio completamente vacıo, porque un repositorio ası no tiene una revision zero.
Tampoco funcionara en caso (muy raro) cuando el repositorio sea una fusion de dos repositorios independientes
y tiene los dos directorios por ahı.
Hay ciertos casos en los cuales podrıa colocar el identificador:
Como una llave en la tabla de una base de datos que administra repositorios en un servidor.
Como una parte del par { ID repositorio, ID revisi´ on}. Almacene esta informacion de forma independiente cuan-
do ejecute construcciones automatizadas u otras actividades, de forma que pueda “reconstruir” posteriormente
en caso de ser necesario.
138
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 149/204
11.8.3. Mostrando salida parecida a Subversion
Intentemos emular la salida usual que usa otro sistema de control de revisiones, Subversion.
1 $ svn log -r9653
2 ------------------------------------------------------------------------
3 r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
4
5 On reporting a route error, also include the status for the error,
6 rather than indicating a status of 0 when an error has occurred.
7
8 Signed-off-by: Sean Hefty <[email protected]>
9
10 ------------------------------------------------------------------------
Dado que la salida de Subversion es sencilla, es f acil copiar y pegar una porcion de su salida en un fichero, y
reemplazar el texto producido previamente por Subversion con valores base que quisieramos ver expandidos.
1 $ cat svn.template
2 r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
3
4 {desc|strip|fill76}5
6 ------------------------------------------------------------------------
Esta plantilla difiere en algunos detalles de la salida producida por Subversion:
Subversion imprime una fecha “legible” (el “Wed, 27 Sep 2006” en el ejemplo de salida anterior) en parente-
sis. El motor de plantillas de Mercurial no ofrece una forma sencilla de desplegar una fecha en este formato sin
imprimir tambien la hora y la zona horaria.
Emulamos las lıneas de “separacion” de subversion con caracteres “-” en una lınea. Usamos la palabra clave
header del motor de plantillas para imprimir una lınea de separacion como la primera lınea de salida (ver mas
abajo), para lograr una salida similara a la de Subversion.
La salida de subversion incluye un conteo en el encabezado del numero de lıneas en el mensaje de consinacion.
No podemos replicarlo en Mercurial; el motor de plantilla no ofrece en la actualidad un filtro que cuente la
cantidad de objetos que se le pasen.
No me tomo mas de un minuto o dos de trabajo para reemplazar texto literal de un ejemplo de salida de la salida
de Subversion con ciertas palabras claves y filtros para ofrecer la plantilla anterior. El fichero de estilo se refiere
sencillamente a la plantilla.
1 $ cat svn.style
2 header = ’------------------------------------------------------------------------\n\n’
3 changeset = svn.template
Podrıamos haber incluıdo el texto del fichero plantilla directamente en el fichero de estilo encerrando entre comillas
y reemplazando las nuevas lıneas con secuencias “\n”, pero harıa muy dif ıcil de leer el fichero de estilos. La facilidad
para leer es importante cuando esta decidiendo si un texto pertenece a un fichero de estilo o a un fichero de plantilla
incluıdo en el estilo. Si el fichero de estilo luce muy grande o complicado, si inserta una pieza de texto literal, mejor
coloquelo en una plantilla.
139
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 150/204
Capıtulo 12
Administracion de cambios con Colas de
Mercurial
12.1. El problema de la administracion de parches
Un escenario frecuente: usted necesita instalar un paquete de software desde las fuentes, pero encuentra un fallo
que debe arreglar antes de poder comenzar a usarlo. Hace sus cambios, y se olvida del paquete por un tiempo, unos
meses despues necesita actualizar a una nueva version del paquete. Si la nueva version del paquete todavıa tiene el
fallo, debe extraer su arreglo del arbol de fuentes anteriores y aplicarlo a la nueva versi on. Una tarea tediosa en la cual
es f acil equivocarse.
Este es un caso simple del problema del “manejo de parches”. Usted tiene un arbol de fuentes del “mantenedor
principal” que no puede cambiar: necesita hacer algunos cambios locales sobre el arbol principal; y desearıa poder
mantener tales cambios separados, de forma tal que pueda aplicarlos a versiones m as nuevas del arbol principal.
El problema de administracion de parches surge en muchas situaciones. Probablemente la mas visible es cuando un
usuario de un proyecto de software de fuentes abiertas contribuye con un arreglo de un fallo o una nueva caracter ıstica
a los mantenedores del proyecto en la forma de un parche.
Aquellos que distribuyen sistemas operativos que incluyen programas abiertos usualmente requieren hacer cambios
en los paquetes que distribuyen de tal forma que se armen apropiadamente en sus ambientes.Cuando hay pocos cambios por mantener, es muy sencillo administrar un solo parche con los programas est andar
diff y patch (ver la seccion 12.4 para ver como emplear tales herramientas). Cuando la cantidad de cambios comienza
a crecer, tiene sentido mantener parches como “porciones de trabajo” individual, de forma que cada cambio contiene
solamente un arreglo de un fallo (el parche puede modificar varios ficheros, pero est a “haciendo una sola cosa”),
y puede tener cierta cantidad de tales parches para diferentes fallos y cambios locales. En esta situacion, si envıa un
parche que arregla un fallo a los mantenedores principales de un paquete y ellos incluyen su arreglo en una publicaci on
posterior, puede deshacerse de tal parche cuando se actualice a la nueva versi on.
Mantener un solo parche frente a un arbol principal es algo tedioso y es facil equivocarse, pero no es difıcil.
Aunque, la complejidad del problema crece rapidamente a medida que la cantidad de parches que tiene que mantener
crece. Con mas que una pequena cantidad de cambios, entender cuales ha aplicado se convierte de algo desordenado a
algo avasallante.
Afortunadamente Mercurial provee una extension poderos: Colas de Mercurial (o simplemente “MQ”), que sim-
plifica en gran medida el problema de administracion de parches.
12.2. La prehistoria de las Colas de Mercurial
A finales de los 90s, muchos desarrolladores del nucleo de Linux comenzaron a mantener “series de parches”
que modificaron el comportamiento del nucleo de Linux. Algunos se enfocaban en estabilidad, otros en aumentar las
caracterısticas, y otros un poco mas especulativos.
140
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 151/204
Los tamanos de las series de parches crecieron rapidamente. En el 2002, Andrew Morton publico algunos guiones
de lınea de ordenes que estuvo usando para automatizar la tarea de administrar su cola de parches. Andrew us o ex-
itosamente tales guiones para administrar centenas (a veces millares) de parches en el n ucleo de Linux.
12.2.1. Trabajar parches con quilt
A comienzos del 2003, Andreas Gruenbacher y Martin Quinson tomaron la aproximaci on de los guiones de An-drew y publicaron una herramienta llamada “patchwork quilt” [AG], o simplemente “quilt” (ver [Gru05] el paper que
lo describe). Dado que quilt automatizaba sustancialmente la administracion de parches, fue adoptado en gran medida
por desarrolladores de programas abiertos.
Quilt maneja una pila de parches sobre un arbol de directorios. Para comenzar, usted le indica a quilt que administre
un arbol de directorios, le indica que ficheros manejar; Este almacena los nombres y los contenidos de estos ficheros.
Para arreglar un fallo, usted crea un nuevo parche (con una sola orden), edita los ficheros que esta arreglando y
“refresca” el parche.
El paso de refresco hace que quilt revise el arbol de directorios; actualiza el parche con todos los cambios que usted
haya hecho. Puede crear otro parche sobre el primero, que hara seguimiento de los cambios requeridos para modificar
el arbol desde “el arbol con un parch aplicado” a un “arbol con dos parches aplicados”.
Usted puede elegir que cambios desea aplicar al arbol. Si “pop”1 un parche, los cambios hechos por tal parchve
desapareceran del arbol de directorios. Quilt recuerda que parches ha sacado, para que pueda “introducirlos”2 posteri-
ormente, ası el arbol de directorios se restaurara con las modificaciones que vienen del parche. Lo mas importante esque puede ejecutar la orden “refresh” en cualquier momento, y el ultimo parche sera actualizado. Esto significa que
puede, en cualquier momento, cambiar que parches seran aplicados y que modificaciones hacen ellos.
Quilt no tiene nada que ver con herramientas de control de versiones, y puede trabajar bien sobre un conjunto de
fuentes que viene de un fichero comprimido y empaquetado o una copia de trabajo de Subversion.
12.2.2. Pasar de trabajo con parches con Quilt hacia Colas de Mercurial
A mediados de 2005, Chris Mason tomo las caracterısticas de quilt y escribio una extension que llamo Colas de
Mercurial3, que proporciono un comportamiento a Mercurial al estilo quilt.
La diferencia clave entre quilt y MQ es que quilt no sabe nada acerca del sistema de control de revisiones, mientras
que MQ esta integrado con Mercurial. Cada parche que usted introduce se representa como un conjunto de cambios
en Mercurial. Si sustrae un parche, el conjunto de cambios desaparece.4
Dado que quilt no se preocupa por las herramientas de control de revisiones, continua siendo una porcion desoftware tremendamente util para aquellas situaciones en las cuales no puede usar Mercurial y MQ.
12.3. La gran ventaja de MQ
No puedo sobreestimar el valor que MQ ofrece en la unificacion de parches y el control de revisiones.
La principal razon por la cual los parches han persistido en el mundo del software libre y de fuentes abiertas–a
pesar de la creciente disponibilidad de herramientas poderosas de control de revisiones– es la agilidad que ofrecen.
Las herramientas tradicionales de control de revisiones llevan un registro permanente e irreversible de todo lo
que usted hace. A pesar de que esto tiene gran valor, tambien es bastante sutil. Si requiere realizar un experimento
((((wild-eyed)))), debe ser cuidadoso en como lo hace, o puede dejar trazas innecesarias–o peor a un, desconcertantes
o desestabilizantes— de los pasos y errores en el registro de revisiones de forma permanente.
En contraste, con la cohesion de MQ con el control de revisiones distribuidos y los parches, resulta mas sencilloaislar su trabajo. Sus parches viven encima del historial de revisiones normales, y puede hacer que ellos desaparezcan
1N. del T. saca2N. del T. push3N. del T. Mercurial Queues4N. del T. introduce originalmente es push y pop es sustraer en este contexto, usaremos el original en ingl es cuando encontremos que facilita la
comprension
141
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 152/204
o reaparezcan cuando lo desee. Si no le gusta un parche, puede desecharlo. Si un parche no satisface todo lo que usted
desea, puede arreglarlo—tantas veces como lo requiera, hasta que lo haya refinado lo suficiente hacia sus expectativas.
Por ejemplo, la integracion de parches con el control de revisiones hace que el entender los parches y revisar sus
efectos—y sus interacciones con el codigo en el cual estan enlazados— sea mucho mas sencillo. Dado que todo parche
que se aplique tiene un conjunto de cambios asociado, puede usar “ hg log filename” para ver que conjuntos de
cambios y parches afectaron un fichero. Puede usar la orden bisect para hacer una busqueda binaria sobre todos los
conjuntos de cambios y parches aplicados para ver donde se introdujo un fallo o donde fue arreglado. Puede usar laorden “hg annotate” para ver que conjuntos de cambios o parches modificaron una lınea particular de un fichero
fuente. Y mucho mas.
12.4. Entender los parches
Dado que MQ no esconde su naturaleza parche-centrica, es muy util para entender de que se tratan los parches, y
un poco acerca de las herramientas que trabajan con ellos.
La orden de Unix tradicional diff compara dos ficheros, e imprime una lista de diferencias de sus lıneas. La orden
patch entiende esas diferencias como modificaciones para construir un fichero. Vea en la figura 12.1 un ejemplo
sencillo de tales ordenes en accion.
1 $ echo ’this is my original thought’ > oldfile2 $ echo ’i have changed my mind’ > newfile
3 $ diff -u oldfile newfile > tiny.patch
4 $ cat tiny.patch
5 --- oldfile 2009-02-10 18:23:25.000000000 +0000
6 +++ newfile 2009-02-10 18:23:25.000000000 +0000
7 @@ -1 +1 @@
8 -this is my original thought
9 +i have changed my mind
10 $ patch < tiny.patch
11 patching file oldfile
12 $ cat oldfile
13 i have changed my mind
Figura 12.1: Uso sencillo de las ordenes diff y patch
El tipo de fichero que diff genera (y que patch toma como entrada) se llama un “parche” o un “diff”; no hay
diferencia entre un parche y un diff. (Usaremos el termino “parche”, dado que es el que mas comunmente se usa.)
Un parche puede comenzar con un texto arbitrario; la orden patch ignora este texto, pero MQ lo usa como el
mensaje de consignacion cuando se crean conjuntos de cambios. Para encontrar el inicio del contenido de un parche,
la orden patch busca la primera lınea que comience con la cadena “diff -”.
MQ trabaja con diffs unificados (patch acepta varios formatos de diff adicionales, pero MQ no). Un diff unificado
contiene dos clases de encabezados. El encabezado de fichero describe el fichero que se esta modificando; contiene el
nombre del fichero a modificar. Cuando patch ve un nuevo encabezado de fichero, busca un fichero con ese nombre
para modificarlo.
Despues del encabezaado vienen varios trozos. Cada trozo comienza con un encabezado; que identifica el rango de
lıneas del fichero que el trozo debe modificar. Despues del encabezado, un trozo comienza y termina con unas pocas
lıneas (usualmente tres) de texto del fichero que no han sido modificadas; las cuales llamamos el contexto del trozo. Si
solamente hay una pequena cantidad de contexto entre trozos sucesivos, diff no imprime un nuevo encabezado para
el trozo, continua integrando los trozos, con unas lıneas de contexto entre las modificaciones.
Cada lınea de contexto comienza con un caracter de espacio. En el trozo, si una l ınea comienza con “-” significa
“elimine esta lınea”, si la lınea comienza con un “+” significa “inserte esta lınea”. Por ejemplo, una lınea que se
142
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 153/204
modifica se representa con una lınea eliminada y una lınea insertada.
Retomaremos aspectos mas sutiles acerca de parches posteriormente (en la seccion 12.6), pero en el momento
usted ya deberıa tener suficiente informacion para usar MQ.
12.5. Comenzar a usar Colas de Mercurial
Dado que MQ esta implementado como una extension, debe habilitarla explıcitamente antes de comenzar a usarla.
(No necesita descargar nada; MQ viene con la distribucion estandar de Mercurial.) Para habilitar MQ, edite su fichero
˜/.hgrc, y anada las lıneas de la figura 12.5.
1 [extensions]
2 hgext.mq =
Figura 12.2: Lıneas a anadir en ˜/.hgrc para habilitar la extension MQ
Cuando la extension este habilitada, apareceran varios comandos. Para verificar que la extension esta trabajando,
puede usar “hg help” para ver si la orden “hg qinit” esta disponible; vea un ejemplo en la figura 12.3.
1 $ hg help qinit
2 hg qinit [-c]
3
4 init a new queue repository
5
6 The queue repository is unversioned by default. If -c is
7 specified, qinit will create a separate nested repository
8 for patches (qinit -c may also be run later to convert
9 an unversioned patch repository into a versioned one).
10 You can use qcommit to commit changes to this queue repository.
11
12 options:
13
14 -c --create-repo create queue repository
15
16 use "hg -v help qinit" to show global options
Figura 12.3: Como verificar que MQ esta habilitado
Puede usar MQ en cualquier repositorio de Mercurial, y sus comandos solamente operaran con tal repositorio.
Para comenzar, basta con preparar el repositorio con la orden “hg qinit” (ver la figura 12.4). Esta orden crea un
directorio vacıo llamado .hg/patches, donde MQ mantendra sus metadatos. Como otras ordenes de Mercurial, la
orden “hg qinit” no imprime nada cuando es exitosa.
12.5.1. Crear un nuevo parche
Para comenzar a trabajar en un nuevo parche use la orden “hg qnew”. Esta orden recibe un argumento, el nombre
del parche a crear. MQ lo usara como el nombre del fichero en el directorio .hg/patches, como puede apreciarlo en
la figura 12.5.
143
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 154/204
1 $ hg init mq-sandbox
2 $ cd mq-sandbox
3 $ echo ’line 1’ > file1
4 $ echo ’another line 1’ > file2
5 $ hg add file1 file2
6 $ hg commit -m’first change’
7 $ hg qinit
Figura 12.4: Preparar un repositorio para usar MQ
1 $ hg tip
2 changeset: 0:90039acadb36
3 tag: tip
4 user: Bryan O’Sullivan <[email protected]>
5 date: Tue Feb 10 18:23:27 2009 +0000
6 summary: first change
7
8
$ hg qnew first.patch9 $ hg tip
10 changeset: 1:495236f727e1
11 tag: qtip
12 tag: first.patch
13 tag: tip
14 tag: qbase
15 user: Bryan O’Sullivan <[email protected]>
16 date: Tue Feb 10 18:23:27 2009 +0000
17 summary: [mq]: first.patch
18
19 $ ls .hg/patches
20 first.patch series status
Figura 12.5: Crear un nuevo parche
Tambien hay otros dos nuevos ficheros en el directorio .hg/patches: series y status. El fichero series lista
todos los parches de los cuales MQ tiene noticia para este repositorio, con un parche por l ınea. Mercurial usa el fichero
status para mantener registros interns; da seguimiento a todos los parches que MQ ha aplicado en el repositorio.
Nota: En ciertas ocasiones usted querra editar el fichero series a mano; por
ejemplo, cambiar el orden en que se aplican ciertos parches. A pesar de esto, es
una mala idea editar manualmente el fichero status, dado que es f acil desorientar
a MQ acerca de lo que esta pasando.
Una vez que haya creado un nuevo parche, puede editar los ficheros en el directorio de trabajo, como lo harıa
usualmente. Toda las ordenes que de a Mercurial, tales como “hg diff” y “hg annotate”, trabajaran de la mismaforma como lo han hecho antes.
12.5.2. Refrescar un parche
Cuando usted llega a un punto en el cual desea guardar su trabajo, use la orden “ hg qrefresh” (figura 12.5) para
actualizar el parche en el cual esta trabajando. Esta orden almacena los cambios que haya hecho al directorio actual de
144
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 155/204
trabajo en su parche, y almacena el conjunto de cambios correspondiente que contiene los cambios.
1 $ echo ’line 2’ >> file1
2 $ hg diff
3 diff -r 495236f727e1 file1
4 --- a/file1 Tue Feb 10 18:23:27 2009 +0000
5 +++ b/file1 Tue Feb 10 18:23:27 2009 +00006 @@ -1,1 +1,2 @@
7 line 1
8 +line 2
9 $ hg qrefresh
10 $ hg diff
11 $ hg tip --style=compact --patch
12 1[qtip,first.patch,tip,qbase] 131b8ed49ec4 2009-02-10 18:23 +0000 bos
13 [mq]: first.patch
14
15 diff -r 90039acadb36 -r 131b8ed49ec4 file1
16 --- a/file1 Tue Feb 10 18:23:27 2009 +0000
17 +++ b/file1 Tue Feb 10 18:23:27 2009 +0000
18 @@ -1,1 +1,2 @@
19 line 1
20 +line 2
21
Figura 12.6: Refrescar un parche
Puede ejecutar la orden “hg qrefresh” tan seguido como quiera, y es una buena forma de “colocar marcas” a su
trabajo. Refresque su parche en momentos oportunos; intente un experimento; si el experimento no funciona, Use “hg
revert” sobre sus modificaciones para volver al refresco anterior.
12.5.3. Aplicar un parche tras otro y dar seguimiento
Cuando haya terminado de trabajar en un parche, o necesite trabajar en otro, puede usar la orden “ hg qnew” para
crear un nuevo parche. Mercurial aplicara este parche sobre su parche anterior. Para un ejemplo, ver la figura 12.8.
Note que el parche contiene los cambios en nuestro parche anterior como parte de su contexto (lo ver a mas claramente
en la salida de “hg annotate”).
Hasta ahora, con excepcion de “hg qnew” y “hg qrefresh”, hemos sido cuidadosos para aplicar unicamente
ordenes usuaales de Mercurial. De todas maneras, MQ ofrece muchos comandos que son mas sencillos de usar cuando
este pensando acerca de parches, como se puede ver en la figura 12.9:
La orden “hg qseries” lista cada parche del cual MQ tiene noticia en este repositorio, desde el m as antiguo
hasta el mas nuevo (El ultimo creado).
La orden “hg qapplied” lista cada parche que MQ haya aplicado en este repositorio, de nuevo, desde el mas
antiguo hasta el mas nuevo (El aplicado mas recientemente).
12.5.4. Manipular la pila de parches
La discusion previa indico que debe haber una diferencia entre los parches “conocidos” y “aplicados”, y efectiva-
mente la hay. MQ puede manejar un parche sin que este haya sido aplicado al repositorio.
145
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 156/204
1 $ echo ’line 3’ >> file1
2 $ hg status
3 M file1
4 $ hg qrefresh
5 $ hg tip --style=compact --patch
6 1[qtip,first.patch,tip,qbase] 4fef714d728c 2009-02-10 18:23 +0000 bos
7 [mq]: first.patch8
9 diff -r 90039acadb36 -r 4fef714d728c file1
10 --- a/file1 Tue Feb 10 18:23:27 2009 +0000
11 +++ b/file1 Tue Feb 10 18:23:27 2009 +0000
12 @@ -1,1 +1,3 @@
13 line 1
14 +line 2
15 +line 3
16
Figura 12.7: Refrescar un parche muchas veces para acumular cambios
Un parche aplicado tiene su correspondiente conjunto de cambios en el repositorio, y los efectos del parche y
el conjunto de cambios son visibles en el directorio de trabajo. Puede deshacer la aplicacion de un parche con la
orden “hg qpop”. MQ sabe acerca de, o maneja un parche sustraıdo, pero el parche ya no tendra un conjunto de
cambios correspondientes en el repositorio, y el directorio de trabajo no contendra los cambios hechos por el parche.
La figura 12.10 ilustra la diferencia entre parches aplicados y seguidos.
Puede reaplicar un parche no aplicado o sustraıdo con la orden “hg qpush”. Esto crea un nuevo conjunto de
cambios correspondiente al parche, y los cambios del parche estaran presentes de nuevo en el directorio de trabajo.
Vea ejemplos de “hg qpop” y “hg qpush” en accion en la figura 12.11. Vea que hemos sustraıdo uno o dos parches,
la salida de“hg qseries” continua igual, mientras que “hg qapplied” ha cambiado.
12.5.5. Introducir y sustraer muchos parchesMientras que “hg qpush” y “hg qpop” operan sobre un unico parche cada vez, puede introducir y sustraer varios
parches de una vez. La opcion -a de “hg qpush” introduce todos los cambios que no hayan sido aplicados, mientras
que la opcion -a de “hg qpop” sustrae todos los cambios aplicados. (Vea la seccion 12.7 mas adelante en la cual se
explican otras formas de de introducir y sustraer varios cambios.)
12.5.6. Medidas de seguridad y como saltarlas
Muchas ordenes MQ revisan el directorio de trabajo antes de hacer cualquier cosa, y fallan si encuentran alguna
modificacion. Lo hacen para garantizar que usted no pierda cambio alguno de los que haya hecho, pero que no hayan
sido incorporados en algun parche. La figura 12.13 ilusta esto; la orden “hg qnew” no creara un nuevo parche si hay
cambios notorios, causados en este caso por aplicado la orden “hg add” a file3.
Las ordenes que revisan el directorio actual cuentan con una opcion “Se lo que estoy haciendo”, que siempre
esta nombrada como -f. El significado exacto de -f depende de la orden. Por ejemplo, “hg qnew -f” incorporaran
cualquier cambio notorio en el nuevo parche que crea pero “hg qpop -f” revertira las modificaciones a cualquier
fichero que haya sido afectado por el parche que esta siendo sustraıdo. ¡Asegurese de leer la documentacion de la
opcion -f de cada comando antes de usarla!
146
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 157/204
1 $ hg qnew second.patch
2 $ hg log --style=compact --limit=2
3 2[qtip,second.patch,tip] 17da5d88f25b 2009-02-10 18:23 +0000 bos
4 [mq]: second.patch
5
6 1[first.patch,qbase] 4fef714d728c 2009-02-10 18:23 +0000 bos
7 [mq]: first.patch8
9 $ echo ’line 4’ >> file1
10 $ hg qrefresh
11 $ hg tip --style=compact --patch
12 2[qtip,second.patch,tip] 7cf293b98474 2009-02-10 18:23 +0000 bos
13 [mq]: second.patch
14
15 diff -r 4fef714d728c -r 7cf293b98474 file1
16 --- a/file1 Tue Feb 10 18:23:27 2009 +0000
17 +++ b/file1 Tue Feb 10 18:23:28 2009 +0000
18 @@ -1,3 +1,4 @@
19 line 1
20 line 221 line 3
22 +line 4
23
24 $ hg annotate file1
25 0: line 1
26 1: line 2
27 1: line 3
28 2: line 4
Figura 12.8: Aplicar un parche despues del primero
12.5.7. Trabajar con varios parches a la vez
La orden “hg qrefresh” siempre refresca el ´ ultimo parche aplicado. Esto significa que usted puede suspender su
trabajo en un parche (refrescandolo), sustraerlo o introducirlo para lograr que otro parche este de ultimo y trabajar en
ese parche por un rato.
A continuacion un ejemplo que ilustra como puede usar esta habilidad. Digamos que esta desarrollando una nueva
caracterıstica en dos parches. El primero es un cambio en la parte fundamental de su programa, y el segundo–sobre
el primero—cambia la interfaz de usuario para usar el codigo que ha anadido a la parte fundamental. Si ve que hay
un fallo en la parte fundamental mientras esta trabajando en el parche de UI5, es f acil arreglar la parte fundamental.
Simplemente use “hg qrefresh” sobre el parche de la UI para guardar los cambios de su trabajo en progreso, y use
“hg qpop” para sacar sustraer el parche de la parte fundamental. Arregla el fallo sobre la parte fundamental, aplique
“hg qrefresh” sobre el parche fundamental, y aplique “hg qpush” sobre el parche de UI para continuar donde habıa
quedado.
5N. del T. Interfaz de Usuario, User Interface en ingles
147
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 158/204
1 $ hg qseries
2 first.patch
3 second.patch
4 $ hg qapplied
5 first.patch
6 second.patch
Figura 12.9: Entender la pila de parches con “hg qseries” y “hg qapplied”
prevent−compiler−reorder.patch
namespace−cleanup.patch
powerpc−port−fixes.patc
report−devinfo−correctly.patch
{
{
presente en la serie,pero no aplicado
parches aplicados,Conjuntos de cambios presentes
parche aplicadomás recientemente 201ad3209902
126b84e593ae
a655daf15409
e50d59aaea3a
forbid−illegal−params.patch
fix−memory−leak.patc
Figura 12.10: Parches aplicados y no aplicados en la pila de parches de MQ
12.6. Mas acerca de parches
MQ usa la orden GNU patch para aplicar los parches, por lo tanto es util conocer ciertos detalles de como trabaja
patch, y tambien acerca de los parches.
12.6.1. La cantidad de franjas
Si ve el encabezado de un parche, notara que la ruta al fichero tiene un componente adicional al principio, que no
esta presente en la ruta. Esta es una traza de c omo generaba anteriormente los parches la gente (algunos aun lo hacen,
pero es raro con las herramientas de control de revisiones del actuales).
Alicia desempaquetarıa un comprimido, editarıa sus ficheros, y querrıa crear un parche. Por lo tanto ella renom-
brarıa su directorio de trabajo, desempacarıa el comprimido de nuevo (para lo cual necesito el renombramiento), y
usarıa las opciones -r y -N de diff para generar recursivamente un parche entre el directorio original y el modificado.
El resultado serıa que el nombre del directorio original estarıa al principio de toda ruta en cada encabezado de fichero,
y el nombre del directorio modificado estarıa al frente de la porcion derecha de la ruta del fichero.
Como alguien que reciba un parche de Alicia en la red podrıa obtener dos directorios, uno original y el otro modi-
ficado con exactamente los mismos nombres, la orden patch tiene la opcion -p que indica la cantidad de componentes
de la ruta a eliminar cuando se vaya a aplicar el parche. Este numero se llama la cantidad de eliminaciones.
La opcion con “-p1” significa “elimine uno”. Si patch ve un nombre de fichero foo/bar/baz en el encabezadodel fichero, eliminara foo y tratara de parchar un fichero llamado bar/baz. (Hablando estrictamente, la cantidad de
eliminaciones se refiere a la cantidad de separadores de ruta (y los componentes que vayan con ellos) a eliminar. Si el
contador es uno volvera foo/bar en bar, pero /foo/bar (note la barra extra) en foo/bar.)
La cantidad a eliminar“estandar” para parches es uno; casi todos los parches contienen un componente inicial de
la ruta que necesita ser eliminado. La orden “hg diff” de Mercurial genera nombres de ruta de esta forma, y la orden
“hg import” y MQ esperan parches que tengan a uno como cuenta de eliminaciones.
148
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 159/204
1 $ hg qapplied
2 first.patch
3 second.patch
4 $ hg qpop
5 Now at: first.patch
6 $ hg qseries
7 first.patch8 second.patch
9 $ hg qapplied
10 first.patch
11 $ cat file1
12 line 1
13 line 2
14 line 3
Figura 12.11: Modificar la pila de parches aplicados
1
$ hg qpush -a2 applying second.patch
3 Now at: second.patch
4 $ cat file1
5 line 1
6 line 2
7 line 3
8 line 4
Figura 12.12: Pushing all unapplied patches
Si recibe un parche de alguien de quien desea adicionar adicionar a su cola de parches, y el parche necesita unacuenta de eliminacion que no sea uno, no podra aplicar “hg qimport” en primera medida, porque “hg qimport”
no tiene todavıa una opcion -p option (ver Fallo de Mercurial No. 311). Lo mejor que puede hacer es aplicar “hg
qnew” por su cuenta, y despues usar “patch -pN ” para aplicar tal parche, seguido de “hg addremove” para tener en
cuenta cualquier fichero adicionado o eliminado por el parche, seguido de “hg qrefresh”. Esta complejidad puede
ser innecesaria; consulte Fallo de Mercurial No. 311 para mas informacion.
12.6.2. Estrategias para aplicar parches
Cuando patch aplica un trozo, intenta varias estrategias sucesivas que decrecen en precision para intentar aplicarlo.
Esta tecnica de pruebas y error aveces permite que un parche que fue generado contra una version anterior de un
fichero, sea aplicada sobre una version mas nueva del mismo.
Primero patch intenta una correspondencia perfecta donde los numeros de lınea, el contexto y el texto a modificar
deben coincidir perfectamente. Si no lo logra, intenta encontrar una correspondencia exacta del contexto, sin tener encuenta el numero de lınea. Si es exitoso, imprime una lınea indicando que el trozo fue aplicado, pero a un corrimiento
del numero de lınea original.
Si falla la correspondencia por contexto, patch elimina la primera y la ultima lınea del contexto, e intenta una
correspondencia reducida del contexto. Si el trozo con contexto reducido es exitoso, imprime un mensaje indicando
que aplico el trozo con un factor difuso (el numero despues del factor difuso indica cuantas lıneas de contexto patch
tuvo que eliminar antes de aplicar el parche).
149
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 160/204
1 $ echo ’file 3, line 1’ >> file3
2 $ hg qnew add-file3.patch
3 $ hg qnew -f add-file3.patch
4 abort: patch "add-file3.patch" already exists
Figura 12.13: Crear un parche a la fuerza
Cuando ninguna de estas tecnicas funciona, patch imprime un mensaje indicando que el trozo en cuestion se
desecho. Almacena los trozos desechados (tambien llamados “descartados”) en un fichero con el mismo nombre, y la
extension .rej anadida. Tambien almacena una copia igual al fichero original con la extension .orig; la copia del
fichero sin extension contendra cualquier cambio hecho por los trozos que sı se aplicaron sin problema. Si usted tiene
un parche que modifica foo con seis trozos, y uno de ellos falla al aplicarse, tendra : un fichero original foo.orig, un
fichero foo.rej que contiene el trozo, y foo, que contiene los cambios que se aplicaron por los cinco trozos exitosos.
12.6.3. Algunos detalles de la representacion de parches
Hay ciertas cosas utiles por saber acerca de como trabaja patch con los ficheros:
Deberıa ser obvio que patch no puede manipular ficheros binarios.
No se preocupa por el bit ejecutable; crea ficheros nuevos en modo lectura, pero no ejecutable.
patch intenta eliminar un fichero como una diferencia entre el fichero a eliminar y un fichero vac ıo. Y por lo
tanto su idea de “Borre este fichero” deberıa pensarse como “toda lınea de este fichero fue eliminada” en un
parche.
Trata la adicion de un fichero como un diff entre un fichero vacıo y el fichero a ser adicionado. Por lo tanto en
un parche su idea de “Anadı este fichero” se verıa como “toda lınea de este fichero fue anadida”.
Trata el renombramiento de un fichero como la eliminacion del nombre anterior y la adicion del nuevo nombre.
Esto significa que los ficheros renombrados dejan un rastro grande en los parches. (Tenga en cuenta que Mercu-
rial no trata de inferir cuando los ficheros han sido renombrados o copiados en un parche en este momento.)
patch no puede representar ficheros vacıos, por lo tanto no puede usar un parche para representar la nocion
“Anadı este fichero vacıo al arbol”.
12.6.4. Cuidado con los difusos
Cuando aplique un trozo con un corrimiento, o con un factor difuso, aveces ser a taotalmente exitoso, tales tecnicas
inexactas dejan claramente la posibilidad de corromper el fichero parchado. Los casos m as tıpicos involucran aplicar
un parche dos veces o en un sitio incorrecto del fichero. Si patch o “hg qpush” llegan a mencionar un corrimiento o
un factor difuso, deberıa asegurarse que los ficheros modificados esten correctos despues del suceso.
Casi siempre es buena idea refrescar un parche que fue aplicado con un corrimiento o un factor difuso; refrescar el
parche genera nueva informacion de contexto que permitira aplicarlo limpiamente. Digo “casi siempre,” no “siempre”,
puesto que en ciertas ocasiones refrescar un parche lo hara fallar frente a una revision diferente del fichero. En algunos
casos, como por ejemplo, cuando usted esta manteniendo un parche que debe estar encima de multiples revisiones de
un arbol de fuentes, es aceptable tener un parche aplicado algo difuso, siempre que haya verificado los resultados del
proceso de parchar.
150
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 161/204
12.6.5. Manejo de descartes
Si “hg qpush” falla al aplicar un parche, mostrara un texto de error y saldra. Si ha dejado ficheros .rej, es mejor
arreglar los trozos descartados antes de introducir parches adicionales o hacer cualquier otra cosa.
Si su parche sol ıa aplicarse limpiamente, y ya no lo hace porque ha cambiado c odigo subyacente en el cual se basa
su parche, las Colas de Mercurial pueden ayudar; consulte la seccion 12.8.
Desafortunadamente, no hay grandes tecnicas para tratar los trozos descartados. Casi siempre debera consultar el
fichero .rej y editar el fichero objetivo, aplicando los trozos descartados a mano.
Si es aventurero, Neil Brown, un hacker del n ucleo Linux, escribio una herramienta llamada wiggle [Bro], que es
mas vigorosa que patch en su intento de hacer que se aplique un parche.
Otro hacker del nucleo Linux, Chris Mason (el autor de las Colas de Mercurial), escribio una herramienta similar
llamada mpatch [Mas], que sigue una aproximacion sencilla para automatizar la aplicacion de trozos descartados por
patch. La orden mpatch puede ayudar con cuatro razones comunes por las cuales un parche ha sido descartado:
El contexto en la mitad de un trozo ha cambiado.
Un trozo ha perdido cierto contexto al principio o al final.
Un trozo largo podrıa aplicarse mejor—por completo o una parte—si estaba cortado en trozos m as pequenos.
Un trozo remueve lıneas con contenido ligeramente diferente que aquellas que estan presentes en el fichero.
Si usted usa wiggle o mpatch, deberıa ser doblemente cuidadoso al revisar sus resultados cuando haya terminado.
De hecho, mpatch refuerza este metodo de revisar por partida doble su salida, dejandolo a usted en un programa de
fusion cuando la herramienta haya terminado su trabajo, de tal forma que usted pueda verificar lo que ha hecho y
pueda terminar de aplicar cualquier fusion faltante.
12.7. maximizar el rendimiento de MQ
MQ es muy eficiente al tratar con una gran cantidad de parches. Corrı unos experimentos de desempeno a mediados
del 2006 para una charla que dı en la conferencia EuroPython 2006 [O’S06]. Emplee la serie de parches para el nucleo
Linux 2.6.17-mm1, que contaba con 1.738 parches. Los aplique sobre un repositorio del nucleo de Linux con todas
las 27.472 revisiones entre 2.6.12-rc2 y 2.6.17.
En mi portatil antiguo y lento, logre aplicar “hg qpush -a” a los 1.738 parches en 3.5 minutos, y “hg qpop -a”en 30 segundos. (En un portatil mas nuevo, el tiempo para introducir todos los parches, se logro en menos de dos
minutos.) Aplique “hg qrefresh” sobre uno de los parches mas grandes (que hizo 22.779 lıneas de cambios en 287
ficheros) en 6,6 segundos.
Claramente, MQ funciona adecuadamente en arboles grandes, y ademas hay unos trucos que pueden emplearse
para obtener el maximo desempeno.
En primer lugar, trate de hacer “en lote” las operaciones. Cada vez que ejecute “hg qpush” o “hg qpop”, tales
ordenes revisan el directorio de trabajo para asegurarse de que usted no ha hecho cambios y ha olvidado ejecutar “hg
qrefresh”. En un arbol pequeno, el tiempo de esta revision puede ser mınimo, Pero en un arbol mediano (con decenas
de miles de ficheros), puede tomar un segundo o mas.
Las ordenes “hg qpush” y “hg qpop” le permiten introducir o sustraer varios parches en una operacion. Puede
identificar el “parche destino” que desee. Cuando aplique “ hg qpush” con un destino, introducira tantos parches
como sea necesario hasta que el especificado este en el tope de la pila. Cuando emplee “hg qpop” con un destino, MQ
sustraera parches hasta que el parche destino este en el tope.
Puede identificar un parche destino con el nombre del parche o con el numero. Si se refiere al numero, los parches
se contaran desde cero; esto significa que el primer parche es cero, el segundo es uno y as ı sucesivamente.
151
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 162/204
12.8. Actualiar los parches cuando el codigo cambia
Es comun contar con una pila de parches sobre un repositorio que usted no modifica directamente. Si esta traba-
jando en cambios de codigo de otros, o en una caracterıstica que tarda bastante en desarrollarse comparada con la tasa
de cambio del codigo sobre la cual se esta trabajando, necesitara sincronizarse con el codigo, y ajustar cualquier trozo
en sus parches que ya no esten al dıa. A esto se le llama hacer rebase a su serie de parches.
La vıa mas sencilla de hacerlo es con “hg qpop -a” sobre sus parches, despues hacer “hg pull” de los cambiosen el repositorio, y finalmente hacer “hg qpush -a” con sus parches de nuevo. MQ dejara de de introducir parches
siempre que llegue a un parche que no se pueda aplicar debido a un conflicto, permitiendole a usted arreglarlo, aplicar
“hg qrefresh” al parche afectado y continuar introduciendo hasta que haya arreglado la pila completa.
Esta aproximacion es sencilla y funciona bien si no espera cambios en el codigo original que afecte en gran medida
los parches que usted este aplicando. Si su pila de parches toca codigo que es modificado frecuentemente o de forma
invasiva sobre el codigo subyacente, arreglar trozos manualmente se vuelve desgastante.
Es posible automatizar de forma parcial el proceso de rebase. Si sus parches se aplican limpiamente sobre algunas
revisiones del repositorio subyacente, MQ puede usar esta informaci on para ayudarle a a resolver conflictos entre sus
parches y una revision distinta.
El proceso resulta un poco complejo:
1. Para comenzar, haga “hg qpush -a” sobre todos los parches que usted sepa se aplican limpiamente.
2. Guarde una copia de seguridad de su directorio de parches con “hg qsave -e -c”. Esto imprime el nom-bre del directorio en el cual se han guardado los parches. Guardar a los parches en un directorio llamado
.hg/patches.N , donde N es un entero pequeno. Tambien consigna un “conjunto de cambios de seguridad”
sobre sus parches aplicados; esto es para mantener el hist orico, y guarda los estados de los ficheros series y
status.
3. Use “hg pull” para traer los nuevos cambios en el repositorio subyacente. (No ejecute “ hg pull -u”; vea mas
adelante por que.)
4. Actualice a la nueva revision punta con “hg update -C” para sobreescribir los parches que haya introducido.
5. Fusione todos los parches con “hg qpush -m -a”. La opcion -m de “hg qpush” le indica a MQ que haga una
fusion que involucra tres fuentes si el parche falla al aplicarse.
Durante el “hg qpush -m”, cada parche en el fichero series se aplica normalmente. Si un parche se aplicadifusamente o se niea a aplicarse, MQ consulta la cola que usted guardo con “hg qsave”, y aplica una fusion de tres
con el correspondiente conjunto de cambios. Esta fusion usa la maquinaria de Mercurial, por lo tanto puede mostrar
una herramienta de fusion GUI para ayudarle a resolver los problemas.
Cuando termine de resolver los efectos de un parche, MQ refrescar a su parche basado en el resultado de la fusion.
Al final de este proceso, su repositorio tendra una cabeza extra de la antigua cola de parches, y una copia de la
cola de parches anterio estara en .hg/patches.N . Puede eliminar la cabeza extra con “hg qpop -a -n patches.N ”
o “hg strip”. Puede eliminar .hg/patches.N una vez que este seguro de que no lo necesita mas como copia de
seguridad.
12.9. Identificar parches
Las ordenes de MQ le permiten trabajar refiriendose al nombre del parche o al numero. Es obvio hacerlo por elnombre; por ejemplo se pasa el nombre foo.patch a “hg qpush”, que introducira los parches hasta que foo.patch
se aplique.
Para hacerlo mas corto, puede referirse a un parche con un nombre y un corrimiento de n umero; por ejemplo,
foo.patch-2 significa “dos parches antes de foo.patch”, mientras que bar.patch+4 significa “cuatro parches de-
spues de bar.patch”.
152
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 163/204
Referirse a un parche por su ındice no es muy diferente. El primer parche que se imprime en la salida de “ hg
qseries” es el parche cero (si, es el primero en los sistemas que comienzan su conteo en cero); el segundo parche es
uno y ası sucesivamente.
MQ facilita el trabajo cuando esta usando ordenes normales de Mercurial. Cada comando que acepte Identifi-
cadores de conjuntos de cambios tambien aceptara el nombre de un parche aplicado. MQ aumenta las etiquetas nor-
malmente en el repositorio con un distintivo para cada parche aplicado. Adicionalmente, las etiquetas especiales qbase
y qtip identifican los parches “primero” y ultimo, respectivamente.Junto con las capacidades de Mercurial para etiquetar, estas adiciones hacen que trabajar con parches sea muy
sencillo.
¿Desea enviar una bomba de parches a una lista de correo con los ultimos cambios que ha hecho?
1 hg email qbase:qtip
(¿No sabe que es una “bomba de parches”? Consulte la seccion 14.4.)
¿Desea ver todos los parches desde que se aplico foo.patch sobre los ficheros de un subdirectorio en su arbol?
1 hg log -r foo.patch:qtip subdir
Dado que MQ nombra los parches disponibles al resto de Mercurial con su maquinaria de etiquetas interna, usted
no necesita teclear el nombre completo de un parche cuando desea identificarlo por su nombre.
Otra consecuencia deseable al representar los nombres de parches como etiquetas es que cuando ejecute la orden
“hg log”, desplegara el nombre del parche como una etiqueta, usualmente con la salida normal. Esto facilita distinguir
visualmente los parches aplicados de las revisiones “normales”. La figura 12.14 muestra algunos comandos usuales de
Mercurial al trabajar con parches.
12.10. Otra informacion util
Hay una cantidad de aspectos que hacen que el uso de MQ no representen secciones en sı mismas, pero de los
cuales es bueno estar enterado. Los presentamos en aquı:
Usualmente cuando hace “hg qpop” a un parche y vuelve a hacerle “hg qpush”, el conjunto de cambios querepresenta el parche despues de introducir/sustraer tendra una identidad distinta que aquella que representaba el
conjunto de cambios anteriormente. Consulte la secction B.1.13 para obtener informacion del por que de esto.
No es una buena idea aplicar “hg merge” de cambios de otra rama con un conjunto de cambios de parches, por
lo menos si desea mantener la “informacion de parches” de ese conjunto de cambios y los conjuntos de cambios
que se encuentran por debajo en la pila de parches. Si intenta hacerlo, parecer a que ha sido exitoso, pero MQ se
confundira.
12.11. Administrar parches en un repositorio
Dado que el directorio .hg/patches de MQ reside fuera del repositorio de trabajo de Mercurial, el repositorio
“subyacente” de Mercurial no sabe nada acerca de la administraci on o presencia de parches.Esto presenta la interesante posibilidad de administrar los contenidos del directorio de parches como un repositorio
de Mercurial por su cuenta. Puede ser una forma util de trabajar. Por ejemplo, puede trabajar en un parche por un rato,
hacerle “hg qrefresh” y despues hacer “hg commit” al estado actual del parche. Esto le permite “devolverse” a esa
version del parche posteriormente.
Puede tambien compartir diferentes versiones de la misma pila de parches entre varios repositorios subyacentes.
Uso esto cuando estoy desarrollando una caracterıstica del nucleo Linux. Tengo una copia original de las fuentes del
153
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 164/204
1 $ hg qapplied
2 first.patch
3 second.patch
4 $ hg log -r qbase:qtip
5 changeset: 1:b3508ccf62ad
6 tag: first.patch
7 tag: qbase8 user: Bryan O’Sullivan <[email protected]>
9 date: Tue Feb 10 18:23:26 2009 +0000
10 summary: [mq]: first.patch
11
12 changeset: 2:c836697fbf55
13 tag: qtip
14 tag: second.patch
15 tag: tip
16 user: Bryan O’Sullivan <[email protected]>
17 date: Tue Feb 10 18:23:26 2009 +0000
18 summary: [mq]: second.patch
19
20 $ hg export second.patch21 # HG changeset patch
22 # User Bryan O’Sullivan <[email protected]>
23 # Date 1234290206 0
24 # Node ID c836697fbf55654f972d867359527813dbbc5d44
25 # Parent b3508ccf62adb8916c6a7b64105642fa516f5a90
26 [mq]: second.patch
27
28 diff -r b3508ccf62ad -r c836697fbf55 other.c
29 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30 +++ b/other.c Tue Feb 10 18:23:26 2009 +0000
31 @@ -0,0 +1,1 @@
32 +double u;
Figura 12.14: Uso de las caracterısticas de etiquetamiento al trabajar con MQ
nucleo para varias arquitecturas, y clone un rpositorio en cada una que contiene los parches en los cuales estoy traba-
jando. Cuando quiero probar un cambio en una arquitectura diferente, introduzco mis parches actuales al repositorio
de parches asociado con el arbol del kernel, sustraigo e introduzco todos mis parches, armo y pruebo el nucleo.
Llevar los parches en un repositorio permite que varios desarrolladores puedan trabajar en la misma serie de
parches sin sobreponerse, todo sobre la fuente base subyacente que pueden o no controlar.
12.11.1. Soporte de MQ para repositorios de parches
MQ le ayuda a trabajar con el directorio .hg/patches como un repositorio; cuando usted prepara un repositorio
para trabajar con parches usando “hg qinit”, puede pasarle la opcion -c para que se cree el directorio .hg/patches
como un repositorio de Mercurial.
154
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 165/204
Nota: Si olvida usar la opcion -c option, puede ir al directorio .hg/patches
en cualquier momento y ejecutar “hg init”. No olvide anadir una entrada en el
fichero status del fichero .hgignore, a pesar de que (“hg qinit -c” hace esto-
do de forma automatica para usted); usted seguro no quiere administrar el fichero
status.
MQ nota convenientemente que el directorio .hg/patches es un repositorio, hara “hg add” automaticamente a
cada parche que usted cree e importe.MQ provee una orden corta, “hg qcommit”, que ejecuta “hg commit” en el directorio .hg/patches. Lo que
ahorra tecleo recurrente.
Finalmente, para administrar convenientemente el directorio de parches, puede definir el alias mq en sistemas Unix.
Por ejemplo, en sistemas Linux con el interprete bash, puede incluir el siguiente recorte de codigo6 en su fichero
˜/.bashrc.
1 alias mq=‘hg -R $(hg root)/.hg/patches’
Puede aplicar las ordenes de la forma “mq pull” al repositorio principal.
12.11.2. Detalles a tener en cuenta
El soporte de MQ para trabajar con un repositorio de parches es limitado en ciertos aspectos:MQ no puede detectar automaticamente los cambios que haga al directorio de parches. Si aplica “ hg pull”, edita
manualmente, o hace “hg update” a los parches o el fichero series, tendra que aplicar “hg qpop -a” y despues “hg
qpush -a” en el repositorio subyacente para que los cambios se reflejen all ı. Si olvida hacerlo, puede confundir a MQ
en cuanto a que parches se han aplicado.
12.12. Otras herramientas para trabajar con parches
Cuando haya trabajado por cierto tiempo con parches, deseara herramientas que le ayuden a entender y manipular
los parches con los que este tratando.
La orden diffstat [Dic] genera un histograma de modificaciones hechas a cada fichero en un parche. Provee una
interesante forma de “dar un vistazo” al parche—que ficheros afecta, y cuantos cambios introduce a cada fichero y
en total. (Me ha parecido interesante usar la opcion -p de diffstat, puesto que de otra forma intentara hacer cosasinteligentes con prefijos de ficheros que terminan confundiendome.)
El paquete patchutils [Wau] es invaluable. Provee un conjunto de pequenas utilidades que siguen la “filosof ıa
Unix”; cada una hace una cosa muy bien hecha a un parche. La orden patchutils que mas uso es filterdiff,
que extrae subconjuntos de un fichero de parche. Por ejemplo, dado un parche que modifica centenas de ficheros en
docenas de directorios, una unica invocacion de filterdiff puede generear un parche mas pequeno que solamente
toca aquellos ficheros con un patron. Puede ver otro ejemplo en la seccion 13.9.2.
12.13. Buenas practicas de trabajo con parches
En caso de que este trabajando en una serie de parches para enviar a un proyecto de software libre o de fuentes
abiertas, o en una serie que desea tratar como un conjunto de cambios regular, cuando haya terminado, puede usar
tecnicas sencillas para mantener su trabajo bien organizado.De nombres descriptivos a sus parches. Un buen nombre para un parche podrıa ser rework-device-alloc.patch ,
porque da de forma inmediata una pista del proposito del parche. Los nombres largos no deben ser un problema; no
los estara tecleando repetidamente, pero estar a ejecutando regularmente ordenes como “hg qapplied” y “hg qtop”.
Los nombres adecuados son especialmente importantes cuando tiene bastantes parches con los cuales trabajar, o si
esta trabajando en diferentes tareas y sus parches toman solamente una porcion de su atencion.
6N. del T. snippet
155
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 166/204
1 $ diffstat -p1 remove-redundant-null-checks.patch
2 drivers/char/agp/sgi-agp.c | 5 ++---
3 drivers/char/hvcs.c | 11 +++++------
4 drivers/message/fusion/mptfc.c | 6 ++----
5 drivers/message/fusion/mptsas.c | 3 +--
6 drivers/net/fs_enet/fs_enet-mii.c | 3 +--
7 drivers/net/wireless/ipw2200.c | 22 ++++++----------------8 drivers/scsi/libata-scsi.c | 4 +---
9 drivers/video/au1100fb.c | 3 +--
10 8 files changed, 19 insertions(+), 38 deletions(-)
11 $ filterdiff -i ’*/video/*’ remove-redundant-null-checks.patch
12 --- a/drivers/video/au1100fb.c˜remove-redundant-null-checks-before-free-in-drivers
13 +++ a/drivers/video/au1100fb.c
14 @@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void)
15 {16 driver_unregister(&au1100fb_driver);
17
18 - if (drv_info.opt_mode)
19 - kfree(drv_info.opt_mode);
20 + kfree(drv_info.opt_mode);21 }22
23 module_init(au1100fb_init);
Figura 12.15: Las ordenes diffstat, filterdiff, y lsdiff
Tenga en cuenta en que parche esta trabajando. Use la orden “hg qtop” para dar un vistazo al texto de sus parches
frecuentemente—por ejemplo, use “hg tip -p”)—para asegurarse en donde esta ubicado. En distintas oportunidades
me sucedio que aplique “hg qrefresh” a un parche distinto al que deseaba hacerlo, y usualmente es complejo migrar
los cambios al parche correcto despues de haberlo hecho mal.
Por este motivo, vale la pena invertir ese poco tiempo para aprender como usar otras herramientas que describı en
la seccion 12.12, particularmente diffstat y filterdiff. La primera le dara una idea de que cambios esta haciendo
su parche, mientras que la segunda permite seleccionar trozos de un parche para colocarlos en otro.
12.14. Recetas de MQ
12.14.1. Administrar parches “triviales”
Puesto que colocar ficheros en un repositorio de Mercurial es tan sencillo, tiene bastante sentido administrar parch-
es de esta forma incluso si desea hacer algunos cambios al paquete de ficheros que descargo.
Para comenzar a descargar y desempaqueter un paquete de ficheros, y volverlo en un repositorio de Mercurial:
1 $ download netplug-1.2.5.tar.bz22 $ tar jxf netplug-1.2.5.tar.bz2
3 $ cd netplug-1.2.5
4 $ hg init
5 $ hg commit -q --addremove --message netplug-1.2.5
6 $ cd ..
7 $ hg clone netplug-1.2.5 netplug
156
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 167/204
8 updating working directory
9 18 files updated, 0 files merged, 0 files removed, 0 files unresolved
Continue creando una pila de parches y haga sus cambios.
1 $ cd netplug
2 $ hg qinit3 $ hg qnew -m ’fix build problem with gcc 4’ build-fix.patch
4 $ perl -pi -e ’s/int addr_len/socklen_t addr_len/’ netlink.c
5 $ hg qrefresh
6 $ hg tip -p
7 changeset: 1:4adf6cb9cc16
8 tag: qtip
9 tag: build-fix.patch
10 tag: tip
11 tag: qbase
12 user: Bryan O’Sullivan <[email protected]>
13 date: Tue Feb 10 18:23:26 2009 +0000
14 summary: fix build problem with gcc 4
15
16 diff -r ca53495653b5 -r 4adf6cb9cc16 netlink.c
17 --- a/netlink.c Tue Feb 10 18:23:26 2009 +0000
18 +++ b/netlink.c Tue Feb 10 18:23:26 2009 +0000
19 @@ -275,7 +275,7 @@
20 exit(1);
21 }22
23 - int addr_len = sizeof(addr);
24 + socklen_t addr_len = sizeof(addr);
25
26 if (getsockname(fd, (struct sockaddr *) &addr, &addr_len) == -1) {27 do_log(LOG_ERR, "Could not get socket details: %m");
28
Digamos que pasan unas semanas o meses, y el autor del paquete libera una nueva version. Primero se traen sus
cambios al repositorio.
1 $ hg qpop -a
2 Patch queue now empty
3 $ cd ..
4 $ download netplug-1.2.8.tar.bz2
5 $ hg clone netplug-1.2.5 netplug-1.2.8
6 updating working directory
7 18 files updated, 0 files merged, 0 files removed, 0 files unresolved
8 $ cd netplug-1.2.8
9 $ hg locate -0 | xargs -0 rm
10 $ cd ..
11 $ tar jxf netplug-1.2.8.tar.bz2
12 $ cd netplug-1.2.8
13 $ hg commit --addremove --message netplug-1.2.8
La porcion que comienza con “hg locate” mostrada mas arriba, borra todos los ficheros en el directorio de trabajo,
157
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 168/204
ası que la opcion --addremove de “hg commit” puede indicar que ficheros se han eliminado en la nueva version del
arbol de fuentes.
Finalmente, puede aplicar sus parches encima del nuevo arbol de fuentes
1 $ cd ../netplug
2 $ hg pull ../netplug-1.2.8
3
pulling from ../netplug-1.2.84 searching for changes
5 adding changesets
6 adding manifests
7 adding file changes
8 added 1 changesets with 12 changes to 12 files
9 (run ’hg update’ to get a working copy)
10 $ hg qpush -a
11 (working directory not at tip)
12 applying build-fix.patch
13 Now at: build-fix.patch
12.14.2. Combinar parches completosMQ provee la orden “hg qfold” que le permite combinar parches enteros. Se “integran” 7 los parches que ust-
ed nombre, en el orden que especifique, en el ultimo parche aplicado, y concatena sus descripciones al final de su
descripcion. Debera sustraer los cambios para poder integrarlos.
El orden en el que integre los parches importa. Si el parche ultimamente aplicado es foo, e integra “hg qfold”
bar y quux en el, terminara con un parche que tiene el mismo efecto que si hubiera aplicado primero foo, y despues
bar, seguido de quux.
12.14.3. Fusionar una porcion de un parche dentro de otro
Fusionar partes de un parche dentro de otro es mas complejo que combinar completamente dos parches.
Si desea mover cambios de ficheros completos, puede usar las opciones filterdiff’s -i y -x para elegir las
modificaciones remover de un parche, concatenar su salida al final del parche donde desea fusionarlo. Usualmente
no necesitara modificar el parche del cual ha fusionado los cambios. En cambio, MQ reportara que hay unos trozos
que se han desechado cuando usted aplique “hg qpush” (de los trozos que haya movido al otro parche), y puede
sencillamente aplicar “hg qrefresh” para eliminar los trozos replicados.
Si tiene un parche que tiene varios trozos que modifican un fichero, y desea mover solamente unos de ellos, el
trabajo es un poco mas enredado, pero puede automatizarlo parcialmente. Use “lsdiff -nvv” para imprimir algunos
metadatos del parche.
1 $ lsdiff -nvv remove-redundant-null-checks.patch
2 22 File #1 a/drivers/char/agp/sgi-agp.c
3 24 Hunk #1 static int __devinit agp_sgi_init(void)
4 37 File #2 a/drivers/char/hvcs.c
5 39 Hunk #1 static struct tty_operations hvcs_ops =
6
53 Hunk #2 static int hvcs_alloc_index_list(int n)7 69 File #3 a/drivers/message/fusion/mptfc.c
8 71 Hunk #1 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
9 85 File #4 a/drivers/message/fusion/mptsas.c
10 87 Hunk #1 mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
11 98 File #5 a/drivers/net/fs_enet/fs_enet-mii.c
7N. del T. fold
158
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 169/204
12 100 Hunk #1 static struct fs_enet_mii_bus *create_bu
13 111 File #6 a/drivers/net/wireless/ipw2200.c
14 113 Hunk #1 static struct ipw_fw_error *ipw_alloc_er
15 126 Hunk #2 static ssize_t clear_error(struct device
16 140 Hunk #3 static void ipw_irq_tasklet(struct ipw_p
17 150 Hunk #4 static void ipw_pci_remove(struct pci_de
18 164 File #7 a/drivers/scsi/libata-scsi.c19 166 Hunk #1 int ata_cmd_ioctl(struct scsi_device *sc
20 178 File #8 a/drivers/video/au1100fb.c
21 180 Hunk #1 void __exit au1100fb_cleanup(void)
Esta orden imprime tres clases diferentes de numeros:
(en la primera columna) un n´ umero de fichero para identificar cada fichero modificado en el parche;
(En la siguiente lınea, indentado) el numero de lınea dentro de un fichero modificado donde comienza el trozo;
y
(en la misma lınea) un n´ umero de trozo que identifica el trozo.
Tendra que hacer una inspeccion visual, y leer el parche para identificar los n umeros de fichero y trozo que desea,pero puede pasar posteriormente a las opciones --files y --hunks de filterdiff, para seleccionar exactamente el
fichero y el trozo que desea extraer.
Cuando tenga el trozo, puede concatenarlo al final de su parche objetivo y continuar como en la seccion 12.14.2.
12.15. Diferencias entre quilt y MQ
Si le es familiar quilt, MQ provee un conjunto similar de ordenes. Hay algunas diferencias en como funcionan.
Debe haber notado que la mayorıa de comandos de quilt tienen su contraparte en MQ, que simplemente comienzan
con “q”. Las excepciones son las ordenes add y remove de quilt, que realmente son las ordenes “hg add” y “hg
remove” de Mercurial. No hay un equivalente en MQ para la orden edit de quilt.
159
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 170/204
Capıtulo 13
Usos avanzados de las Colas de Mercurial
Auunque es facil aprender los usos mas directos de las Colas de Mercurial, tener algo de disciplina junto con
algunas de las capacidadees menos usadas de MQ hace posible trabajar en entornos de desarrollo complejos.
En este capıtulo, usare como ejemplo una tecnica que he usado para administrar el desarrollo de un controlador de
dispositivo Infiniband para el kernel de Linux. El controlador en cuestion es grande (al menos en lo que se refiere a
controladores), con 25,000 lıneas de codigo esparcidas en 35 ficheros fuente. Es mantenido por un equipo pequeno dedesarrolladores.
Aunque mucho del material en este capıtulo es especıfico de Linux, los mismos principios aplican a cualquier base
de codigo de la que usted no sea el propietario principal, y sobre la que usted necesita hacer un mont on de desarrollo.
13.1. El problema de multiples objetivos
El kernel de Linux cambia con rapidez, y nunca ha sido estable internamente; los desarrolladores hacen cambios
drasticos entre versiones frecuentemente. Esto significa que una version del controlador que funciona bien con una
version particular del kernel ni siquiera compilar´ a correctamente contra, tıpicamente, cualquier otra version.
Para mantener un controlador, debemos tener en cuenta una buena cantidad de versiones de Linux en mente.
Un objetivo es el arbol de desarrollo principal del kernel de Linux. En este caso el mantenimiento del codigo
es compartido parcialmente por otros desarrolladores en la comunidad del kernel, quienes hacen modificaciones
“de-afan” al controlador a medida que desarrollan y refinan subsistemas en el kernel.
Tambien mantenemos algunos “backports” para versiones antiguas del kernel de Linux, para dar soporte a
las necesidades de los clientes que estan corriendo versiones antiguas de Linux que no incorporan nuestros
controladores. (Hacer el backport de un pedazo de codigo es modificarlo para que trabaje en una version de su
entorno objetivo anterior a aquella para la cual fue escrito.)
Finalmente, nosotros liberamos nuestro software de acuerdo a un cronograma que no necesariamente est a alin-
eado con el que usan los distribuidores de Linux y los desarrolladores del kernel, ası que podemos entregar
nuevas caracterısticas a los clientes sin forzarlos a actualizar kernels completos o distribuciones.
13.1.1. Aproximaciones tentadoras que no funcionan adecuadamente
Hay dos maneras estandar de mantener una porcion de software que debe funcionar en muchos entornos diferentes.
La primera es mantener varias ramas, cada una pensada para un unico entorno. El problema de esta aproximacion
es que usted debe tener una disciplina f errea con el flujo de cambios entre repositorios. Una nueva caracter ıstica o un
arreglo de fallo deben empezar su vida en un repositorio “pr ıstino”, y luego propagarse a cada repositorio de backport.
Los cambios para backports estan mas limitados respecto a las ramas a las que deber ıan propagarse; un cambio para
backport que es aplicado a una rama en la que no corresponde probablemente hara que el controlador no compile.
160
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 171/204
La segunda es mantener un unico arbol de codigo fuente lleno de declaraciones que activen o desactiven secciones
de codigo dependiendo del entorno objetivo. Ya que estos “ifdefs” no est an permitidos en el arbol del kernel de Linux,
debe seguirse algun proceso manual o automatico para eliminarlos y producir un arbol limpio. Una base de codigo
mantenida de esta manera se convierte rapidamente en un nido de ratas de bloques condicionales que son dif ıciles de
entender y mantener.
Ninguno de estos enfoques es adecuado para situaciones en las que usted no es “dueno” de la copia canonica
de un arbol de fuentes. En el caso de un controlador de Linux que es distribuido con el kernel est andar, el arbol deLinux contiene la copia del codigo que sera considerada por el mundo como la canonica. La version oficial de “mi”
controlador puede ser modificada por gente que no conozco, sin que yo siquiera me entere de ello hasta despu es de
que los cambios aparecen en el arbol de Linus.
Estos enfoques tienen la debilidad adicional de dificultar la generacion de parches bien formados para enviarlos a
la version oficial.
En principio, las Colas de Mercurial parecen ser un buen candidato para administrar un escenario de desarrollo
como el de arriba. Aunque este es de hecho el caso, MQ tiene unas cuantas caracter ısticas adicionales que hacen el
trabajo mas agradable.
13.2. Aplicar parches condicionalmente mediante guardias
Tal vez la mejor manera de conservar la cordura con tantos entornos objetivo es poder escoger parches especıficospara aplicar para cada situacion. MQ provee una caracterıstica llamada “guardias” (que se origina del comando guards
de Quilt) que hace precisamente esto. Para empezar, creemos un repositorio sencillo para experimentar.
1 $ hg qinit
2 $ hg qnew hello.patch
3 $ echo hello > hello
4 $ hg add hello
5 $ hg qrefresh
6 $ hg qnew goodbye.patch
7 $ echo goodbye > goodbye
8 $ hg add goodbye
9 $ hg qrefresh
Esto nos brinda un pequeno repositorio que contiene dos parches que no tienen ninguna dependencia respecto al otro,
porque tocan ficheros diferentes.
La idea detras de la aplicacion condicional es que usted puede “etiquetar” un parche con un guardia, que sim-
plemente es una cadena de texto de su eleccion, y luego decirle a MQ que seleccione guardias especıficos para usar
cuando aplique parches. MQ entonces aplicara, u omitira, un parche vigilado, dependiendo de los guardias que usted
haya seleccionado.
Un parche puede tener una cantidad arbitraria de guardias; cada uno es positivo (“aplique el parche si este guardia
es seleccionado”) o negativo (“omita este parche si este guardia es seleccionado”). Un parche sin guardias siempre es
aplicado.
13.3. Controlar los guardias de un parche
El comando “hg qguard” le permite determinar que guardias deben aplicarse a un parche, o mostrar los guardias
que estan en efecto. Sin ningun argumento, el comando muestra los guardias del parche actual de la parte m as alta de
la pila.
1 $ hg qguard
2 goodbye.patch: unguarded
161
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 172/204
Para poner un guardia positivo en un parche, prefije el nombre del guardia con un “+”.
1 $ hg qguard +foo
2 $ hg qguard
3 goodbye.patch: +foo
Para poner un guardia negativo en un parche, prefije el nombre del guardia con un “-”.
1 $ hg qguard hello.patch -quux
2 $ hg qguard hello.patch
3 hello.patch: -quux
Nota: El comando “hg qguard” pone los guardias en un parche; no los modifica.
Esto significa que si usted ejecuta “hg qguard +a +b” sobre un parche, y luego
“hg qguard +c” en el mismo parche, el unico guardia sobre el parche despues del
comando sera +c.
Mercurial almacena los guardias en el fichero series; la forma en que son almacenados es f acil tanto de entender
como de editar a mano. (En otras palabras, usted no tiene que usar el comando “hg qguard” si no lo desea; esta bien
simplemente editar el fichero series)
1 $ cat .hg/patches/series2 hello.patch #-quux
3 goodbye.patch #+foo
13.4. Selecccionar los guardias a usar
El comando “hg qselect” determina que guardias estan activos en cualquier momento. El efecto de esto es
determinar que parches aplicara MQ la proxima vez que usted ejecute “hg qpush”. No tiene ningun otro efecto; en
particular, no hace nada a los parches que ya han sido aplicados.
Sin argumentos, el comando “hg qselect” lista los guardias en efecto actualmente, uno por cada l ınea de salida.
Cada argumento es tratado como el nombre de un guardia a aplicar.
1 $ hg qpop -a
2 Patch queue now empty
3 $ hg qselect
4 no active guards
5 $ hg qselect foo
6 number of unguarded, unapplied patches has changed from 1 to 2
7 $ hg qselect
8 foo
Si esta interesado, los guardias seleccionados actualmente estan almacenados en el fichero guards.
1 $ cat .hg/patches/guards
2 foo
Podemos ver el efecto que tienen los guardias seleccionados cuando ejecutamos “ hg qpush”.
1 $ hg qpush -a
2 applying hello.patch
3 applying goodbye.patch
4 Now at: goodbye.patch
162
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 173/204
Un guardia no puede empezar con un caracter “ +” o “-”. El nombre del guardia no debe contener espacios en
blanco, pero muchos otros caracteres son aceptables. Si usted trata de usar un guardia con un nombre inv alido, MQ se
quejara:
1 $ hg qselect +foo
2 abort: guard ’+foo’ starts with invalid character: ’+’
Cambiar los guardias seleccionados cambia los parches que son aplicados.
1 $ hg qselect quux
2 number of guarded, applied patches has changed from 0 to 2
3 $ hg qpop -a
4 Patch queue now empty
5 $ hg qpush -a
6 patch series already fully applied
Usted puede ver en el ejemplo de abajo que los guardias negativos tienen precedencia sobre los guardias positivos.
1 $ hg qselect foo bar
2 number of unguarded, unapplied patches has changed from 0 to 23 $ hg qpop -a
4 no patches applied
5 $ hg qpush -a
6 applying hello.patch
7 applying goodbye.patch
8 Now at: goodbye.patch
13.5. Reglas de MQ para aplicar parches
Las reglas que MQ usa para decidir si debe aplicar un parche son las siguientes.
Un parche sin guardias es aplicado siempre.
Si el parche tiene algun guardia negativo que corresponda con cualquiera de los guardias seleccionados, se salta
el parche.
Si el parche tiene algun guardia positivo que corresponda con cualquiera de los guardias seleccionados, se aplica
el parche.
Si el parche tiene guardias positivos o negativos, pero ninguno corresponde con cualquiera de los guardias
seleccionados, se salta el parche.
13.6. Podar el entorno de trabajo
En el trabajo del controlador de dispositivo que mencione anteriormente, yo no aplico los parches a un arbolnormal del kernel de Linux. En cambio, uso un repositorio que s olo contiene una instantanea de los ficheros fuente y
de cabecera que son relevantes para el desarrollo de Infiniband. Este repositorio tiene un 1 % del tamano del repositorio
del kernel, por lo que es mas f acil trabajar con el.
Luego escojo una version “base” sobre la cual son aplicados los parches. Es una instantanea del arbol del kernel
de Linux en una revision de mi eleccion. Cuando tomo la instantanea, almaceno el ID de conjunto de cambios en el
mensaje de consignacion. Ya que la instantanea preserva la “forma” y el contenido de las partes relevantes del arbol
del kernel, puedo aplicar mis parches sobre mi pequeno repositorio o sobre un arbol normal del kernel.
163
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 174/204
Normalmente, el arbol base sobre el que se aplican los parches deberıa ser una instantanea de un arbol de desarrollo
muy reciente. Esto facilita mucho el desarrollo de parches que puedan ser enviados al arbol oficial con pocas o ninguna
modificacion.
13.7. Dividir el fichero series
Yo categorizo los parches en el fichero series en una serie de grupos logicos. Cada seccion de parches similares
empieza con un bloque de comentarios que describen el proposito de los parches que le siguen.
La secuencia de grupos de parches que mantengo se muestra a continuaci on. El orden de los grupos es importante;
explicare porque luego de que presente los grupos.
El grupo “aceptado”. Son parches que el equipo de desarrollo ha enviado al mantenedor del subsistema Infini-
band, y que el ha aceptado, pero que no estan presentes en la instantanea en la cual esta basada el repositorio
pequeno. Estos son parches de “solo lectura”, presentes unicamente para transformar el arbol en un estado
similar al del repositorio del mantenedor oficial.
El grupo “revisar”. Parches que yo he enviado, pero sobre los que que el mantenedor oficial ha solicitado
modificaciones antes de aceptarlos.
El grupo “pendiente”. Parches que no he enviado al mantenedor oficial, pero que ya estan terminados. Estosparches seran de “solo lectura” por un buen tiempo. Si el mantenedor oficial los acepta cuando los envıe, los
movere al final del grupo “aceptado”. Si el solicita que modificaciones en alguno de ellos, los movere al principio
del grupo “revisar”.
El grupo “en proceso”. Parches que estan siendo activamente desarrollados, y no deberıan ser enviados a ninguna
parte aun.
El grupo “backport”. Parches que adaptan el arbol de fuentes a versiones antiguas del arbol del kernel.
El grupo “no enviar”. Parches que por alguna razon nunca deben ser enviados al mantenedor oficial del kernel.
Por ejemplo, alguno de esos parches podrıa cambiar las cadenas de identificacion embebidas del controlador
para hacer mas facil la distincion, en pruebas de campo, entre una version del controlador de salida-del-arbol y
una version entregada por un vendedor de alguna distribucion.
Ahora volvemos a las razones para ordenar los grupos de parches en esta manera. Quisieramos que los parches del
fondo de la pila sean tan estables como sea posible, para no tener que revisar parches m as arriba debido a cambios de
contexto. Poner los parches que nunca cambiaran en el primer lugar del fichero series sirve a este proposito.
Tambien desearıamos que los parches que sabemos que debemos modificar sean aplicados sobre un arbol de fuentes
que se parezca al oficial tanto como sea posible. Es por esto que mantenemos los parches aceptados disponibles por
una buena cantidad de tiempo.
Los parches “backport” y “no enviar” flotan al final del fichero series. Los parches de backport deben ser aplica-
dos encima de todos los otros parches, y los parches “no enviar” pueden perfectamente quedarse fuera del camino.
13.8. Mantener la serie de parches
En mi trabajo, uso varios guardias para controlar que parches deben ser aplicados.
Los parches “aceptados” son vigilados con accepted. Yo habilito este guardia la mayorıa de las veces. Cuando
aplico los parches sobre un arbol donde los parches ya estan presentes, puedo desactivar este parche, y los
parches que lo siguen se aplicaran sin problemas.
Los parches que estan “terminados”, pero no han sido enviados, no tienen guardias. Si estoy aplicando la pila
de parches a una copia del arbol oficial, no necesito habilitar ningun guardia para obtener un arbol de fuentes
razonablemente seguro.
164
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 175/204
Los parches que necesitan revision antes de ser reenviados tienen el guardia rework.
Para aquellos parches que aun estan bajo desarrollo, uso devel.
Un parche de backport puede tener varios guardias, uno para cada version del kernel a la que aplica. Por ejemplo,
un parche que hace backport de un segmento de codigo a 2.6.9 tendra un guardia 2.6.9.
La variedad de guardias me brinda una flexibilidad considerable para determinar que tipode arbol de fuentes acabare porobtener. En la mayorıa de las situaciones, la seleccion de guardias apropiados es automatizada durante el proceso de
compilacion, pero puedo ajustar manualmente los guardias a usar para circunstancias poco comunes.
13.8.1. El arte de escribir parches de backport
Al usar MQ, escribir un parche de backport es un proceso simple. Todo lo que dicho parche debe hacer es modificar
una seccion de codigo que usa una caracterıstica del kernel que no esta presente en la version anterior del kernel, para
que el controlador siga funcionando correctamente en esa version anterior.
Una meta util al escribir un buen parche de backport es hacer parecer que el c odigo hubiera sido escrito para la
version vieja del kernel que usted tiene como objetivo. Entre menos intrusivo el parche, mas f acil sera entenderlo y
mantenerlo. Si usted esta escribiendo una coleccion de parches de backport para evitar el efecto de “nido de ratas” de
tener muchos #ifdefs (secciones de codigo fuente que solo son usados condicionalmente) en su codigo, no introduzca
#ifdefs dependientes de versiones especıficas en los parches. En vez de eso, escriba varios parches, cada uno de elloshaciendo cambios incondicionales, y controle su aplicacion usando guardias.
Hay dos razones para ubicar los parches de backport en un grupo diferente, aparte de los parches “regulares”
cuyos efectos son modificados por ellos. La primera es que mezclar los dos hace m as dif ıcil usar herramientas como la
extension patchbomb para automatizar el proceso de enviar los parches a un mantenedor oficial. La segunda es que un
parche de backport puede perturbar el contexto en el que se aplica un parche regular subsecuente, haciendo imposible
aplicar el parche normal limpiamente sin que el parche de backport sea aplicado antes.
13.9. Consejos utiles para hacer desarrollo con MQ
13.9.1. Organizar parches en directorios
Si esta trabajando en un proyecto grande con MQ, no es dif ıcil acumular un gran numero de parches. Por ejemplo,tengo un repositorio de parches que contiene mas de 250 parches.
Si usted puede agrupar estos parches en categorıas logicas separadas, usted puede almacenarlos en diferentes
directorios si lo desea; MQ no tiene problemas manejando nombres de parches que contienen separadores de ruta.
13.9.2. Ver el historial de un parche
Si usted esta desarrollando un conjunto de parches en un perıodo de tiempo grande, es una buena idea mantenerlos
en un repositorio, como se discutio en la seccion 12.11. Si lo hace, notara rapidamente que usar el comando “hg diff”
para mirar el historial del repositorio no es viable. Esto es debido en parte a que usted est a mirando la segunda derivada
del codigo real (el diff de un diff), pero tambien porque MQ anade ruido al proceso al modificar las marcas de tiempo
y los nombres de directorio cuando actualiza un parche.
Sin embargo, usted puede usar la extension extdiff, que es provisto junto con Mercurial, para convertir un diff
de dos versiones de un parche en algo legible. Para hacer esto, usted necesitar a un paquete de un tercero llamadopatchutils [Wau]. Este paquete provee un comando llamado interdiff, que muestra las diferencias entre dos diffs
como un diff. Al usarlo en dos versiones del mismo diff, genera un diff que representa el diff de la primera a la segunda
version.
Usted puede habilitar la extension extdiff de la manera usual, anadiendo una lınea a la seccion [extensions]
de su hgrc.
165
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 176/204
1 [extensions]
2 extdiff =
El comando interdiff espera recibir los nombres de dos ficheros, pero la extension extdiff le pasa un par de
directorios al programa que ejecuta, cada uno de los cuales puede contener una cantidad arbitraria de ficheros. Por
esto necesitamos un programa pequeno que ejecute interdiff en cada par de ficheros de estos dos directorios.Este programa esta disponible como hg-interdiff en el directorio examples del repositorio de codigo fuente que
acompana a este libro.
1 #!/usr/bin/env python
2 #
3 # Adapter for using interdiff with mercurial’s extdiff extension.
4 #
5 # Copyright 2006 Bryan O’Sullivan <[email protected]>
6 #
7 # This software may be used and distributed according to the terms of
8 # the GNU General Public License, incorporated herein by reference.
9
10 import os, sys11
12 def walk(base):
13 # yield all non-directories below the base path.
14 for root, dirs, files in os.walk(base):
15 for f in files:
16 path = os.path.join(root, f)
17 yield path[len(base)+1:], path
18 else:
19 if os.path.isfile(base):
20 yield ’’, base
21
22 # create list of unique file names under both directories.
23 files = dict(walk(sys.argv[1]))
24 files.update(walk(sys.argv[2]))
25 files = files.keys()
26 files.sort()
27
28 def name(base, f):
29 if f:
30 path = os.path.join(base, f)
31 else:
32 path = base
33 # interdiff requires two files; use /dev/null if one is missing.
34 if os.path.exists(path):
35 return path
36 return ’/dev/null’
37
38 r e t = 0
39
40 for f in files:
41 if os.system(’interdiff "%s" "%s"’ % (name(sys.argv[1], f),
42 name(sys.argv[2], f))):
166
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 177/204
43 r e t = 1
44
45 sys.exit(ret)
Con el programa hg-interdiff en la ruta de busqueda de su interprete de comandos, puede ejecutarlo como
sigue, desde dentro de un directorio de parches MQ:
1 hg extdiff -p hg-interdiff -r A:B my-change.patch
Ya que usted seguramente querra usar este comando tan largo a menudo, puede hacer que hgext lo haga disponible
como un comando normal de Mercurial, editando de nuevo su hgrc.
1 [extdiff]
2 cmd.interdiff = hg-interdiff
Esto le indica a hgext que ponga a disposicion un comando interdiff, con lo que usted puede abreviar la invocacion
anterior de “hg extdiff” a algo un poco mas manejable.
1 hg interdiff -r A:B my-change.patch
Nota: El comando interdiff trabaja bien solo si los ficheros contra los cuales
son generadas las versiones de un parche se mantienen iguales. Si usted crea un
parche, modifica los ficheros subyacentes, y luego regenera el parche, interdiff
podrıa no producir ningun resultado util.
La extension extdiff es util para mas que solamente mejorar la presentacion de los parches MQ. Para leer mas
acerca de esto, vaya a la seccion 14.2.
167
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 178/204
Capıtulo 14
A ˜ nadir funcionalidad con extensiones
A pesar de que el corazon de Mercurial es muy completo desde el punto de vista de funcionalidad, carece de
caracterısticas rimbombantes deliberadamente. Esta aproximacion de preservar la simplicidad mantiene el programa
sencillo tanto para mantenedores como para usuarios.
Si embargo Mercurial no le cierra las posibilidades a un conjunto inflexible de ordenes: usted puede anadir carac-
terısticas como extensiones (aveces llamadas a˜ nadidos1
). Ya hemos discutido algunas de estas extensiones en capıtulosanteriores:
La seccion 3.3 cubre la extension fetch; que combina jalar cambios y fusionarlos con los cambios locales en
una sola orden: “hg fetch”.
En el capıtulo 10, cubrimos muchas extensiones que son utiles en funcionalidades relacionadas con ganchos:
Los acl anaden listas de control de acceso; bugzilla anade integracion con el sistema de seguimiento de fallos
Bugzilla; y notify envıa notificaciones por correo de nuevos cambios.
La extension de administracion de parches MQ es tan invaluable que amerita dos capıtulos y un apendice por
sı misma. El capıtulo 12 cubre lo basico; el capıtulo 13 discute temas avanzados; y el apendice B muestra en
detalle cada orden.
En este capıtulo cubriremos algunas extensiones adicionales disponibles para Mercurial, y daremos un vistazo a lamaquinaria que necesita conocer en caso de que desee escribir una extension.
En la seccion 14.1, discutiremos la posibilidad de mejorar el desempeno en gran medida con la extension
inotify.
14.1. Mejorar el desempe ˜ no con la extension inotify
¿Desea lograr que las operaciones mas comunmente usadas de Mercurial se ejecuten centenas de veces mas rapido?
¡A leer!
Mercurial tiene gran desempeno bajo circunstancias normales. Por ejemplo, cuando ejecuta la orden “hg status”,
Mercurial tiene que revisar casi todos los ficheros y directorios en su repositorio de forma que pueda desplegar el estado
de los ficheros. Muchas otras ordenes tienen que hacer tal trabajo tras bambalinas; por ejemplo la orden “ hg diff”
usa la maquinaria de estado para evitar hacer operaciones de comparacion costosas en ficheros que obviamente no hancambiado.
Dado que obtener el estado de los ficheros es crucial para obtener buen desempeno, los autores de Mercurial han
optimizado este codigo en la medida de lo posible. Sin embargo, no puede obviarse el hecho de que cuando ejecuta
“hg status”, Mercurial tendra que hacer por lo menos una costosa llamada al sistema por cada fichero administrado
1N. del T. plugins
168
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 179/204
para determinar si ha cambiado desde la ultima vez que se consigno. Para un repositorio suficientemente grande, puede
tardar bastante tiempo.
Para mostrar en numeros la magnitud de este efect, cree un repositorio que contenıa 150.000 ficheros administrador.
Tardo diez segundos para ejecutar “hg status”, a pesar de que ninguno de los ficheros habıa sido modificado.
Muchos sistemas operativos modernos contienen una facilidad de notificacion de ficheros. Si un programa se
registra con un servicio apropiado, el sistema operativo le notificara siempre que un fichero de interes haya sido
creado, modificado o borrado. En sistemas Linux, el componente del nucleo que lo hace se llama inotify.La extension inotify habla con el componente inotify del nucleo para optimizar las ordenes de “hg status”.
La extension tiene dos componentes. Un daemonio esta en el fondo recibiendo notificaciones del subsistema inotify.
Tambien escucha conexiones de una orden regular de Mercurial. La extension modifica el comportamiento de Mercu-
rial de tal forma que, en lugar de revisar el sistema de ficheros, le pregunta al daemonio. Dado que el daemonio tiene
informacion perfecta acerca del estado del repositorio, puede responder instantaneamente con el resultado, evitando la
necesidad de revisar cada directorio y fichero del repositorio.
Retomando los diez segundos que medı al ejecutar la orden “hg status” de Mercurial sobre un repositorio de
150.000 ficheros. Con la extension inotify habilitada, el tiempo se disipo a 0.1 seconds, un factor cien veces mas
rapido.
Antes de continuar, tenga en cuenta algunos detalles:
La extension inotify es especıfica de Linux. Porque se enlaza directamente con el subsistema inotify del
nucleo Linux, no funciona en otros sistemas operativos.
Deberıa funcionar en cualquier distribucion Linux a partir de comienzos del 2005. Las distribuciones mas an-
tiguas deben tener un kernel sin inotify, o una version de glibc que no tiene necesariamente el soporte para
la interfaz.
No todos los sistemas de ficheros pueden usarse con la extension inotify. Los sistemas de ficheros tales como
NFS no lo soportan, por ejemplo, si esta corriendo Mercurial en vaios sistemas, montados todos sobre el mismo
sistema de ficheros en red. El sistema inotify del kernel no tiene forma de saber acerca de los cambios hechos
en otro sistema. La mayorıa de sistemas de ficheros locales (p.e. ext3, XFS, ReiserFS) deberıan funcionar bien.
Hacia mayo de 2007 la extension inotify no venıa de forma predeterminada en Mercurial2, y es un poco mas
compleja de activar que otras extensiones. Pero la mejora en el desempe no bien vale la pena!
La extension venıa en dos partes: un conjunto de parches al codigo fuente de Mercurial, y una librerıa de interfaces
de Python hacia el subsistema inotify.
Nota: Hay dos librerıas de enlace de Python hacia inotify. Una de ellasse llama pyinotify, y en algunas distribuciones de Linux se encuentra como
python-inotify. Esta es la que no necesita, puesto que tiene muchos fallos, y
es ineficiente para ser practica.
Para comenzar, es mejor tener una copia de Mercurial funcional instalada:
Nota: Si sigue las instrucciones a continuacion, esta
biendo cualquier instalacion previa de Mercurial qu
de Mercurial “mas reciente y peligrosa”. No diga qu
1. Clone el repositorio de interfaz entre Python e inotify. Armelo e instalelo:
1 hg clone http://hg.kublai.com/python/inotify
2 cd inotify
3 python setup.py build --force
4 sudo python setup.py install --skip-build
2. Clone el repositorio crew de Mercurial. Clone el repositorio de parches de inotify de forma tal que las colas
de Mercurial puedan aplicar los parches sobre el repositorio crew.
2N. del T. Desde el 2008 para kernels 2.6 viene en Mercurial, pero no esta activada de forma predeterminada
169
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 180/204
1 hg clone http://hg.intevation.org/mercurial/crew
2 hg clone crew inotify
3 hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches
3. Asegurese de instalar la extension Colas de Mercurial mq y que esten habilitadas. Si nunca ha usado MQ, lea la
seccion 12.5 para poder comenzar rapidamente.
4. Vaya al repositorio de inotify y aplique todos los parches de inotify con la opcion -a de la orden “hg
qpush”.
1 cd inotify
2 hg qpush -a
Si obtiene un mensaje de error de “hg qpush”, no deberıa continuar. Mejor pida ayuda.
5. Arme e instale la version parchada de Mercurial.
1 python setup.py build --force
2 sudo python setup.py install --skip-build
Una vez que haya armado una version funcional parchada de Mercurial, todo lo que necesita es habilitar la extension
inotify colocando una entrada en su hgrc.
1 [extensions]
2 inotify =
Cuando la extension inotify este habilitada, Mercurial iniciara transparente y automaticamente el daemonio de es-
tado la primera vez que ejecute un comando que requiera estado del repositorio. Ejecuta un daemonio de estado por
repositorio.
El daemonio de estado se inicia silenciosamente y se ejecuta en el fondo. Si mira a la lista de procesos en ejecucion
despues de habilitar la extension inotify y ejecuta unos pocos comandos en diferentes repositorios, vera que hay
algunos procesos de hg por ahı, esperando actualizaciones del kernel y solicitudes de Mercurial.La primera vez que ejecuta un comando de Mercurial en un repositorio cuando tiene la extensi on inotify ha-
bilitada, correra casi con el mismo desempeno que una orden usual de Mercurial. Esto es debido a que el estado del
daemonio necesita aplicar una busqueda normal sobre el estado para poder tener una lınea de partida frente a la cual
aplicar posteriormente actualizaciones del nucleo. De todas formas, todo comando posterior que haga cualquier clase
de revision del estado deberıa ser notablemente mas rapido en repositorios con incluso un tamano modesto. Aun mejor,
a medida que su repositorio sea mas grande, mejor desempeno vera. El daemonio inotify hace operaciones de estado
de forma casi instantanea en repositorios de todos los tamanos!
Si lo desea, puede iniciar manualmente un daemonio de estado con la orden “hg inserve”. Esto le da un control
un poco mas fino acerca de como deberıa ejecutarse el daemonio. Esta orden solamente estara disponible cuando haya
habilitado la extension inotify.
Cuando este usando la extension inotify, no deberıa ver diferencia en el comportamiento de Mercurial, con
la unica excepcion de que los comandos relacionados con el estado deberıan ejectuarse mucho mas rapido que co-
mo solıan hacerlo. Deberıa esperar especıficamente que las ordenes no deberıan ofrecer salidas distintas; ni ofrecerresultados diferentes. Si alguna de estas situaciones ocurre, por favor reporte el fallo.
14.2. Soporte flexible de diff con la extension extdiff
La orden predeterminada “hg diff” de Mercurial despliega diffs en texto plano unificadas.
170
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 181/204
1 $ hg diff
2 diff -r d6e1fbefacc8 myfile
3 --- a/myfile Tue Feb 10 18:23:22 2009 +0000
4 +++ b/myfile Tue Feb 10 18:23:22 2009 +0000
5 @@ -1,1 +1,2 @@
6 The first line.7 +The second line.
Si dese emplear una herramienta externa para desplegar las modificaciones, querra usar la extension extdiff. Esta le
permitira usar por ejemplo una herramienta grafica de diff.
La extension extdiff viene con Mercurial, y es f acil configurar. En la seccion [extensions] de su hgrc, basta
con anadir una entrada de una lınea para habilitar la extension.
1 [extensions]
2 extdiff =
Esto introduce una orden llamada “hg extdiff”, que de forma predeterminada usa su orden del sistema diff para
generar un diff unificado de la misma forma que lo hace el comando predeterminado “hg diff”.
1 $ hg extdiff
2 --- a.d6e1fbefacc8/myfile 2009-02-10 18:23:22.000000000 +0000
3 +++ /tmp/extdiff83LA2p/a/myfile 2009-02-10 18:23:22.000000000 +0000
4 @@ -1 +1,2 @@
5 The first line.
6 +The second line.
El resultado no sera exactamente el mismo que con la orden interna “hg diff”, puesto que la salida de diff varıa de
un sistema a otro, incluso pasando las mismas opciones.
Como lo indican las lıneas“making snapshot”, la orden “hg extdiff” funciona creando dos instantaneas de
su arbol de fuentes. La primera instantanea es la revision fuente; la segunda es la revision objetivo del directorio
de trabajo. La orden “hg extdiff” genera estas instantaneas en un directorio temporal, pasa el nombre de cada
directorio a un visor de diffs temporal y borra los directorios temporales. Por cuestiones de eficiencia solamentegenera instantaneas de los directorios y ficheros que han cambiado entre dos revisiones.
Los nombres de los directorios de instantaneas tienen los mismos nombres base de su repositorio. Si su repositorio
tiene por ruta /quux/bar/foo, foo sera el nombre de cada instantanea de directorio. Cada instantanea de directorio
tiene sus identificadores de conjuntos de cambios al final del nombre en caso de que sea apropiado. Si una instant anea
viene de la revision a631aca1083f, el directorio se llamara foo.a631aca1083f . Una instantanea del directorio de
trabajo no tendra el identificador del conjunto de cambios, y por lo tanto sera solamente foo en este ejemplo. Para ver
como luce en la practica, veamos de nuevo el ejemplo “hg extdiff” antes mencionado. Tenga en cuenta que los diffs
tienen los nombres de las instantaneas de directorio dentro de su encabezado.
La orden “hg extdiff” acepta dos opciones importantes. La opcion -p le permite elegir un programa para ver las
diferencias, en lugar de diff. Con la opcion -o puede cambiar las opciones que “hg extdiff” pasa a tal programa
(de forma predeterminada las opciones son“-Npru”, que tienen sentido unicamente si esta usando diff). En otros
aspectos, la orden “hg extdiff” actua de forma similar a como lo hace la orden “ hg diff” de Mercurial: usted usa
los mismos nombres de opciones, sintaxis y argumentos para especificar las revisiones y los ficheros que quiere, yası sucesivamente.
Por ejemplo, para ejecutar la orden usual del sistema diff, para lograr que se generen diferencias de contexto
(con la opcion -c) en lugar de diferencias unificadas, y cinco lıneas de contexto en lugar de las tres predeterminadas
(pasando 5 como argumento a la opcion -C).
1 $ hg extdiff -o -NprcC5
2 *** a.d6e1fbefacc8/myfile Tue Feb 10 18:23:22 2009
171
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 182/204
3 --- /tmp/extdiff83LA2p/a/myfile Tue Feb 10 18:23:22 2009
4 ***************
5 *** 1 ****
6 --- 1,2 ----
7 The first line.
8 + The second line.
Es sencillo lanzar unas herramienta usual de diferencias. Para lanzar el visor kdiff3:
1 hg extdiff -p kdiff3 -o ’’
Si su orden para visualizar diferencias no puede tratar con directorios, puede usar un poco de scripting para lograrlo.
Un ejemplo de un script con la extension mq junto con la orden interdiff esta en la seccion 13.9.2.
14.2.1. Definicion de alias de comandos
Acordarse de todas las opciones de las ordenes “hg extdiff” y el visor de diferencias de su preferencia puede
ser dispendioso, y por lo tanto la extension extdiff le permite definir nuevas ordenes que invocaran su visor de
diferencias con las opciones exactas.
Basta con editar su fichero hgrc, y anadir una seccion llamada [extdiff]. Dentro de esta seccion puede definirvarias ordenes. Mostraremos como anadir la orden kdiff3. Despues de definido, puede teclear “hg kdiff3” y la
extension a extdiff ejecutara la orden kdiff3.
1 [extdiff]
2 cmd.kdiff3 =
Si deja vacıa la porcion derecha de la definicion, como en el ejemplo, la extension extdiff usa el nombre de la
orden se definira como el nombre del programa externo a ejecutar. Pero tales nombres no tienen por qu e ser iguales.
Definimos ahora la orden llamada “hg wibble”, que ejecuta kdiff3.
1 [extdiff]
2 cmd.wibble = kdiff3
Tambien puede especificar las opciones predeterminadas con las cuales desea invocar el visor de diferencias. Se
usa el prefijo “opts.”, seguido por el nombre de la orden a la cual se aplican las opciones. En este ejemplos se define
la orden “hg vimdiff” que ejecuta la extension DirDiff del editor vim.
1 [extdiff]
2 cmd.vimdiff = vim
3 opts.vimdiff = -f ’+next’ ’+execute "DirDiff" argv(0) argv(1)’
14.3. Uso de la extension transplant para seleccionar
Need to have a long chat with Brendan about this.
14.4. Enviar cambios vıa correo electronico con la extension patchbomb
Varios proyectos tienen la cultura de “revision de cambios”, en la cual la gente envıa sus modificaciones a una lista
de correo para que otros las lean y comenten antes de consignar la version final a un repositorio compartido. Algunos
proyectos tienen personas que actuan como cancerberos; ellos aplican los cambios de otras personas a un repositorio
para aquellos que no tienen acceso.
172
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 183/204
Mercurial facilita enviar cambios por correo para revision o aplicacion gracias a su extension patchbomb. La
extension es tan popular porque los cambios se formatean como parches y es usual que se envıa un conjunto de
cambios por cada correo. Enviar una gran cantidad de cambios por correos se llama por tanto “bombardear” el buz on
de entrada del destinatario, de ahı su nombre “bombardeo de parches”.
Como es usual, la configuracion basica de la extension patchbomb consta de una o dos lıneas en su hgrc.
1
[extensions]2 patchbomb =
Cuando haya habilitado la extension, dispondra de una nueva orden, llamada “hg email”.
La forma mejor y mas segura para invocar la orden “hg email” es ejecutarla siempre con la opcion -n; que le
mostrara lo que la orden enviarıa, sin enviar nada. Una vez que haya dado un vistazo a los cambios y verificado que
esta enviando los correctos, puede volver a ejecutar la misma orden, sin la opcion -n.
La orden “hg email” acepta la misma clase de sintaxis de revisiones como cualquier otra orden de Mercurial. Por
ejemplo, enviara todas las revisiones entre la 7 y la punta, inclusive.
1 hg email -n 7:tip
Tambien puede especificar un repositorio para comparar. Si indica un repositoro sin revisiones, la orden “ hg email”
enviara todas las revisiones en el repositorio local que no estan presentes en el repositorio remoto. Si especificarevisiones adicionalmente o el nombre de una rama (la ultima con la opcion -b), respetara las revisiones enviadas.
Ejecutar la orden “hg email” sin los nombres de aquellas personas a las cuales desea enviar el correo es comple-
tamente seguro: si lo hace, solicitara tales valores de forma interactiva. (Si esta usando Linux o un sistema tipo Unix,
tendra capacidades estilo–readline aumentadas cuando ingrese tales encabezados, lo cual es sumamente util.)
Cuando envıe una sola revision, la orden “hg email” de forma predeterminada usara la primera lınea de descrip-
cion del conjunto de cambios como el tema del unico mensaje que se enviara.
Si envıa varias revisiones, la orden “hg email” enviara normalmente un mensaje por conjunto de cambios. Colo-
cara como prefacio un mensaje introductorio en el cual usted deberıa describir el proposito de la serie de cambios que
esta enviando.
14.4.1. Cambiar el comportamiento de las bombas de parches
Cada proyecto tiene sus propias convenciones para enviar cambios en un correo electronico; la extension patchbomb
intenta acomodarse a diferentes variaciones gracias a las opciones de la lınea de ordenes:
Puede escribir un tema para el mensaje introductorio en la lınea de ordenes con la opcin -s. Toma un argumento:
el tema del mensaje a usar.
Para cambiar el correo electronico del campo del cual se origina, use la opcion -f. Toma un argumento, el correo
electronico a usar.
El comportamiento predeterminado es enviar diferencias unificadas (consulte la seccion 12.4 si desea una de-
scripcion del formato), una por mensaje. Puede enviar un conjunto binario3 con la opcion -b.
Las diferencias unificadas estan precedidas por un encabezado de metadatos. Puede omitirlo, y enviar diferencias
sin adornos con la opcion --plain.
Las diferencias usualmente se envıan “en lınea”, como parte del cuerpo del mensaje con la descripcion del
parche. Que facilita a a la mayor cantidad de lectores citar y responder partes de un diff, dado que algunos
clientes de correo solamente citaran la primera parte MIME del cuerpo de un mensaje. Si prefiere enviar la
descripcion y el diff en partes separadas del cuerpo, use la opcion -a.
3N. del T. binary bundle
173
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 184/204
En lugar de enviar mensajes de correo puede escribirlos a un fichero con formato- mbox- con la opcion -m. La
opcion recibe un argumento, el nombre del fichero en el cual escribir.
Si desea anadir un resumen con formato-diffstat en cada parche, y uno como mensaje introductorio, use la
opcion -d. La orden diffstat despliega una tabla que contiene el nombre de cada fichero parchado, el numero
de lıneas afectadas, y un historgrama mostrando cuanto ha sido modificado cada fichero. Lo cual ofrece a los
lectores una mirada cuantitativa de cuan complejo es el parche.
174
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 185/204
Apendice A
Referencia de Ordenes
A.1. “hg add”—A ˜ nade ficheros en la proxima consignacion
--include, tambien -I
--exclude, tambien -X--dry-run, tambien -n
A.2. “hg diff”—imprime los cambios en el historial o el directorio actual
Mostrar las diferencias entre revisiones para ficheros especificados o directorios, con el formato unificado diff. Si
desea ver una descripcion del formato unificado diff, ver la seccion 12.4.
De forma predeterminada, esta orden no imprime las diferencias para los ficheros binarios que Mercurial est e sigu-
iendo. Para controlar este comportamiento, vea las opciones -a y --git.
A.2.1. Options
opcion --nodates
Omite la fecha y hora cuando se muestran los encabezados de las diferencias.
--ignore-blank-lines, tambien -B
No imprime los cambios que solamente insertan o eliminan lıneas en blanco. Una lınea que contiene espacios en
blanco no se considera como una lınea en blanco.
--include, tambien -I
Incluye ficheros y directorios cuyos nombres coinciden con los patrones elegidos.
--exclude, tambien -X
Excluye los ficheros y directorios cuyos nombres coinciden con los patrones elegidos.
--text, tambien -a
Si no especifica esta opcion, “hg diff” no mostrara las diferencias de los ficheros que detecte como binarios. Al
especificar -a se forza a “hg diff” a tratar los ficheros como texto, y generar diferencias para todos.
175
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 186/204
Esta opcion es util para los ficherso que son “texto en mayor medida” pero que tienen caracteres NUL. Si lo usa
en ficheros que contienen muchos datos binarios, la salida sera incomprensible.
--ignore-space-change, tambien -b
No imprime si el unico cambio que en la lınea es la cantidad de espacio en blanco.
--git, tambien -g
Mostrar diferencias compatibles con git. XXX reference a format description.
--show-function, tambien -p
Mostrar el nombre de la funcion que contiene elcodigo en una porcion del encabzado usando una heurıstica simple.
Esta funcionalidad se habilita de forma predeterminada, ası que la opcion -p no tiene efectos a menos que cambie el
valor de showfunc en la configuracion, como en el ejemplo siguiente.
1 $ echo ’[diff]’ >> $HGRC
2 $ echo ’showfunc = False’ >> $HGRC
3 $ hg diff
4 diff -r a38a6c74a605 myfile.c
5 --- a/myfile.c Tue Feb 10 18:23:18 2009 +0000
6 +++ b/myfile.c Tue Feb 10 18:23:18 2009 +0000
7 @@ -1,4 +1,4 @@
8 int myfunc()
9 {10 - return 1;
11 + return 10;
12 }13 $ hg diff -p
14 diff -r a38a6c74a605 myfile.c
15 --- a/myfile.c Tue Feb 10 18:23:18 2009 +0000
16 +++ b/myfile.c Tue Feb 10 18:23:18 2009 +0000
17 @@ -1,4 +1,4 @@ int myfunc()
18 int myfunc()
19 {20 - return 1;
21 + return 10;
22 }
--rev, tambien -r
Especifique una o mas revisiones para comparar. La orden “hg diff” acepta hasta dos opciones -r para especificar
las revisiones a comparar.
1. Despliega las diferencias entre la revision padre y del directorio de trabajo.
2. Despliega las diferencias entre el conjunto de cambios especificados y el directorio de trabajo.
3. Despliega las diferencias entre dos conjuntos de cambios especificados.
Puede especificar dos revisiones usando o bien sea las opciones -r o la notacion de rango. Por ejemplo, las dos
especificaciones de revisiones a continuacion son equivalentes:
176
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 187/204
1 hg diff -r 10 -r 20
2 hg diff -r10:20
Cuando especifica dos revisiones, esto tiene significado para Mercurial. Esto significa que “hg diff -r10:20”
producira un diff que transformara los ficheros desde los contenidos en la revision 10 a los contenidos de la revision
20, mientras que “hg diff -r20:10” significa lo opuesto: el diff que transformar ıa los contenidos de los ficheros dela revision 20 a los contenidos de la revision 10. No puede invertir el orden de esta forma si esta haciendo un diff frente
al directorio de trabajo.
--ignore-all-space, tambien -w
A.3. “hg version”—imprime la informacion de version y derechos de re-
produccion
Esta orden despliega la version de Mercurial que esta usando, y su nota de derechos de reproduccion. Hay cuatro
clases de cadenas de version posibles:
La cadena “unknown”. Esta version de Mercurial no fue construida en un repositorio de Mercurial, y no puede
determinar su propia version.
Una cadena numerica corta, tal como “1.1”. Esta es una construccion de una version de Mercurial que se iden-
tifica con una etiqueta especıfica en el repositorio en el cual fue armada (Esto no significa necesariamente que
esta ejecutando una version oficial; alguien pudo haber anadido tal etiqueta a cualquier version del repositorio
en el cual armaron Mercurial).
Una cadena hexadecimal, tal como “875489e31abe”. Esta es una construccion de una revision dada de Mercu-
rial.
Una cadena hexadecimal seguida por una fecha, tal como “ 875489e31abe+20070205 ”. Esta construccion de la
revision de Mercurial fue la construccion de un repositorio que tuvo cambios locales que no han sido consigna-
dos.
A.3.1. Consejos y trucos
¿Por que difieren los resultados de “hg diff” y “hg status”?
Cuando ejecuta la orden “hg status”, vera una lista de ficheros para los cuales Mercurial almacenara cambios la
proxima vez que consigne. Si ejecuta la orden “hg diff”, vera que imprime diferencias solamente para un subconjunto
de los ficheros que “hg status” liste. Hay dos posibles razones para este comportamiento:
La primera es que “hg status” imprime cierta clase de modificaciones que “hg diff” no despliega normalmente.
La orden “hg diff” usualmente despliega diferencias unificadas, las cuales no tienen la habilidad de representar
algunos cambios que Mercurial puede seguir. Lo mas notable es que las diferencias tradicionales no pueden representar
un cambio acerca de la ejecutabilidad de un fichero, pero Mercurial sı almacena esta informacion.
Si usa la opcion --git de “hg diff”, mostrara diferencias compatibles con git que pueden desplegar esta infor-
macion adicional.
La segunda razon posible para que “hg diff” este imprimiendo diferencias para un subconjunto de ficheros delo que muestra “hg status” es que si usted le invoca sin argumento alguno, “ hg diff” imprime diferencias frente
al primer padre del directorio de trabajo. Si ha ejecutado “hg merge” para fusionar dos conjuntos de cambios, pero
no ha consignado aun los resultados de la fusion, su directorio de trabajo tiene dos padres (use “hg parents” para
verlos). Mientras que “hg status” imprime modificaciones relativas a ambos padres despues de una fusion que no
se ha consignado, “hg diff” opera aun relativo solamente al primer padre. Puede lograr que imprima las diferencias
relativas al segundo padre especificando tal padre con la opcion -r. No hay forma de hacer que imprima las diferencias
relativas a los dos padres.
177
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 188/204
Generar diferencias seguras en binarios
Si usa la opcion -a para forzar que Mercurial imprima las diferencias de los ficheros que so o bien “casi comple-
tamente texto” o contienen muchos datos binarios, tales diferencias no pueden aplicarse subsecuentemente a la orden
“hg import” de Mercurial o a la orden patch del sistema.
Si desea generar una diferencia de un fichero binario que es seguro para usarlo como entrada a la orden “ hg
import”, use la opcion “hg diff”–git cuando genere el parche. La orden patch del sistema no puede tratar con
parches binarios.
178
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 189/204
Apendice B
Referencia de las Colas de Mercurial
B.1. Referencia de ordenes MQ
Si desea dar un vistazo a las ordenes que ofrece MQ, use la orden “hg help mq”.
B.1.1. “hg qapplied”—imprimir los parches aplicados
La orden “hg qapplied” imprime la pila actual de parches aplicados. Los parches se imprimen en orden de
antiguedad, primero los mas antiguos y despues los mas recientes, por lo tanto el ultimo parche de la lista es el que
esta en el “tope”.
B.1.2. “hg qcommit”—consignar cambios en la cola del repositorio
La orden “hg qcommit” consigna cualquier cambio sobresaliente en el repositorio .hg/patches. Esta orden so-
lamente funciona si el directorio .hg/patches es un repositorio, p.e. usted creo el directorio con “hg qinit -c” o
ejecuto “hg init” en el directorio despues de correr “hg qinit”.
Esta orden es un atajo para “hg commit --cwd .hg/patches”.
B.1.3. “hg qdelete”—eliminar un parche del fichero series
La orden “hg qdelete” elimina la entrada del fichero series para el parche en el directorio .hg/patches. No
sca el parche si ha sido aplicado. De forma predeterminada no borra el fichero del parche; use la opci on -f para
hacerlo.
Opciones:
-f Elimina el fichero del parche.
B.1.4. “hg qdiff”—imprimir la diferencia del ultimo parche aplicado
La orden “hg qdiff” imprime un diff del parche mas recientemente aplicado. Es equivalente a “hg diff -r-2:-1”.
B.1.5. “hg qfold”—fusionar (“integrar”) varios parches en uno solo
La orden “hg qfold” fusiona muchos parches en el ultimo parche aplicado, de tal forma que el ultimo parche
aplicado es la union de todos los cambios de los parches en cuestion.
Los parches a fusionar no deben haber sido aplicados; “hg qfold” saldra indicando un error si alguno ha sido
aplicado. El orden en el cual los parches se pliegan es significativo; “hg qfold a b” significa “aplique el parche mas
reciente, seguido de a, y seguido de b”.
179
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 190/204
Los comentarios de los parches integrados se colocan al final de los comentarios del parche destino, con cada
bloque de comentarios separado con tres asteriscos (“*”). Se usa la opcion -e para editar el mensaje de consignacion
para el conjunto de cambios/parches despues de completarse el pliegue.
Opciones:
-e Edita el mensaje de consignacion y la descripcion del parche del parche que se ha integrado.
-l Usa los contenidos del fichero dado como el nuevo mensaje de consignacion y descripcion del parche para elparche a integrar.
-m Usa el texto dado como el mensaje de consignacion y descripcion del parche para el parche integrado.
B.1.6. “hg qheader”—desplegar el encabezado/descripcion de un parche
La orden “hg qheader” imprime el encabezado o descripcion de un parche. De forma predeterminada, imprime
el encabezado del ultimo parche aplicado. Si se da un argumento, imprime el encabezado del parche referenciado.
B.1.7. “hg qimport”—importar el parche de un tercero en la cola
La orden “hg qimport” anade una entrada de un parche externo al fichero series y copia el parche en el directorio
.hg/patches. Anade la entrada inmediatamente despues del ultimo parche aplicado, pero no introduce el parche.
Si el directorio .hg/patches es un repositorio, “hg qimport” automaticamente hace un “hg add” del parche
importado.
B.1.8. “hg qinit”—preparar un repositorio para trabajar con MQ
La orden “hg qinit” prepara un repositorio para trabajar con MQ. Crea un directorio llamado .hg/patches.
Opciones:
-c Crea .hg/patches como un repositorio por sı mismo. Tambien crea un fichero .hgignore que ignorara el
fichero status.
Cuando el directorio .hg/patches es un repositorio, las ordenes “hg qimport” y “hg qnew” hacen “hg add”
automaticamente a los parches nuevos.
B.1.9. “hg qnew”—crear un parche nuevo
La orden “hg qnew” crea un parche nuevo. Exige un argumento, el nombre que se usara para tal parche. El parche
recien creado esta vacıo inicialmente. Se anade al fichero series despues del ultimo parche aplicado, y se introduce
en el tope de ese parche.
Si “hg qnew” encuentra ficheros modificados en el directorio de trabajo, rehusara crear un parche nuevo a meos
que se emplee -f la opcion (ver mas adelante). Este comportamiento le permite hacer “hg qrefresh” al ultimo parche
aplicado antes de aplicar un parche nuevo encima de este.
Opciones:
-f Crea un parche nuevo si los contenidos del directorio actual han sido modificados. Cualquier modificaci on
significativa se anade al parche recientemente creado, de tal forma que al finalizar la orden, el directorio de
trabajo no lucira modificado.
-m Usa el texto dado como el mensaje de consignacion. Este texto se almacenara al principio del fichero del parche,
antes de los datos del parche.
B.1.10. “hg qnext”—imprimir el nombre del proximo parche
La orden “hg qnext” imprime el nombre del siguiente parche en el fichero series a continuacion del ultimo
parche aplicado. Este parche serıa el proximo parche a aplicar si se ejecutara la orden “hg qpush”.
180
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 191/204
B.1.11. “hg qpop”—sustraer parches de la pila
La orden “hg qpop” elimina los parches aplicados del tope de la pila de parches aplicados. De forma predetermi-
nada solamente remueve un parche.
Esta orden elimina los conjuntos de cambios que representan los parches sustraıdos del repositorio, y actualiza el
directorio de trabajo para deshacer los efectos de los parches.
Esta orden toma un argumento opcional, que usa como el nombre o el ındice del parche que desea sustraer. Si se da
el nombre, sustraera los parches hasta que el parche nombrado sea el ultimo parche aplicado. Si se da un numero, “hg
qpop” lo trata como un ındice dentro del fichero series, contando desde cero (no cuenta las lıneas vacıas o aquellas
que sean unicamente comentarios). Sustrae los parches hasta que el parche identificado por el ındice sea el ultimo
parche aplicado.
La orden “hg qpop” no lee o escribe parches en el fichero series. “hg qpop” se constituye por tanto en una
forma segura de sustraer un parche del fichero series o un parche que ha eliminado o renombrado completamente.
En los dos ultimos casos, use el nombre del parche tal como lo hizo cuando lo aplico.
De forma predeterminada, la orden “hg qpop” no sustraera parche alguno si el directorio de trabajo ha sido modi-
ficado. Puede modificar este comportamiento con la opcion -f, que revierte todas las modificaciones del directorio de
trabajo.
Opciones:
-a Sustrae todos los parches aplicados. Restaura el repositorio al estado antes de haber aplicado parche alguno.
-f Revertir forzadamente cualquier modificacion del directorio de trabajo cuando se hace sustracciones.
-n Sustraer un parche de la cola dado un nombre.
La orden “hg qpop” elimina una lınea del final del fichero status por cada parche que se sustrae.
B.1.12. “hg qprev”—imprimir el nombre del parche anterior
La orden “hg qprev” imprime el nombre del parche en el fichero series que esta antes del ultimo parche aplicado.
Este se volvera el ultimo parche aplicado si ejecuta “hg qpop”.
B.1.13. “hg qpush”—introducir parches a la pila
La orden “hg qpush” anade parches a la pila. De forma predeterminada anade solamente un parche.
Esta orden crea un conjunto de cambios que representa cada parche aplicado y actualiza el directorio de trabajo
aplicando los efectos de los parches.
Los datos predeterminados cuando se crea un conjunto de cambios corresponde a:
La fecha de consignacion y zona horaria corresponden a la hora actual de la zona. Dado que tales datos se
usan para computar la identidad de un conjunto de cambios, significa que si hace “hg qpop” a un parche y
“hg qpush” de nuevo, el conjunto de cambios que introduzca tendra una identidad distinta a la del conjunto de
cambios que sustrajo.
El autor es el mismo que el predeterminado usado por la orden “hg commit”.
El mensaje de consignacion es cualquier texto del fichero del parche que viene antes del primer encabezado del
diff. Si no hay tal texto, un mensaje predeterminado se sua para identificar el nombre del parche.Su un parche contiene un encabezado de parche de Mercurial (XXX add link), la informacion en el encabezado del
parche tiene precedencia sobre el predeterminado.
Opciones:
-a Introduce todos los parches que no han sido aplicados del fichero series hasta que no haya nada mas para
introducir.
181
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 192/204
-l Anade el nombre del parche al final del mensaje de consignacion
-m Si un parche no se aplica limpiamente, usa la entrada para un parche en otra cola almacenada para computar los
parametros en una fusion de tres, y aplica una fusion de tres fuentes usando la maquinaria usual de Mercurial.
Usa la resolucion de la fusion como el contenido del parche nuevo.
-n Usa la cola mencionada si se esta fusionando en la introduccion.
La orden “hg qpush” lee, pero no modifica el fichero series. Anade al final del fichero “hg status” una lınea
por cada parche que se introduce.
B.1.14. “hg qrefresh”—actualiza el ultimo parche aplicado
La orden “hg qrefresh” actualiza el ultimo parche aplicado. Modifica el parche, elimina el ultimo conjunto de
cambios que represento el parche, y crea un nuevo conjunto de cambios para representar el parche modificado.
La orden “hg qrefresh” busca las siguientes modificaciones:
Los cambios al mensaje de consignacion, p.e. el texto antes del primer encabezado de diff en el fichero del
parche, se replejan en el nuevo conjunto de cambios que representa el parche.
Las modificaciones a los ficheros a los que se les da seguimiento en el directorio de trabajo se a nade al parche.
Los cambios a los ficheros a los que se les da seguimiento con “hg add”, “hg copy”, “hg remove”, o “hg
rename”. Se anaden al parche los ficheros anadidos, copiados y renombrados, mientras que los ficheros elimi-
nados y las fuentes renombradas se eliminan.
Incluso si “hg qrefresh” no detecta cambios, de todas maneras recrea el conjunto de cambios que representa el
cambio. Esto causa que la identidad del conjunto de cambios difiera del conjunto de cambios previo que identific o al
parche.
Opciones:
-e Modificar la descripcion de la consignacion y el parche con el editor de texto preferido.
-m Modificar el mensaje de consignacion y la descripcion del parche con el texto dado.
-l Modificar el mensaje de consignacion y la descripcion del parche con el texto del fichero dado.
B.1.15. “hg qrename”—renombrar un parche
La orden “hg qrename” renombra un parche y cambia la entrada del parche en el fichero series.
Con un argumento sencillo, “hg qrename” renombra el ultimo parche aplicado. Con dos argumentos, renombra el
primer argumento con el segundo.
B.1.16. “hg qrestore”—restaurar el estado almacenado de la cola
XXX No idea what this does.
B.1.17. “hg qsave”—almacena el estado actual de la cola
XXX Likewise.
B.1.18. “hg qseries”—imprime la serie completa de parches
La orden “hg qseries” imprime la serie completa de parches del fichero series. Imprime solamente los nombres
de los parches sin las lıneas en blanco o comentarios. Imprime primero el primero y de ultimo, el ultimo aplicado.
182
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 193/204
B.1.19. “hg qtop”—imprime el nombre del parche actual
“hg qtop” imprime el nombre del ultimo parche aplicado.
B.1.20. “hg qunapplied”—imprimir los parches que aun no se han aplicado
La orden “hg qunapplied” imprime los nombres de los parches del fichero series que todavıa no han sido
aplicados. Los imprime de acuerdo al orden en el cual serıan introducidos.
B.1.21. “hg strip”—remover una revision y sus descendientes
La orden “hg strip” remueve una revision, y todos sus descendientes del repositorio. Deshace los efectos de las
revisiones removidas del repositorio, y actualiza el directorio de trabajo hasta el primer padre de la revision removida.
La orden “hg strip” almacena una copia de segurida de los conjuntos de cambios en un agrupamiento, de forma
tal que puedan ser reaplicados en caso de que se hayan removido por equivocacion.
Opciones:
-b Almacenar conjuntos de cambios no relacionados que se han mezclado con los conjuntos de cambios que estan
en franjas con el agrupamiento de copia de seguridad.
-f Si una rama tiene varias ramas principales remueve todos los frentes. XXX This should be renamed, y usa -fpara desagrupar revisiones cuando hay cambios pendientes.
-n No almacene la copia de seguridad agrupada.
B.2. Referencia de ficheros de MQ
B.2.1. El fichero series
El fichero series contiene una lista de los nombres de todos los parches que MQ puede aplicar. Se representa
como una lista de nombres, uno por l ınea. Se ignora el espacio en blanco al principio y al final.
Las lıneas pueden contener comentario. Un comentario comienza con el caracter “#”, y va hasta el final de la lınea.
Se ignoran las lıneas vacıas y las que solamente contengan comentarios.
En algun momento podrıa editar el fichero series a mano, por tal motivo se admiten comentarios y l ıneas enblanco como se menciono anteriormente. Por ejemplo, puede poner en comentario un parche temporalmente y “ hg
qpush” omitira tal parche cuando los aplique. Tambien puede cambiar el orden en el cual se aplican los parches,
reordenando las entradas en el fichero series.
Tambien es posible colocar el fichero series bajo control de revisiones; tambien es favorable colocar todos los
parches que refiera bajo control de revisiones. Si crea un directorio de parches con la opci on -c de “hg qinit”, esto
se hara automaticamente.
B.2.2. El fichero status
El fichero status contiene los nombres y los hashes de los conjuntos de cambios de todos los parches que MQ ha
aplicado. A diferencia del fichero series, este NO ha sido disenado para ser editado. No deberıa colocar este fichero
bajo el control de revisiones o modificarlo de forma alguna. MQ lo usa estrictamente para administraci on interna.
183
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 194/204
Apendice C
Instalar Mercurial desde las fuentes
C.1. En un sistema tipo Unix
Si usa un sistema tipo Unix que tiene una version suficientemente reciente de Python (2.3 o superior) disponible,
es f acil instalar Mercurial desde las fuentes.
1. Descargue un paquete fuente reciente de http://www.selenic.com/mercurial/download .
2. Descomprımalo:
1 gzip -dc mercurial-version.tar.gz | tar xf -
3. Vaya al directorio fuente y ejecute el guion de instalacion. Esto armara Mercurial y lo instalara en su directorio
casa:
1 cd mercurial-version
2 python setup.py install --force --home=$HOME
Cuando termine la instalacion, Mercurial estara en el subdirectorio bin de su directorio casa. No olvide asegurarse deque este directorio este presente en el camino de busqueda de su interprete de ordenes.
Probablemente necesitara establecer la variable de ambiente PYTHONPATH de tal forma que los ejecutables de Mer-
curial puedan encontrar el resto de los paquetes de Mercurial. Por ejemplo, en mi portatil, la establecıa a /home/bos/lib/pytho
La ruta exacta que usted use dependera de como ha sido construıdo Python en su sistema, pero deberıa ser facil de-
ducirla. Si no esta seguro, mire lo que haya mostrado el script en el paso anterior, y vea donde se instalaron los
contenidos del directorio mercurial se instalaron.
C.2. En Windows
Armar e instalar Mercurial en Windows requiere una variedad de herramientas, cierta suficiencia tecnica y pacien-
cia considerable. Personalmente, no le recomiendo hacerlo si es un “usuario casual”. A menos que intente hacer hacks
a Mercurial, le recomiendo que mejor use un paquete binario.Si esta decidido a construir Mercurial desde las fuentes en Windows, siga el “camino dif ıcil” indicado en el wiki de
Mercurial en http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall , y espere que el proceso
sea realmente un trabajo duro.
184
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 195/204
Apendice D
Licencia de Publicacion Abierta
Version 1.0, 8 Junio de 1999
D.1. Requerimientos en versiones modificadas y no modificadas
Los trabajos bajo Publicacion Abierta pueden reproducirse y distribuirse enteros o en porciones, en cualquier
medio fısico o electronico, siempre y cuando se respeten los terminos de esta licencia, y se incorpore esta licencia o
su referencia (con cualquiera de las opciones elegidas por el autor y el editor) en la reproduccion.
A continuacion mostramos la forma correcta de incorporar por referencia:
Copyright (c) a˜ no por nombre del autor o designado. Este material puede distribuirse solamente bajo los
terminos y condiciones especificados por la Licencia de Publicacion Abierta, v x.y o posterior (la ultima
version disponible esta en http://www.opencontent.org/openpub/ ).
La referencia debe estar seguida inmediatamente por cualquier opcion elegida por el(os) autor(es) y/o editor(es)
del documento (consulte la seccion D.6).
Se permite la redistribucion comercial de los materiales sujetos a la Publicacion Abierta.
Cualquier publicacion en forma estandar de libro (papel) requerira citar al editor y autor original. Los nombres
del editor y el autor apareceran en todas las superficies externas del libro. En todas las superficies externas el nombre
del editor debera aparecer en tamano de la misma medida que el tıtulo del trabajo y sera citado como poseedor con
respecto al tıtulo.
D.2. Derechos de reproduccion
El derecho de reproduccion de cada Publicacion Abierta pertenece al(os) autor(es) o designados.
D.3. Alcance de la licencia
Los terminos de licencia dsecritos aplican a todos los trabajos bajo licencia de publicaci on abierta a menos que se
indique de otra forma en este documento.La simple agregacion de trabajos de Publicacion Abierta o una porcion de trabajos de Publicacion Abierta con otros
trabajos o programas en el mismo medio no causaran que esta licencia se aplique a los otros trabajos. Los agregados
deberan contener una nota que especifique la inclusion de matrial de Publicacion Abierta y una nota de derechos de
reproduccion acorde.
Separabilidad. Si cualquier porcion de esta licencia no es aplicable en alguna jurisdicci on, las porciones restantes
se mantienen.
185
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 196/204
Sin garantıa. Los trabajos de Publicacion Abierta se licencian y ofrecen “como estan” sin garantıa de ninguna
clase, expresa o implıcita, incluyendo, pero no limitados a las garantıas de mercabilidad y adaptabilidad para un
proposito particular o garantıa de no infraccion.
D.4. Requerimientos sobre trabajos modificados
Todas las versiones modificadas de documentos cubiertos por esta licencia, incluyendo traducciones, antologıas,
compilaciones y documentos parciales, deben seguir estos requerimientos:
1. La version modificada debe estar etiquetada como tal.
2. La persona que hace la modificacion debe estar identificada y la modificacion con fecha.
3. El dar credito al autor original y al editor si se requiere de acuerdo a las pr acticas academicas de citas.
4. Debe identificarse el lugar del documento original sin modificacion.
5. No puede usarse el(os) nombre(s) del autor (de los autores) para implicar relacion alguna con el documento
resultante sin el permiso explıcito del autor (o de los autores).
D.5. Recomendaciones de buenas practicas
Adicional a los requerimientos de esta licencia, se solicita a los redistribuidores y se recomienda en gran medida
que:
1. Si esta distribuyendo trabajaos de Publicacion Abierta en copia dura o CD-ROM, envıe una notificacion por
correo a los autores acerca de su intencion de redistribuir por lo menos con treinta dıas antes de que su manuscrito
o el medio se congelen, para permitir a los autores tiempo para proveer documentos actualizados. Esta notifi-
cacion deberıa describir las modificaciones, en caso de que haya, al documento.
2. Todas las modificaciones sustanciales (incluyendo eliminaciones) deben estar marcadas claramente en el docu-
mento o si no descritas en un adjunto del documento.
3. Finalmente, aunque no es obligatorio bajo esta licencia, se considera de buenos modales enviar una copia gratis
de cualquier expresion en copia dura o CD-ROM de un trabajo licenciado con Publicacion Abierta a el(os)
autor(es).
D.6. Opciones de licencia
El(os) autor(es) y/o editor de un documento licenciado con Publicacion Abierta pueden elegir ciertas opciones
anadiendo informacion a la referencia o a la copia de la licencia. Estas opciones se consideran parte de la instancia de
la licencia y deben incluirse con la licencia (o su incorporacion con referencia) en trabajos derivados.
A Prohibir la distribucion de versiones substancialmente modificadas sin el permiso explıcito del(os) autor(es). Se
definen “modificaciones substanciales” como cambios en el contenido semantico del documento, y se excluyen
simples cambios en el formato o correcciones tipograficas.
Para lograr esto, anada la frase “Se prohibe la distribucion de versiones substancialmente modificadas de este
documento sin el permiso explıcito del dueno de los derechos de reproduccion.” a la referencia de la licencia o a la
copia.
186
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 197/204
B Esta prohibido prohibir cualquier publicacion de este trabajo o derivados como un todo o una parte en libros estandar
(de papel) con propositos comerciales a menos que se obtenga un permiso previo del dueno de los derechos de
reproduccion.
Para lograrlo, anada la frase “La distribucion del trabajo o derivados en cualquier libro estandar (papel) se prohibe
a menos que se obtenga un permiso previo del dueno de los derechos de reproduccion.” a la referencia de la licencia
o la copia.
187
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 198/204
Bibliograf ıa
[AG] Jean Delvare Andreas Gruenbacher, Martin Quinson. Patchwork quilt. http://savannah.nongnu.org/
projects/quilt.
[BI] Ronald Oussoren Bob Ippolito. Universal macpython. http://bob.pythonmac.org/archives/2006/04/
10/python-and-universal-binaries-on-mac-os-x/.
[Bro] Neil Brown. wiggle–apply conflicting patches. http://cgi.cse.unsw.edu.au/ ˜neilb/source/
wiggle/.
[Dic] Thomas Dickey. diffstat–make a histogram of diff output. http://dickey.his.com/diffstat/diffstat.html.
[Dus] Andy Dustman. Mysql for python. http://sourceforge.net/projects/mysql-python.
[Gru05] Andreas Gruenbacher. How to survive with many patches (introduction to quilt). http://www.suse.de/
˜agruen/quilt.pdf , June 2005.
[Mas] Chris Mason. mpatch–help solve patch rejects. http://oss.oracle.com/ ˜mason/mpatch/.
[O’S06] Bryan O’Sullivan. Achieving high performance in mercurial. In EuroPython Conference, July 2006. XXX.
[Pyt] Python.org. ConfigParser—configuration file parser. http://docs.python.org/lib/
module-ConfigParser.html.
[RS] GNU Project volunteers Richard Stallman. Gnu coding standards—change logs. http://www.gnu.org/
prep/standards/html_node/Change-Logs.html.
[Tat] Simon Tatham. Putty—open source ssh client for windows. http://www.chiark.greenend.org.uk/
˜sgtatham/putty/.
[Wau] Tim Waugh. patchutils–programs that operate on patch files. http://cyberelk.net/tim/
patchutils/.
188
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 199/204
Indice alfabetico
.hg/hgrc, fichero, 73, 74, 110
.hg/localtags, fichero, 84, 128, 129
.hg/patches.N , directorio, 152
.hg/patches, directorio, 143, 144, 153–155, 178, 179
.hg/store/data, directorio, 36
.hgignore, fichero, 155, 179
.hgrc, fichero, 20, 35
.hgtags, fichero, 83, 84, 128, 129
.orig, fichero, 150
.rej, fichero, 150, 151
.ssh/config, fichero, 69
.ssh, directorio, 67, 68
EMAIL, variable de entorno, 20
HGMERGE, variable de entorno, 31, 33
HGUSER, variable de entorno, 20
HG NODE, variable de entorno, 112, 124
HG PARENT1, variable de entorno, 124
HG PARENT2, variable de entorno, 124
HG SOURCE, variable de entorno, 125
HG URL, variable de entorno, 124, 125
Mercurial.ini, fichero de configuracion, 66
PATH, variable de entorno, 68
PYTHONPATH, variable de entorno, 68, 71, 115, 183acl, extension, 117, 118, 168
acl, gancho, 118
addbreaks, filtro de plantilla, 134
addremove, comando, 52, 149
add, comando, 44, 49–51, 54, 58, 75, 77, 91, 92, 94, 146,
155, 159, 174, 179, 181
opcion --dry-run, 174
opcion --exclude, 174
opcion --include, 174
opcion -I, 174
opcion -n, 174
opcion -X, 174
age, filtro de plantilla, 134annotate, comando, 142, 144, 145
authorized keys, fichero, 67, 68
author, palabra clave de plantilla, 132, 134, 135
filtro domain, 134
filtro email, 134
filtro person, 135
filtro user, 135
backout, comando, 95–102
opcion --merge, 96, 98, 101
opcion -m, 96
basename, filtro de plantilla, 134
bash, comando de sistema, 155
bisect, comando, 102–108
bisect, extension, 2, 142
branches, comando, 86
branches, palabra clave de plantilla, 132
branch, comando, 87, 88
bugzilla, extension, 119–122, 168
bugzilla, gancho, 119, 120
bundle, comando, 126
changegroup, gancho, 109, 112, 125–128
chmod, comando de sistema, 70
clone, comando, 13, 18, 65, 73, 84
opcion -r, 84
commit, comando, 19–21, 30, 41, 49, 52, 86, 112, 116,
117, 153, 155, 158, 178, 180
opcion --addremove, 158
opcion -A, 52
opcion -l, 117opcion -u, 20
commit, gancho, 109, 112, 113, 126, 127, 129
config, comando, 110
convert, comando (extension conver), 10
convert, extension, 10
conver, extension
comando convert, 10
copy, comando, 44, 52–56, 95, 181
opcion --after, 55
cp, comando, 54
cp, comando de sistema, 54
date, filtro de plantilla, 134
date, palabra clave de plantilla, 132, 134, 135filtro age, 134
filtro date, 134
filtro hgdate, 134
filtro isodate, 134, 135
filtro rfc822date, 135
filtro shortdate, 135
189
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 200/204
desc, palabra clave de plantilla, 132, 135
diffstat, comando
opcion -p, 155
diffstat, comando de sistema, 155, 156, 173
diff, comando, 19, 21, 144, 148, 165, 168, 170, 171,
174–178
opcion --exclude, 174opcion --git, 174–176
opcion --ignore-all-space , 176
opcion --ignore-blank-lines , 174
opcion --ignore-space-change , 175
opcion --include, 174
opcion --nodates, 174
opcion --rev, 175
opcion --show-function , 175
opcion --text, 174
opcion -a, 174, 177
opcion -B, 174
opcion -b, 175
opcion -C, 171opcion -c, 171
opcion -g, 175
opcion -I, 174
opcion -N, 148
opcion -p, 175
opcion -r, 148, 175, 176
opcion -w, 176
opcion -X, 174
diff, comando de sistema, 140, 142, 148, 171
domain, filtro de plantilla, 134
email, comando (extension patchbomb), 173
email, comando (extension patchbomb)
opcion --plain, 173opcion -a, 173
opcion -b, 173
opcion -d, 173
opcion -f, 173
opcion -m, 173
opcion -n, 173
opcion -s, 173
email, filtro de plantilla, 134
escape, filtro de plantilla, 134
export, comando, 101
extdiff, comando (extension extdiff), 167, 171, 172
extdiff, comando (extension extdiff)
opcion -o, 171
opcion -p, 171
extdiff, extension, 165–167, 170–172
comando extdiff, 167, 171, 172
extdiff, extension
comando extdiff
opcion-o, 171
opcion-p, 171
fetch, comando, 35
fetch, comando (extension fetch), 168
fetch, extension, 35, 168
comando fetch, 168
ficheros, palabra clave de plantilla, 134
file adds, palabra clave de plantilla, 133file dels, palabra clave de plantilla, 133
files, palabra clave de plantilla, 133
fill68, filtro de plantilla, 134
fill76, filtro de plantilla, 134
filterdiff, comando
opcion --files, 159
opcion --hunks, 159
opcion -i, 158
opcion -x, 158
filterdiff, comando de sistema, 155, 156, 158, 159
firstline, filtro de plantilla, 134
foo, comando, 88
git, comando de sistema, 63, 175, 176grep, comando de sistema, 105, 107
guards, fichero, 162
header, palabra clave de plantilla, 139
heads, comando, 28
help, comando, 12, 13, 143, 178
hg-interdiff, fichero, 166, 167
hgdate, filtro de plantilla, 134
hgext, extension, 167
hgmerge, comando de sistema, 31, 33, 129
hgrc, fichero
seccion acl.allow, 118
seccion acl.deny, 118
seccion acl, 118entrada bundle, 118
entrada pull, 118
entrada push, 118
entrada serve, 118
entrada sources, 118
seccion bugzilla, 119, 121
entrada db, 120
entrada host, 119
entrada notify, 120
entrada password, 120
entrada usermap, 120
entrada user, 120
entrada version, 119
seccion diff
entrada showfunc, 175
seccion extdiff, 172
seccion extensions, 35, 165, 171
seccion hooks, 112
seccion notify, 122
190
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 201/204
entrada config, 122
entrada maxdiff, 123
entrada sources, 123
entrada strip, 122
entrada template, 123
entrada test, 122, 124
seccion uientrada username, 20
entrada verbose, 113
seccion usermap, 120, 122
seccion web, 73, 74, 121, 123
entrada accesslog, 74
entrada address, 74
entrada allow archive, 73
entrada allowpull, 73
entrada baseurl, 121, 123
entrada contact, 73
entrada description, 74
entrada errorlog, 74
entrada ipv6, 74entrada maxchanges, 73
entrada maxfiles, 73
entrada motd, 74
entrada name, 74
entrada port, 74
entrada stripes, 73
entrada style, 73, 74
entrada templates, 74
hgrc, fichero de configuracion, 69, 73, 74, 90, 110–112,
114, 115, 118–122, 131, 165, 167, 170–172
hgweb.cgi, fichero, 70–74
hgweb.config, fichero, 72, 74
hgwebdir.cgi, fichero, 72–74hg, comando de sistema, 68
import, comando, 148, 177
incoming, comando, 22, 65, 110, 131
incoming, gancho, 109, 119, 125–128
init, comando, 155, 178
inotify, extension, 168–170
comando inserve, 170
inserve, comando (extension inotify), 170
interdiff, comando de sistema, 165–167, 172
isodate, filtro de plantilla, 134, 135
kdiff3, comando de sistema, 31, 32, 172
locate, comando, 157
log, comando, 14–18, 20, 21, 82, 83, 87, 88, 96, 131, 132,
142, 153
opcion --patch, 17
opcion --rev, 16, 18
opcion --template, 132, 135
opcion -p, 17
opcion -r, 16, 18
lsdiff comando de sistema, 158
lsdiff, comando de sistema, 156
mercurial.localrepo , modulo
clase localrepository , 115, 124
mercurial.node, modulo
funcion bin, 124
mercurial.ui, moduloclase ui, 115, 124
merge, comando, 29, 35, 40–42, 80, 90, 153, 176
merge, comando de sistema, 33, 34
mpatch, comando de sistema, 151
mq comando de sistema, 155
mq, comando de sistema, 155
mq, extension, 170, 172
comando qapplied, 145, 146, 148, 155, 178
comando qcommit, 155, 178
comando qdelete, 178
comando qdiff, 178
comando qfold, 158, 178
comando qguard, 161, 162comando qheader, 179
comando qimport, 149, 179
comando qinit, 143, 154, 178, 179, 182
comando qnew, 143, 145, 146, 149, 179
comando qnext, 179
comando qpop, 146, 147, 151, 153, 180
comando qprev, 180
comando qpush, 146, 147, 150–153, 158, 162, 170,
179–182
comando qrefresh, 144, 145, 147, 149, 151–153,
156, 158, 179, 181
comando qrename, 181
comando qrestore, 181comando qsave, 152, 181
comando qselect, 162
comando qseries, 145, 146, 148, 153, 181
comando qtop, 155, 156, 182
comando qunapplied, 182
mq, extension
comando qdel
opcion-f, 178
comando qfold
opcion-e, 179
opcion-l, 179
opcion-m, 179
comando qinit
opcion-c, 154, 155, 178, 179, 182
comando qnew
opcion-f, 146, 179
opcion-m, 179
comando qpop
opcion-a, 146, 151, 152, 155, 180
191
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 202/204
opcion-f, 146, 180
opcion-n, 152, 180
comando qpush
opcion-a, 146, 151, 152, 155, 170, 180
opcion-l, 181
opcion-m, 152, 181
opcion-n, 181comando qrefresh
opcion-e, 181
opcion-l, 181
opcion-m, 181
comando qsave
opcion-c, 152
opcion-e, 152
node, palabra clave de plantilla, 133
filtro short, 135
notify, extension, 122–124, 168
obfuscate, filtro de plantilla, 135
outgoing, comando, 24, 131
outgoing, gancho, 109, 110, 126, 127pageant, comando de sistema, 67, 68
parents, comando, 24, 29, 30, 40, 176
parents, palabra clave de plantilla, 133
patchbomb, extension, 165, 172, 173
comando email, 173
patchbomb, extension
comando email
opcion--plain, 173
opcion-a, 173
opcion-b, 173
opcion-d, 173
opcion-f, 173
opcion-m, 173opcion-n, 173
opcion-s, 173
patchutils, paquete, 155, 165
patch comando de sistema, 149
patch, comando
opcion --reverse, 101
opcion -p, 148
patch, comando de sistema, 101, 102, 140, 142, 148–151,
177
perl, comando de sistema, 117
person, filtro de plantilla, 135
plink, comando de sistema, 66, 69
prechangegroup, gancho, 109, 125–128
precommit, gancho, 109, 116, 126–129
preoutgoing, gancho, 109, 112, 126, 127
pretag, gancho, 109, 128, 129
pretxnchangegroup , gancho, 90, 109, 111, 112, 118, 125–
128
pretxncommit, gancho, 109, 111, 113–116, 119, 126–
128
preupdate, gancho, 109, 129
pull, comando, 22–25, 28, 35, 41, 65, 73, 80, 88, 92, 110,
125, 128, 152, 155
opcion -u, 23, 24
push, comando, 25, 80, 125, 126, 128puttygen, comando de sistema, 67
putty, comando de sistema, 67
qapplied, comando (extension mq), 145, 146, 148, 155,
178
qcommit, comando (extension mq), 155, 178
qdelete, comando (extension mq), 178
qdel, comando (extension mq)
opcion -f, 178
qdiff, comando (extension mq), 178
qfold, comando, 178
qfold, comando (extension mq), 158, 178
qfold, comando (extension mq)
opcion -e, 179opcion -l, 179
opcion -m, 179
qguard, comando, 162
qguard, comando (extension mq), 161, 162
qheader, comando (extension mq), 179
qimport, comando (extension mq), 149, 179
qinit, comando, 155, 178
qinit, comando (extension mq), 143, 154, 178, 179, 182
qinit, comando (extension mq)
opcion -c, 154, 155, 178, 179, 182
qnew, comando, 146
qnew, comando (extension mq), 143, 145, 146, 149, 179
qnew, comando (extension mq)opcion -f, 146, 179
opcion -m, 179
qnext, comando (extension mq), 179
qpop, comando, 146, 151, 152, 155
qpop, comando (extension mq), 146, 147, 151, 153, 180
qpop, comando (extension mq)
opcion -a, 146, 151, 152, 155, 180
opcion -f, 146, 180
opcion -n, 152, 180
qprev, comando (extension mq), 180
qpush, comando, 151, 152, 155
qpush, comando (extension mq), 146, 147, 150–153, 158,
162, 170, 179–182
qpush, comando (extension mq)
opcion -a, 146, 151, 152, 155, 170, 180
opcion -l, 181
opcion -m, 152, 181
opcion -n, 181
192
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 203/204
qrefresh, comando (extension mq), 144, 145, 147, 149,
151–153, 156, 158, 179, 181
qrefresh, comando (extension mq)
opcion -e, 181
opcion -l, 181
opcion -m, 181
qrename, comando (extension mq), 181qrestore, comando (extension mq), 181
qsave, comando, 152
qsave, comando (extension mq), 152, 181
qsave, comando (extension mq)
opcion -c, 152
opcion -e, 152
qselect, comando (extension mq), 162
qseries, comando (extension mq), 145, 146, 148, 153,
181
qtop, comando (extension mq), 155, 156, 182
qunapplied, comando (extension mq), 182
remove, comando, 44, 51, 52, 56, 76, 94, 159, 181
opcion --after, 52rename, comando, 44, 55, 56, 80, 95, 181
opcion --after, 56
revert, comando, 52, 58, 93–95, 101, 145
rev, palabra clave de plantilla, 133
rfc822date, filtro de plantilla, 135
rollback, comando, 91, 92, 102
root, comando, 76
sed, comando de sistema, 19
series, fichero, 144, 152, 155, 162, 164, 178–182
serve, comando, 59, 60, 65, 73, 74
opcion -p, 65
shortdate, filtro de plantilla, 135
short, filtro de plantilla, 135ssh-add, comando de sistema, 67, 68
ssh-agent, comando de sistema, 67
ssh-keygen, comando de sistema, 67
ssh, comando
opcion -C, 69
ssh, comando de sistema, 42, 60, 66–69
status, comando, 19, 21, 49, 51–53, 55, 76, 87, 91, 95,
101, 168, 169, 176, 181
opcion -C, 53, 55
status, fichero, 144, 152, 155, 179, 180, 182
strip, comando, 152, 182
opcion -b, 182
opcion -f, 182
opcion -n, 182
strip, filtro de plantilla, 135
sudo apt-get install mercurial-py25, comando de
sistema, 12
sudo port install mercurial, comando de sistema,
12
sudo, comando de sistema, 121
tabindent, filtro de plantilla, 134, 135
tabindent, palabra clave de plantilla, 135
tags, comando, 82, 83
tags, palabra clave de plantilla, 133
tag, comando, 61, 81, 83, 84
opcion -f, 83opcion -l, 84
tag, gancho, 109, 128, 129
tar, comando de sistema, 73
tip, comando, 21, 23, 87, 131, 156
opcion -p, 156
transplant, extension, 172
unbundle, comando, 125, 128
update, comando, 23, 24, 29, 35, 40, 61, 80, 88–90, 101,
152, 155
opcion -C, 88, 152
update, gancho, 110, 129
urlescape, filtro de plantilla, 135
user, filtro de plantilla, 135version, comando, 12, 68, 176
vim, comando de sistema, 172
wiggle, comando de sistema, 151
zip, comando de sistema, 73
Base de datos de fallos de Mercurial
fallo 29, 57
fallo 311, 149
fichero de configuracion
Mercurial.ini (Windows), 66
hgrc (Linux/Unix), 69, 73, 74, 90, 110–112, 114,
115, 118–122, 131, 165, 167, 170–172filtros de plantilla
addbreaks, 134
age, 134
basename, 134
date, 134
domain, 134
email, 134
escape, 134
fill68, 134
fill76, 134
firstline, 134
hgdate, 134
isodate, 134, 135obfuscate, 135
person, 135
rfc822date, 135
shortdate, 135
short, 135
strip, 135
193
7/11/2019 Control Distribuido de Revisiones Con Mercurial
http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 204/204
tabindent, 134, 135
urlescape, 135
user, 135
ganchos
acl, 118
bugzilla, 119, 120changegroup, 109, 112, 125–128
commit, 109, 112, 113, 126, 127, 129
incoming, 109, 119, 125–128
outgoing, 109, 110, 126, 127
prechangegroup, 109, 125–128
precommit, 109, 116, 126–129
preoutgoing, 109, 112, 126, 127
pretag, 109, 128, 129
pretxnchangegroup , 90, 109, 111, 112, 118, 125–
128
pretxncommit, 109, 111, 113–116, 119, 126–128
preupdate 109 129
qtip, 153
variables de entorno
EMAIL, 20
HGMERGE, 31, 33
HGUSER, 20
HG NODE, 112, 124HG PARENT1, 124
HG PARENT2, 124
HG SOURCE, 125
HG URL, 124, 125
PATH, 68
PYTHONPATH, 68, 71, 115, 183