¿Puedo aplastar confirmaciones en Mercurial?

109

Tengo un par de confirmaciones que deberían ser solo una. Si estuviera usando git, usaría:

git rebase -i <some-commit-before>

y luego aplastarlos.

¿Puedo hacer eso en mercurial? ¿Si es así, cómo?

R. Martinho Fernandes
fuente

Respuestas:

88

Sí, puede hacer esto usando mercurial sin ninguna extensión mediante la concatenación de conjuntos de cambios .

Alternativamente, si desea usar una extensión, puede usar:

Ry4an Brase
fuente
Sí, saqué esa respuesta de las preguntas falsas que me gustaban en mi comentario sobre la pregunta general. Creo que es tu respuesta a eso.
Ry4an Brase
4
Una pequeña nota al margen: la extensión Histedit se distribuye con Mercurial 2.3 y versiones posteriores. Solo tienes que habilitarlo.
Paidhi
1
En el documento Concatenación de conjuntos de cambios se utilizan conceptos abstractos de "repositorios", ¿cómo puedo hacer referencia a ellos? Por ejemplo: hg -R oldrepo export ... produce "abortar: repositorio oldrepo not found!
Aleksandr Levchuk
13
Solo intento aplastar 2 confirmaciones. ¿Realmente necesito una página wiki con más de 10 comandos o extensiones alternativas?
Aleksandr Levchuk
3
Vea los comentarios. Histedit ahora está integrado, solo necesita habilitarlo (porque ningún comando predeterminado modificará el historial)
Ry4an Brase
43

Mi favorito es el hg strip --keepmando. Y luego realizo todos los cambios en una confirmación.

Es la forma más rápida y cómoda para mí, porque me gusta hacer muchos pequeños compromisos durante mi trabajo diario;)


Nota 1: stripnecesita una extensión incorporada mqpara estar habilitada.
Nota 2: Mi cliente Git / Mercurial favorito (SmartGit / Hg) agrega un --keepparámetro predeterminado durante strip. Y lo que es aún más conveniente: proporciona una opción llamada join commits:]

G. Demecki
fuente
4
El comando completo para hg strip es: hg strip --keep --rev [rev] ¿Dónde revestá el número de revisión de la primera confirmación que desea aplastar con la última
Nicolas Forney
3
@NicolasForney No exactamente, --reves opcional, el comando completo eshg strip --keep [rev]
G. Demecki
La revisión es obligatoria para mí en 3.3.3: hg help stripda hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV..., y omitir la revisión me da abort: empty revision set.
Roman Starkov
3
Usar hg stripno es la mejor idea. No es exactamente seguro. Intente hg histedit, tal vez incluso intente usar la extensión evolucionar.
Martin Thomson
Parece la forma más natural para la gente de git;)
foo
32

La extensión Rebase funcionó a las mil maravillas . Para aplastar 2 confirmaciones:

$ hg rebase --dest .~2 --base . --collapse

Dot es un atajo para la revisión actual.

Es incluso más fácil cuando tiene algunas confirmaciones en una rama y desea colapsarlas todas en una:

$ hg rebase --dest {destination branch (e.g. master)} --base . --collapse

Como funciona esto:

ingrese la descripción de la imagen aquí

