2008-09-24 13 views
71

Soy relativamente nuevo en Mercurial y mi equipo lo está probando en este momento como un reemplazo para Subversion.¿Cuál es la forma más fácil de enviar y enviar un solo archivo dejando otras modificaciones en paz?

¿Cómo puedo enviar y enviar un archivo a otro repositorio sin dejar otras modificaciones en mi directorio de trabajo sin confirmar (o al menos no enviarlas al otro repositorio)?

Esto sucede con las migraciones de bases de datos. Queremos comprometer la migración al control de origen para que un administrador de bases de datos pueda verlo y editarlo mientras trabajamos en las modificaciones del código para que coincidan con la migración de la base de datos. Los cambios aún no están listos para comenzar, así que no queremos expulsarlos a todos.

En la subversión, yo simplemente hago:

svn add my_migration.sql 
# commit only the migration, but not the other files I'm working on 
svn commit -m "migration notes" my_mygration.sql 

y seguir trabajando a nivel local.

Esto no funciona con mercurial como cuando lo estoy sacando al otro repositorio, si hay cambios en él que no he bajado, quiere que los tire hacia abajo, los combine, y comprometer esa fusión al repositorio. Las confirmaciones posteriores a una combinación no le permiten omitir archivos, por lo que le obliga a confirmar todo en su repositorio local.

Lo más fácil que puedo averiguar es enviar el archivo a mi repositorio local, clonar mi repositorio local, buscar cualquier cambio nuevo del repositorio real, fusionarlos y comprometer esa fusión, y estos eliminan mis cambios.

hg add my_migration.sql 
hg commit -m "migration notes" my_migration.sql 
cd .. 
hg clone project project-clone 
cd project-clone 
hg fetch http://hg/project 
hg push http://hg/project 

Esto funciona, pero se siente como que me falta algo más fácil, una cierta manera de indicarle a Mercurial hacer caso omiso de los archivos que ya están en mi directorio de trabajo, acaba de hacer la fusión y enviar los archivos a lo largo. Sospecho que las colas mercuriales pueden hacer esto, pero aún no sé mucho de mq.

Gracias a Josh Matthews a continuación, el comando de archivado es exactamente lo que estoy buscando. No vi ninguna gran instrucciones de instalación con algunas google, así que aquí es la materia combinada utilicé para que funcione:

conseguir con:

hg clone http://freehg.org/u/tksoh/hgshelve/ hgshelve 

El único archivo (actualmente) en el proyecto es el archivo hgshelve.py

Modificar su ~/.hgrc de añadir la extensión estantería, señalando a donde ha clonado el repositorio:

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py 

A continuación, puede hg shelve y hg unshelve para almacenar temporalmente los cambios de distancia. Le permite trabajar en el nivel "parche de parche" para seleccionar y elegir los artículos que desea guardar. No parecía guardar un archivo en la lista para agregar, solo los archivos que ya están en el repositorio con modificaciones.

+1

esta es una característica que realmente valoro en Git (lo uso todo el tiempo), y haría más difícil para mí cambiar ... –

+12

Esto no es realmente cómo haría las cosas ahora que he aprendido mucho más sobre hg. Ahora confirmaría los cambios localmente, actualizaré a la revisión anterior y haré mis cambios allí y "hg push --rev". empujar solo la rama actual. Luego actualice de nuevo al otro trabajo y continúe allí. Si decidiera que ya no quería ese trabajo, simplemente lo "eliminaría". Mucho más fácil y no necesita preocuparse por trozos rechazados de archivos, todo se rastrea y en control de fuente. –

Respuesta

29

Hay una extensión Mercurial que implementa comandos shelve y unshelve, que le brindan una manera interactiva de especificar cambios para almacenar hasta un momento posterior: Shelve.

3

Otra opción si no quiere confiar en las extensiones es mantener un clon de su repositorio de nivel superior localmente que solo utilice para este tipo de tareas de integración.

En su ejemplo, puede simplemente extraer/fusionar su cambio en el repositorio de integración/aguas arriba y enviarlo directamente al servidor remoto.

10

tl; dr: Mi explicación original parece complicada, pero espero que explique completamente cómo usar una cola de parches. Aquí está la versión corta:

$ hg qnew -m "migration notes" -f migration my_migration.sql 
$ hg qnew -f working-code 
# make some changes to your code 
$ hg qrefresh # update the patch with the changes you just made 
$ hg qfinish -a # turn all the applied patches into normal hg commits 

Colas de Mercurial hace que este tipo de cosas una brisa, y se hace más compleja la manipulación de conjuntos de cambios posibles. Vale la pena aprender

En esta situación primero que probablemente querrá para salvar lo que está en el directorio actual antes de tirar abajo los cambios:

# create a patch called migration containing your migration 
$ hg qnew -m "migration notes" -f migration.patch my_migration.sql 
$ hg qseries -v # the current state of the patch queue, A means applied 
0 A migration.patch 
$ hg qnew -f working-code.patch # put the rest of the code in a patch 
$ hg qseries -v 
0 A migration.patch 
1 A working-code.patch 

Ahora vamos a hacer un poco de trabajo adicional en el código de trabajo. Voy a seguir haciendo qseries solo para ser explícito, pero una vez que construyas un modelo mental de colas de parches, no tendrás que seguir mirando la lista.

$ hg qtop # show the patch we're currently editing 
working-code.patch 
$ ...hack, hack, hack... 
$ hg diff # show the changes that have not been incorporated into the patch 
blah, blah 
$ hg qrefresh # update the patch with the changes you just made 
$ hg qdiff # show the top patch's diff 