(de http://mercurial-scm.org/wiki/RebaseExtension#Collapsing )

Martin Konicek
fuente
1
¿Dónde encontraste el "~ 2" para dos confirmaciones?
Mi-La
1
Se explica en el tema revsets, consulte la ayuda de hg revsets.
marzo y
13

Si está leyendo esta respuesta, puede olvidar todas las demás opciones mencionadas en esta respuesta y usar el foldcomando de la extensión evolucionar .

evolvees una extensión de mercurial que nos ayuda a tener un historial mutable seguro, aunque todavía es experimental. Puede usarlo clonándolo desde su repositorio y agregándolo a su .hgrc de esta manera.

[extensions]
evolve = ~/evolve/hgext/evolve.py

Suponiendo que clonó el repositorio evolucionar en su directorio de inicio. Ahora estás listo para irte. También puede buscar ayuda en hg help fold.

Doblar comando

Le dice folda aplastar / doblar una cadena lineal de confirmaciones que no se rompa. Lo que hace fold es que crea un nuevo conjunto de cambios que contiene los cambios de todos los conjuntos de cambios y marca todas esas confirmaciones como obsoletas. Puede tener una visión más profunda de esto en docs .

Ahora suponga que tiene el siguiente historial.

a -> b -> c -> d -> e -> f -> g

Usted quiere aplastar e, fy g. Tu puedes hacer

hg up g
hg fold -r e

El resultado sera

a -> b -> c -> d -> h

donde hes el conjunto de cambios que contiene los cambios de las tres confirmaciones e, fy g.

También puede plegar conjuntos de cambios desde la mitad del historial, es decir, no necesariamente tiene que elegir una cadena que incluya la punta. Supongamos que usted quiere doblar b, cy d. Tu puedes hacer

hg up d
hg fold -r b
hg evolve --all

Esto resultará en

a -> i -> j

donde ies el conjunto de cambios plegada de b, c, dy jes el mismo de cambios como h. La guía del usuario de Evolve es una lectura obligada.

Pulkit Goyal
fuente
Parece que rebase cubre la mayoría (¿quizás todos?) Los casos de uso de esa extensión, y ciertamente el que se hace en esta pregunta. La característica principal de esa extensión es ocultar (en lugar de eliminar) las revisiones que reemplaza, pero la --keepopción de rebase cubre esto (seguido de marcar las revisiones como secretas o usar una tira en ellas una vez que haya verificado el resultado). Incluso es posible mover revisiones entre otras revisiones con una secuencia de dos comandos de rebase.
Arthur Tacca
... además, si está haciendo algo realmente complicado, siempre puede clonar el repositorio local primero para usarlo como respaldo. Teniendo en cuenta lo raro que es (¡con suerte!), Es menos esfuerzo que aprender a usar una extensión totalmente nueva.
Arthur Tacca
"NameError: el nombre 'execfile' no está definido", lo que significa que evolucionar está escrito en Python 2, que es básicamente la edad de piedra.
Neil G
1
@NeilG mercurial aún no es compatible con Python 3.
Pulkit Goyal
2
@NeilG sí, la comunidad mercurial está trabajando arduamente para obtener soporte para py3 lo antes posible.
Pulkit Goyal
1

Con Mercurial 4.8 (noviembre de 2018, 9 años después), podría considerar el nuevo comando hg absorb(antes era una característica experimental ).

Consulte " Absorción de cambios de compromiso en Mercurial 4.8 "

La extensión absorber tomará cada cambio en su directorio de trabajo, determinará qué confirmaciones en su serie modificaron esa línea y enmendarán automáticamente el cambio en esa confirmación.
Si hay alguna ambigüedad (es decir, varias confirmaciones modificadas en la misma línea), absorber simplemente ignorará ese cambio y lo dejará en su directorio de trabajo para que se resuelva manualmente.

A nivel técnico, hg absorbbusca todos los cambios no confirmados e intenta asignar cada línea modificada a una confirmación anterior inequívoca.
Para cada cambio que se puede asignar de forma limpia, los cambios no confirmados se absorben en la confirmación previa adecuada. Las confirmaciones afectadas por la operación se vuelven a basar automáticamente.
Si un cambio no se puede asignar a una confirmación anterior inequívoca, se deja sin confirmar y los usuarios pueden volver a un flujo de trabajo existente (por ejemplo, usar hg histedit).

La lógica de reescritura automática de hg absorbse implementa siguiendo el historial de líneas: esto es fundamentalmente diferente del enfoque adoptado por hg histedito git rebase, que tienden a depender de estrategias de combinación basadas en la combinación de 3 vías para derivar una nueva versión de un archivo dada una entrada múltiple Versiones

Este enfoque combinado con el hecho de que hg absorber omite cambios con una confirmación de aplicación ambigua significa que hg absorber nunca encontrará conflictos de fusión.

Ahora, puede estar pensando que si ignora las líneas con objetivos de aplicación ambiguos, el parche siempre se aplicaría limpiamente usando una combinación clásica de 3 vías. Esta declaración suena lógicamente correcta. Pero no lo es: hg absorbpuede evitar conflictos de fusión cuando la fusión realizada por hg histedito git rebase -ifallaría.

VonC
fuente
0

Creo que chistedit(integrado desde Mercurial 2.3) es el más cercano a rebase -iMercurial puro ( chistedites la versión interactiva de histedit). Una vez en histedit, el foldcomando se asigna a rebase squashy los rollmapas de comando a rebase fixup. Consulte los documentos histedit para obtener más información.

He aquí un ejemplo sencillo. Suponga que tiene lo siguiente y desea mover todos los cambios de 1e21c4b1 a la revisión anterior y simplemente mantener el mensaje de la revisión anterior.

@  1e21c4b1 drees tip
|  A commit you want to squash
o  b4a738a4 drees
|  A commit
o  788aa028 drees
|  Older stuff

Puede ejecutar hg chistedit -r b4a738a4para editar el historial de nuevo a b4a738a4. En chistedit, luego el cursor hacia abajo hasta 1e21c4b1 y presiona rpara indicar que desea lanzar esa revisión. Tenga en cuenta que el orden en histedit (de más antiguo a más nuevo) se invierte de hg log(más nuevo a más antiguo).

#0  pick   160:b4a738a49916   A commit
#1  ^roll  161:1e21c4b1500c

Después de elegir sus cambios, elige cconfirmarlos. El resultado es el siguiente:

@ bfa4a3be drees tip | Un compromiso de 788aa028 drees | Cosas más antiguas

Si es relativamente nuevo en ellos, entonces histeditpuede ser una mejor opción que chisteditporque proporciona las descripciones de los comandos en el archivo histedit como referencia. Solo se necesita un poco más de edición para configurar los comandos usando la edición de texto normal (al igual que el rebase normal).

Tenga en cuenta que para usar histedito chisteditdebe agregar histedita sus extensiones en su ~ / .hgrc:

[extensions]
histedit =

Sugerí chisteditya que está más cerca rebase -iy funciona en cualquier parte de la historia. Si realmente solo desea subsumir / modificar la revisión actual en la anterior, entonces @G. La stripsugerencia de Demecki puede ser buena ya que lo que está sucediendo es claro. Está construido desde Mercuria 2.8. Para obtener los resultados equivalentes a los anteriores, puede hacer lo siguiente:

hg strip .
hg add
hg commit --amend

Tenga en cuenta que strip, como histedit, debe estar habilitado en su ~ / .hgrc:

[extensions]
strip =
studgeek
fuente
0

Supongamos que desea aplastar (unir) 2 confirmaciones más recientes.

  1. Encuentra un número de revisión

    hg log -G -l 3
    

    posible salida:

    @  changeset:   156:a922d923cf6f
    |  branch:      default
    |  tag:         tip
    |  user:        naXa!
    |  date:        Thu Dec 13 15:45:58 2018 +0300
    |  summary:     commit message 3
    |
    o  changeset:   155:5feb73422486
    |  branch:      default
    |  user:        naXa!
    |  date:        Thu Dec 13 15:22:15 2018 +0300
    |  summary:     commit message 2
    |
    o  changeset:   154:2e490482bd75
    |  branch:      default
    ~  user:        naXa!
       date:        Thu Dec 13 03:28:27 2018 +0300
       summary:     commit message 1
    
  2. Rama de reinicio suave

    hg strip --keep -r 155
    
  3. Confirmar cambios de nuevo

    hg commit -m "new commit message"
    

Notas

striprequiere que se habilite una extensión incorporada. Cree / edite el ~/.hgrcarchivo de configuración con el siguiente contenido:

[extensions]
strip = 
naXa
fuente
-1

Yo suelo:

hg phase --draft --force -r 267
...
hg rebase --dest 282 --source 267 --collapse
Sasha-ch
fuente