Debido a que todo el trabajo se guarda en la cola de parche ahora, se puede cancelar la aplicación de esos cambios y restaurarlos después de haber tirado de los cambios remotos. Normalmente para desaplicar todos los parches, solo haga hg qpop -a. Solo para mostrar el efecto sobre la fila de parches, los mostraré uno a la vez.

$ hg qpop # unapply the top patch, U means unapplied 
$ hg qseries -v 
0 A migration.patch 
1 U working-code.patch 
$ hg qtop 
migration.patch 
$ hg qpop 
$ hg qseries -v 
0 U migration.patch 
1 U working-code.patch 

En este punto, es como si no hubiera cambios en su directorio. Haz el hg fetch. Ahora puede volver a activar los cambios en la cola de parches y fusionarlos si hay algún conflicto. Esto es conceptualmente algo similar a la rebase de git.

$ hg qpush # put the first patch back on 
$ hg qseries -v 
0 A migration.patch 
1 U working-code.patch 
$ hg qfinish -a # turn all the applied patches into normal hg commits 
$ hg qseries -v 
0 U working-code.patch 
$ hg out 
migration.patch commit info... blah, blah 
$ hg push # push out your changes 

En este punto, ha expulsado la migración manteniendo sus otros cambios locales. Sus otros cambios están en un parche en la cola. Hago la mayor parte de mi desarrollo personal utilizando una cola de parches para ayudarme a estructurar mejor mis cambios. Si desea deshacerse de la cola de parches y volver a un estilo normal, tendrá que exportar los cambios y volver a importarlos en mercurial "normal".

$ hg qpush 
$ hg qseries -v 
0 A working-code.patch 
$ hg export qtip > temp.diff 
$ rm -r .hg/patches # get rid of mq from the repository entirely 
$ hg import --no-commit temp.diff # apply the changes to the working directory 
$ rm temp.diff 

estoy sumamente adicto a parchear las colas para el desarrollo y mq es una de las mejores implementaciones por ahí. La capacidad de crear varios cambios al mismo tiempo realmente mejora la concentración y la limpieza de sus compromisos. Lleva un tiempo acostumbrarse, pero va increíblemente bien con un flujo de trabajo DVCS.

+0

+1 para la explicación, pero parece * muy * complicado. Compárelo con "git rebase -i", que no requiere reflexión ni configuración, y todavía no veo cómo MQ es una solución viable para el problema del "conjunto de parches limpio" (¡para los mortales!). Parece que tienes que planificar realmente tu flujo de trabajo de todos modos. – richq

+20

No estoy seguro de que me refiriera a un proceso de 20 pasos de líneas de comando oscuras como "una brisa". – Crashworks

+1

jeje, buena llamada. Escribí la breve y dulce respuesta a su solución arriba. – Kobold

38

Han pasado casi 2 años desde que originalmente planteé esta pregunta. Lo haría de manera diferente ahora (como mencioné en un comentario anterior a la pregunta anterior). Lo que haría ahora sería cometer vez mis cambios en el archivo de uno en mi repo local (se puede utilizar la extensión de registro de Hg para cometer solamente piezas de un archivo):

hg commit -m "commit message" filename 

A continuación, sólo desplazados hacia fuera.

hg push 

Si hay un conflicto debido a que otros se han hecho cambios al repositorio que necesito para combinar en primer lugar, me gustaría actualizar a la revisión de los padres (que se ve con "hg parents -r." Si no lo hace saber qué es), cometer mis otros cambios allí, así que tengo 2 cabezas.A continuación, vuelva a la confirmación original de archivo único y tire/fusione los cambios en esa versión. A continuación, elimine los cambios con

hg push --rev . 

Para expulsar solo el archivo único y la fusión de esa revisión. Entonces puedes fusionar las dos cabezas que tienes localmente.

De esta manera se deshace de las cosas de mq y la posibilidad de trozos rechazados y mantiene todo controlado por el control de origen. También puede realizar revisiones de "hg strip" si luego decide que no las quiere.

+1

Esto suena bien. Empiezo a cruzarse cada vez que veo una letra 'q' en cualquier lugar cerca de Mercurial. Es posible que se divierta con 'hg nudge' de Steve Losh: http://hgtip.com/tips/advanced/2009-09-28-nudge-a-gentler-push/ –

2

lo que yo uso generalmente se utilice para cometer un solo archivo:

hg commit -m "commit message" filename 

En este último caso, tengo un conflicto de combinación y todavía no estoy lista para cometer mis cambios, siga estos pasos:

1) Crea un archivo de parche.

hg diff > changes.patch 

2) revertir todos los cambios no confirmados en circulación, solamente después de comprobar su archivo de revisión.

hg revert --all 

3) Tire, actualizar y fusionar a última revisión

hg pull -u 
hg merge 
hg commit -m "local merge" 

4) Ahora simplemente importar su parche atrás y obtener los cambios.

hg import --no-commit changes.patch 

Recuerde utilizar el indicador -no-commit de la confirmación automática de los cambios.

0

Como dijo más fácil, a menudo uso hg commit -i (--interactive) incluso cuando se comprometen archivos completos. Con --interactive puede simplemente seleccionar el/los archivo (s) que desee en lugar de escribir su (s) ruta (s) completa (s) en la línea de comando. Como una ventaja adicional, puede incluso incluir/excluir fragmentos dentro de los archivos.

Y luego tan solo hg push para enviar esa confirmación recientemente creada.

pongo más detalles sobre el uso de hg commit --interactive en esta respuesta: https://stackoverflow.com/a/47931672/255961

Cuestiones relacionadas